update
This commit is contained in:
68
app.c
68
app.c
@@ -1,65 +1,3 @@
|
|||||||
#define DJSTD_BASIC_ENTRY
|
//#include "./scratchpad.c"
|
||||||
#include "core.c"
|
//#include "./server-chat.example.c"
|
||||||
|
#include "./http1-1.example.c"
|
||||||
int djstd_entry(Arena *arena, StringList args) {
|
|
||||||
Socket sock = socketConnect(arena, (SocketConnectInfo){ .address="::1", .port=8080, .blocking=true });
|
|
||||||
|
|
||||||
string newLine = s("\r\n");
|
|
||||||
string lines[] = {
|
|
||||||
s("GET / HTTP/1.1"),
|
|
||||||
s("Host: localhost"),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (EachInArray(lines, i)) {
|
|
||||||
socketWriteStr(&sock, lines[i]);
|
|
||||||
socketWriteStr(&sock, newLine);
|
|
||||||
}
|
|
||||||
socketWriteStr(&sock, newLine);
|
|
||||||
|
|
||||||
CharList body = EmptyList();
|
|
||||||
bool streamingBody = false;
|
|
||||||
|
|
||||||
Forever {
|
|
||||||
StringResult response = socketReadStr(arena, &sock);
|
|
||||||
if (response.valid) {
|
|
||||||
if (streamingBody) {
|
|
||||||
if (body.capacity - body.length >= response.result.length) {
|
|
||||||
memcpy(body.data + body.length, response.result.str, response.result.length);
|
|
||||||
body.length += response.result.length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
StringList lines = strSplit(arena, s("\r\n"), response.result);
|
|
||||||
for (EachEl(lines, string, line)) {
|
|
||||||
if (body.capacity > 0 && strEql(*line, s(""))) {
|
|
||||||
streamingBody = true;
|
|
||||||
} else if (streamingBody && (body.capacity - body.length) >= line->length) {
|
|
||||||
// TODO(dledda): append list to list, string to string, whatever
|
|
||||||
// TODO(dledda): `joinStringList`
|
|
||||||
memcpy(body.data + body.length, line->str, line->length);
|
|
||||||
body.length += line->length;
|
|
||||||
} else {
|
|
||||||
// TODO(dledda): `strContains`
|
|
||||||
// TODO(dledda): `stringContains` -> `strContainsChar`
|
|
||||||
StringList split = strSplit(arena, s("Content-Length: "), *line);
|
|
||||||
if (split.length > 1) {
|
|
||||||
Int32Result lengthResult = parsePositiveInt(split.data[1]);
|
|
||||||
if (lengthResult.valid) {
|
|
||||||
body = PushList(arena, CharList, lengthResult.result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (streamingBody == true && body.length == body.capacity) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dledda): string from CharList/ByteList
|
|
||||||
// TODO(dledda): `printStr`
|
|
||||||
print("%S", (string){.str=body.data, .length=body.length});
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
36
core.c
36
core.c
@@ -176,6 +176,15 @@ string strSlice(string str, size_t start, size_t stop) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string strListJoin(Arena *arena, StringList list) {
|
||||||
|
string result = PushString(arena, 0);
|
||||||
|
for (EachEl(list, string, item)) {
|
||||||
|
PushString(arena, item->length);
|
||||||
|
memcpy(result.str + result.length, item->str, item->length);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
string strSliceCStr(char *data, size_t start, size_t stop) {
|
string strSliceCStr(char *data, size_t start, size_t stop) {
|
||||||
return (string){
|
return (string){
|
||||||
data + start,
|
data + start,
|
||||||
@@ -183,7 +192,7 @@ string strSliceCStr(char *data, size_t start, size_t stop) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stringContains(string str, char c) {
|
bool strContainsChar(string str, char c) {
|
||||||
for (size_t i = 0; i < str.length; i++) {
|
for (size_t i = 0; i < str.length; i++) {
|
||||||
if (str.str[i] == c) {
|
if (str.str[i] == c) {
|
||||||
return true;
|
return true;
|
||||||
@@ -192,9 +201,24 @@ bool stringContains(string str, char c) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool strContains(string str, string search) {
|
||||||
|
if (search.length == 0) return true;
|
||||||
|
if (search.length <= str.length) {
|
||||||
|
for (size_t i = 0; i <= str.length - search.length; i++) {
|
||||||
|
for (size_t j = 0; j < search.length; j++) {
|
||||||
|
if (str.str[i + j] != search.str[j]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j == search.length - 1) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
string NUMERIC_CHARS = s("0123456789");
|
string NUMERIC_CHARS = s("0123456789");
|
||||||
inline bool isNumeric(char c) {
|
inline function bool isNumeric(char c) {
|
||||||
return stringContains(NUMERIC_CHARS, c);
|
return strContainsChar(NUMERIC_CHARS, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringList strSplit(Arena *arena, string splitStr, string inputStr) {
|
StringList strSplit(Arena *arena, string splitStr, string inputStr) {
|
||||||
@@ -288,7 +312,7 @@ Real32Result parsePositiveReal32(string str) {
|
|||||||
StringList getArgs(Arena *arena, int argc, char **argv) {
|
StringList getArgs(Arena *arena, int argc, char **argv) {
|
||||||
StringList args = PushList(arena, StringList, (size_t)argc - 1);
|
StringList args = PushList(arena, StringList, (size_t)argc - 1);
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
AppendList(&args, strFromCString(arena, argv[i]));
|
ListAppend(args, strFromCString(arena, argv[i]));
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
@@ -365,6 +389,10 @@ function void printlnStdout(const char *fmt, ...) {
|
|||||||
void (*print)(const char *fmt, ...) = &printStdout;
|
void (*print)(const char *fmt, ...) = &printStdout;
|
||||||
void (*println)(const char *fmt, ...) = &printlnStdout;
|
void (*println)(const char *fmt, ...) = &printlnStdout;
|
||||||
|
|
||||||
|
void printStr(string str) {
|
||||||
|
print("%S\n", str);
|
||||||
|
}
|
||||||
|
|
||||||
void setStdout() {
|
void setStdout() {
|
||||||
print = &printStdout;
|
print = &printStdout;
|
||||||
println = &printlnStdout;
|
println = &printlnStdout;
|
||||||
|
|||||||
43
core.h
43
core.h
@@ -5,6 +5,7 @@
|
|||||||
#include "stdbool.h"
|
#include "stdbool.h"
|
||||||
#include "stdint.h" // necessary for int type sizes
|
#include "stdint.h" // necessary for int type sizes
|
||||||
#include "time.h" // TODO(djledda): try not to depend on this one
|
#include "time.h" // TODO(djledda): try not to depend on this one
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
// ### Misc macros ###
|
// ### Misc macros ###
|
||||||
#if DJSTDLIB_DEBUG
|
#if DJSTDLIB_DEBUG
|
||||||
@@ -151,6 +152,7 @@ inline function Vec4 vec4(real32 x, real32 y, real32 z, real32 w) {
|
|||||||
#define ListElementSize(list) MemberSizeUnderlying(list, data)
|
#define ListElementSize(list) MemberSizeUnderlying(list, data)
|
||||||
|
|
||||||
DefineList(string, String);
|
DefineList(string, String);
|
||||||
|
DefineList(void, Void);
|
||||||
|
|
||||||
#define PushList(arena, type, size) (type){ .data=pushSize(arena, ListElementSize(type)*(size)), .length=0, .capacity=(size) }
|
#define PushList(arena, type, size) (type){ .data=pushSize(arena, ListElementSize(type)*(size)), .length=0, .capacity=(size) }
|
||||||
#define PushListZero(arena, type, size) (type){ .data=pushSizeFill(arena, ListElementSize(type)*(size), 0), .length=0, .capacity=(size) }
|
#define PushListZero(arena, type, size) (type){ .data=pushSizeFill(arena, ListElementSize(type)*(size), 0), .length=0, .capacity=(size) }
|
||||||
@@ -161,22 +163,37 @@ DefineList(string, String);
|
|||||||
#define __ArrayAsList(array) { .data=(array), .length=ArrayCount(array), .capacity=ArrayCount(array) }
|
#define __ArrayAsList(array) { .data=(array), .length=ArrayCount(array), .capacity=ArrayCount(array) }
|
||||||
#define AsList(listtype, ...) (listtype)__ArrayAsList(((listtype##_underlying[])__VA_ARGS__))
|
#define AsList(listtype, ...) (listtype)__ArrayAsList(((listtype##_underlying[])__VA_ARGS__))
|
||||||
|
|
||||||
// TODO(dledda): clone list
|
#define ListAppend(list, element) \
|
||||||
// TODO(dledda): list back element accessor
|
if ((list).length < (list).capacity) { \
|
||||||
#define AppendList(list, element) \
|
(list).data[(list).length++] = (element); \
|
||||||
if ((list)->length < (list)->capacity) { \
|
|
||||||
(list)->data[(list)->length++] = (element); \
|
|
||||||
}
|
}
|
||||||
#define ZeroListFull(list) memset((list)->data, 0, (list)->length * sizeof((list)->data[0]))
|
#define ZeroListFull(list) memset((list)->data, 0, (list)->length * sizeof((list)->data[0]))
|
||||||
#define ZeroList(list) (list)->length = 0; \
|
#define ZeroList(list) (list)->length = 0; \
|
||||||
memset((list)->data, 0, (list)->length * sizeof((list)->data[0]))
|
memset((list)->data, 0, (list)->length * sizeof((list)->data[0]))
|
||||||
|
/** 1 indicates last element, 2 second last, etc. */
|
||||||
|
#define ListGetFromEnd(list, count) ((list).data[(list).length - (count)])
|
||||||
|
#define ListLast(list) ListGetFromEnd(list, 1)
|
||||||
|
|
||||||
|
inline VoidList __cloneList(Arena *arena, VoidList list, size_t underlyingSize) {
|
||||||
|
byte *newData = PushArrayZero(arena, void, list.capacity*underlyingSize);
|
||||||
|
memcpy(newData, list.data, list.capacity*underlyingSize);
|
||||||
|
return (VoidList){
|
||||||
|
.data=newData,
|
||||||
|
.capacity=list.capacity,
|
||||||
|
.length=list.length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#define CloneList(arena, type, list) (type)cloneList((arena), (VoidList)(list), (MemberSizeUnderlying(list)))
|
||||||
|
#define ListAppendList(appendee, list)\
|
||||||
|
if ((appendee).capacity - (appendee).length >= list.length) {\
|
||||||
|
memcpy((appendee).data + (appendee).length, (list).data, MemberSizeUnderlying(list)*(list).length);\
|
||||||
|
(appendee).length += (list).length;\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Following two macros do not use pointers due to copying
|
// Following two macros do not use pointers due to copying
|
||||||
#define ListSlice(list, start, stop) {\
|
#define ListSlice(list, start, stop) {\
|
||||||
.data= (stop > (list).length || start > stop) ? 0 : (list).data + start,\
|
.data= (stop > (list).length || start > stop) ? 0 : (list).data + start,\}
|
||||||
.length=(stop > (list).length || start > stop) ? 0 : stop - start,\
|
|
||||||
.capacity=(stop > (list).length || start > stop) ? 0 : stop - start,\
|
|
||||||
}
|
|
||||||
#define ListTail(list, start) ListSlice(list, start, (list).length)
|
#define ListTail(list, start) ListSlice(list, start, (list).length)
|
||||||
|
|
||||||
#define ListRemove(list, index)\
|
#define ListRemove(list, index)\
|
||||||
@@ -196,6 +213,7 @@ struct string {
|
|||||||
#define s(lit) ((string){(char *)(lit), sizeof(lit) - 1})
|
#define s(lit) ((string){(char *)(lit), sizeof(lit) - 1})
|
||||||
#define PushString(arena, length) ((string){ (char *)pushSize(arena, length), (length) })
|
#define PushString(arena, length) ((string){ (char *)pushSize(arena, length), (length) })
|
||||||
#define PushStringFill(arena, length, characterByte) ((string){ (char *)pushSizeFill(arena, length, characterByte), (length) })
|
#define PushStringFill(arena, length, characterByte) ((string){ (char *)pushSizeFill(arena, length, characterByte), (length) })
|
||||||
|
#define StrFromList(list) ((string){.str=(list).data,.length=(list).length})
|
||||||
|
|
||||||
// C Strings
|
// C Strings
|
||||||
DefineList(char, Char);
|
DefineList(char, Char);
|
||||||
@@ -206,7 +224,8 @@ string strFromCString(Arena *arena, const char *str);
|
|||||||
|
|
||||||
bool strEql(string s1, string s2);
|
bool strEql(string s1, string s2);
|
||||||
bool strStartsWith(string str, string testStr);
|
bool strStartsWith(string str, string testStr);
|
||||||
bool stringContains(string str, char c);
|
bool strContainChar(string str, char c);
|
||||||
|
bool strContains(string a, string b);
|
||||||
|
|
||||||
string strReverse(Arena *arena, string str);
|
string strReverse(Arena *arena, string str);
|
||||||
string strSlice(string str, size_t start, size_t stop);
|
string strSlice(string str, size_t start, size_t stop);
|
||||||
@@ -215,6 +234,8 @@ StringList strSplit(Arena *arena, string splitStr, string inputStr);
|
|||||||
string strPrintfv(Arena *arena, const char *fmt, va_list args);
|
string strPrintfv(Arena *arena, const char *fmt, va_list args);
|
||||||
string strPrintf(Arena *arena, const char *fmt, ...);
|
string strPrintf(Arena *arena, const char *fmt, ...);
|
||||||
|
|
||||||
|
string strListJoin(Arena *arena, StringList list);
|
||||||
|
|
||||||
#define DefineResult(type, prefix) \
|
#define DefineResult(type, prefix) \
|
||||||
typedef struct prefix ## Result prefix ## Result;\
|
typedef struct prefix ## Result prefix ## Result;\
|
||||||
struct prefix ## Result {\
|
struct prefix ## Result {\
|
||||||
@@ -303,8 +324,10 @@ typedef enum {
|
|||||||
#define COLOR_TEXT_RGB(text, red, green, blue) ANSI_INSTRUCTION_STR("38;2;" #red ";" #green ";" #blue) text ANSI_RESET
|
#define COLOR_TEXT_RGB(text, red, green, blue) ANSI_INSTRUCTION_STR("38;2;" #red ";" #green ";" #blue) text ANSI_RESET
|
||||||
|
|
||||||
DefineList(int, Int);
|
DefineList(int, Int);
|
||||||
|
|
||||||
void printIntList(IntList l);
|
void printIntList(IntList l);
|
||||||
void printStrList(StringList l);
|
void printStrList(StringList l);
|
||||||
|
void printStr(string str);
|
||||||
void setStdout();
|
void setStdout();
|
||||||
void setStderr();
|
void setStderr();
|
||||||
extern void (*print)(const char *fmt, ...);
|
extern void (*print)(const char *fmt, ...);
|
||||||
|
|||||||
62
http1-1.example.c
Normal file
62
http1-1.example.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#define DJSTD_BASIC_ENTRY
|
||||||
|
#include "core.c"
|
||||||
|
|
||||||
|
int djstd_entry(Arena *arena, StringList args) {
|
||||||
|
Socket sock = socketConnect(arena, (SocketConnectInfo){
|
||||||
|
.address="dlh.mediasuite.zii.aero",
|
||||||
|
.port=443,
|
||||||
|
.blocking=true
|
||||||
|
});
|
||||||
|
|
||||||
|
println("%d", sock.closed);
|
||||||
|
string newLine = s("\r\n");
|
||||||
|
string lines[] = {
|
||||||
|
s("GET / HTTP/1.1"),
|
||||||
|
s("Host: localhost"),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (EachInArray(lines, i)) {
|
||||||
|
socketWriteStr(&sock, lines[i]);
|
||||||
|
socketWriteStr(&sock, newLine);
|
||||||
|
}
|
||||||
|
socketWriteStr(&sock, newLine);
|
||||||
|
|
||||||
|
StringList body = EmptyList();
|
||||||
|
bool streamingBody = false;
|
||||||
|
|
||||||
|
Forever {
|
||||||
|
StringResult response = socketReadStr(arena, &sock);
|
||||||
|
if (response.valid) {
|
||||||
|
if (streamingBody) {
|
||||||
|
if (body.capacity - body.length >= response.result.length) {
|
||||||
|
ListAppend(body, response.result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
StringList lines = strSplit(arena, s("\r\n"), response.result);
|
||||||
|
for (EachEl(lines, string, line)) {
|
||||||
|
if (body.capacity > 0 && strEql(*line, s(""))) {
|
||||||
|
streamingBody = true;
|
||||||
|
} else if (streamingBody && (body.capacity - body.length) >= line->length) {
|
||||||
|
ListAppend(body, *line);
|
||||||
|
} else {
|
||||||
|
StringList split = strSplit(arena, s("Content-Length: "), *line);
|
||||||
|
if (split.length > 1) {
|
||||||
|
Int32Result lengthResult = parsePositiveInt(split.data[1]);
|
||||||
|
if (lengthResult.valid) {
|
||||||
|
body = PushList(arena, StringList, lengthResult.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streamingBody == true && body.length == body.capacity) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printStr(strListJoin(arena, body));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "sys/epoll.h"
|
#include "sys/epoll.h"
|
||||||
#include "sys/socket.h"
|
#include "sys/socket.h"
|
||||||
#include "arpa/inet.h"
|
#include "arpa/inet.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
void *os_alloc(uint64 capacity) {
|
void *os_alloc(uint64 capacity) {
|
||||||
@@ -226,7 +227,7 @@ Socket *serverAccept(Server *s) {
|
|||||||
epoll_ctl(((EPollServerEvents *)s->events)->epollFd, EPOLL_CTL_ADD, clientSockHandle, &event);
|
epoll_ctl(((EPollServerEvents *)s->events)->epollFd, EPOLL_CTL_ADD, clientSockHandle, &event);
|
||||||
|
|
||||||
if (s->clients.length < s->clients.capacity) {
|
if (s->clients.length < s->clients.capacity) {
|
||||||
AppendList(&s->clients, ((Socket){
|
ListAppend(s->clients, ((Socket){
|
||||||
.handle=(SocketHandle *)(uint64)clientSockHandle,
|
.handle=(SocketHandle *)(uint64)clientSockHandle,
|
||||||
.address=(Address *)clientAddr,
|
.address=(Address *)clientAddr,
|
||||||
}));
|
}));
|
||||||
@@ -280,7 +281,7 @@ ServerEvent *serverGetNextEvent(Server *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (serverEvents->userEvents.length == 0) {
|
if (serverEvents->userEvents.length == 0) {
|
||||||
AppendList(&serverEvents->userEvents, (ServerEvent){ .type=ServerEventType_None });
|
ListAppend(serverEvents->userEvents, (ServerEvent){ .type=ServerEventType_None });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop next event
|
// Pop next event
|
||||||
@@ -354,10 +355,10 @@ Socket socketConnect(Arena *arena, SocketConnectInfo info) {
|
|||||||
Socket result = {
|
Socket result = {
|
||||||
.handle=(SocketHandle *)(uint64)socketFd,
|
.handle=(SocketHandle *)(uint64)socketFd,
|
||||||
.address=(Address *)remoteAddr,
|
.address=(Address *)remoteAddr,
|
||||||
.closed=false,
|
.closed=connectErr == -1,
|
||||||
//.closed=connectErr == -1,
|
|
||||||
// TODO(dledda): investigate error behaviour
|
// TODO(dledda): investigate error behaviour
|
||||||
};
|
};
|
||||||
|
perror("errconn");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
6
scratchpad.c
Normal file
6
scratchpad.c
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#define DJSTD_BASIC_ENTRY
|
||||||
|
#include "core.c"
|
||||||
|
|
||||||
|
int djstd_entry(Arena *arena, StringList args) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user