diff --git a/http/http_response.c b/http/http_response.c
index 7feb726..1e8a8b0 100644
--- a/http/http_response.c
+++ b/http/http_response.c
@@ -75,7 +75,8 @@ s_http_response * http_response_buf_parse (s_http_response *response,
goto ok;
if (content_length < 0)
goto restore;
- if (! buf_read(buf, content_length, &tmp.body))
+ tmp.body.type = TAG_STR;
+ if (! buf_read(buf, content_length, &tmp.body.data.str))
goto restore;
ok:
buf_save_clean(buf, &save);
@@ -95,13 +96,16 @@ sw http_response_buf_write (const s_http_response *response,
s_str content_length_str = {0};
s_tag default_messages = {0};
s_ident ident = {0};
+ s_buf *in;
s_tag *key = NULL;
const s_list *l = NULL;
s_str protocol = {0};
sw r = 0;
sw result = 0;
+ s_str str;
s_tag tag_code = {0};
s_tag tag_message = {0};
+ const s_sym *type;
s_tag *value = NULL;
assert(response);
assert(buf);
@@ -195,14 +199,16 @@ sw http_response_buf_write (const s_http_response *response,
result += r;
l = list_next(l);
}
- if (content_length < 0) {
+ if (content_length < 0 &&
+ response->body.type == TAG_STR) {
if ((r = buf_write_str(buf, &content_length_str)) < 0)
return r;
result += r;
if ((r = buf_write_1(buf, ": ")) < 0)
return r;
result += r;
- if ((r = buf_inspect_uw_decimal(buf, &response->body.size)) < 0)
+ if ((r = buf_inspect_uw_decimal(buf,
+ &response->body.data.str.size)) < 0)
return r;
result += r;
if ((r = buf_write_1(buf, "\r\n")) < 0)
@@ -213,8 +219,30 @@ sw http_response_buf_write (const s_http_response *response,
return r;
result += r;
if (send_body) {
- if ((r = buf_write_str(buf, &response->body)) < 0)
- return r;
+ if (! tag_type(&response->body, &type))
+ return -1;
+ if (type == &g_sym_Str) {
+ if ((r = buf_write_str(buf, &response->body.data.str)) < 0)
+ return r;
+ }
+ else if (type == &g_sym_Buf) {
+ in = response->body.data.struct_.data;
+ while (buf_refill(in, in->size) > 0) {
+ err_inspect_buf(in);
+ if (! buf_read_to_str(in, &str))
+ return -1;
+ err_inspect_str(&str);
+ if ((r = buf_write(buf, str.ptr.pchar, str.size)) <= 0)
+ return r;
+ str_clean(&str);
+ }
+ }
+ else {
+ err_write_1("http_response_buf_write: unknown body type: ");
+ err_inspect_sym(&type);
+ err_write_1("\n");
+ return -1;
+ }
result += r;
}
return result;
diff --git a/http/types.h b/http/types.h
index c2460f0..390bf1b 100644
--- a/http/types.h
+++ b/http/types.h
@@ -46,7 +46,7 @@ struct http_response {
u16 code;
s_str message;
s_list *headers;
- s_str body;
+ s_tag body;
};
#endif /* HTTP_TYPES_H */
diff --git a/lib/kc3/0.1/file.kc3 b/lib/kc3/0.1/file.kc3
index ff42a05..a35830f 100644
--- a/lib/kc3/0.1/file.kc3
+++ b/lib/kc3/0.1/file.kc3
@@ -1,5 +1,7 @@
defmodule File do
+ def close = cfn Void "file_close" (Tag)
+
def exists? = cfn Bool "file_exists" (Str, Result)
def ext = cfn Str "file_ext" (Str, Result)
@@ -15,6 +17,10 @@ defmodule File do
def list = cfn List "file_list" (Str, Result)
+ def open_r = cfn Buf "file_open_r" (Str, Result)
+
+ def open_w = cfn Buf "file_open_w" (Str, Result)
+
def stat = cfn File.Stat "file_stat" (Str, Result)
def read = cfn Str "file_read" (Str, Result)
diff --git a/lib/kc3/0.1/http/response.kc3 b/lib/kc3/0.1/http/response.kc3
index a72ca1e..5f053df 100644
--- a/lib/kc3/0.1/http/response.kc3
+++ b/lib/kc3/0.1/http/response.kc3
@@ -4,7 +4,7 @@ defmodule HTTP.Response do
code: (U16) 200,
message: "",
headers: [{"Content-Type", "text/html"}],
- body: ""]
+ body: ?]
dlopen(__DIR__ + "../http.so")
diff --git a/lib/kc3/0.1/httpd.kc3 b/lib/kc3/0.1/httpd.kc3
index 3a5d454..cb7355f 100644
--- a/lib/kc3/0.1/httpd.kc3
+++ b/lib/kc3/0.1/httpd.kc3
@@ -144,9 +144,11 @@ defmodule HTTPd do
ext = File.ext(request.url)
path = root_dir + request.url
if File.exists?(path) do
- body = File.read(path)
mime = HTTP.mime_type(ext)
- headers = [{"Content-Type", (Str) mime}]
+ stat = File.stat(path)
+ headers = [{"Content-Type", (Str) mime},
+ {"Content-Length", (Str) stat.st_size} ]
+ body = File.open_r(path)
%HTTP.Response{body: body, headers: headers}
else
error_404_page(request)
diff --git a/libkc3/buf_file.c b/libkc3/buf_file.c
index 063e4a5..378d420 100644
--- a/libkc3/buf_file.c
+++ b/libkc3/buf_file.c
@@ -35,7 +35,7 @@ void buf_file_close (s_buf *buf)
buf->user_ptr = NULL;
}
-bool buf_file_is_open (s_buf *buf)
+bool buf_file_is_open (const s_buf *buf)
{
s_buf_file *buf_file;
assert(buf);
@@ -47,6 +47,16 @@ bool buf_file_is_open (s_buf *buf)
return false;
}
+FILE * buf_file_fp (const s_buf *buf)
+{
+ s_buf_file *buf_file;
+ assert(buf);
+ if (! buf->user_ptr)
+ return NULL;
+ buf_file = (s_buf_file *) buf->user_ptr;
+ return buf_file->fp;
+}
+
s_buf * buf_file_open_r (s_buf *buf, FILE *fp)
{
s_buf_file *buf_file;
diff --git a/libkc3/buf_file.h b/libkc3/buf_file.h
index 9788811..9ebff27 100644
--- a/libkc3/buf_file.h
+++ b/libkc3/buf_file.h
@@ -20,10 +20,11 @@
#include <stdio.h>
#include "types.h"
-/* observers */
-bool buf_file_is_open (s_buf *buf);
+/* Observers. */
+bool buf_file_is_open (const s_buf *buf);
+FILE * buf_file_fp (const s_buf *buf);
-/* modifiers */
+/* Modifiers. */
s_buf * buf_file_open_r (s_buf *buf, FILE *fp);
s_buf * buf_file_open_w (s_buf *buf, FILE *fp);
void buf_file_close (s_buf *buf);
diff --git a/libkc3/facts_spec.c b/libkc3/facts_spec.c
index aa001ca..6e0b344 100644
--- a/libkc3/facts_spec.c
+++ b/libkc3/facts_spec.c
@@ -33,13 +33,13 @@ uw facts_spec_count_facts (p_facts_spec spec)
p_facts_spec facts_spec_new_expand (p_facts_spec spec)
{
uw count;
+ s_facts_spec_cursor cursor;
+ s_fact fact;
+ p_facts_spec new;
+ p_facts_spec n;
assert(spec);
count = facts_spec_count_facts(spec);
if (count > 0) {
- s_facts_spec_cursor cursor;
- s_fact fact;
- p_facts_spec new;
- p_facts_spec n;
new = alloc((count * 4 + 1) * sizeof(s_tag *));
if (! new)
return NULL;
diff --git a/libkc3/file.c b/libkc3/file.c
index fc1460d..1452d23 100644
--- a/libkc3/file.c
+++ b/libkc3/file.c
@@ -29,6 +29,7 @@
#include "list.h"
#include "str.h"
#include "sym.h"
+#include "tag.h"
#include "time.h"
#include "config.h"
@@ -58,6 +59,34 @@ bool file_access (const s_str *path, const s_sym *mode)
return ! access(path->ptr.pchar, m);
}
+void file_close (const s_tag *tag)
+{
+ s_buf_rw *buf_rw;
+ FILE *fp;
+ const s_sym *type;
+ if (! tag_type(tag, &type))
+ return;
+ if (type == &g_sym_Buf) {
+ fp = buf_file_fp(tag->data.struct_.data);
+ buf_file_close(tag->data.struct_.data);
+ fclose(fp);
+ }
+ else if (type == &g_sym_BufRW) {
+ buf_rw = tag->data.struct_.data;
+ fp = buf_file_fp(buf_rw->r);
+ buf_file_close(buf_rw->r);
+ fclose(fp);
+ fp = buf_file_fp(buf_rw->w);
+ buf_file_close(buf_rw->w);
+ fclose(fp);
+ }
+ else {
+ err_write_1("file_close: unknown tag type: ");
+ err_inspect_sym(&type);
+ err_write_1("\n");
+ }
+}
+
sw file_copy (const char *from, const char *to)
{
char buf[4096];
@@ -224,6 +253,71 @@ FILE * file_open (const char *path, const char *mode)
return fp;
}
+s_buf * file_open_r (const s_str *path, s_buf *dest)
+{
+ FILE *fp;
+ s_buf tmp;
+ assert(path);
+ assert(dest);
+ fp = file_open(path->ptr.pchar, "rb");
+ if (! fp)
+ return NULL;
+ if (! buf_init_alloc(&tmp, BUF_SIZE)) {
+ fclose(fp);
+ return NULL;
+ }
+ if (! buf_file_open_r(&tmp, fp)) {
+ buf_clean(&tmp);
+ fclose(fp);
+ return NULL;
+ }
+ *dest = tmp;
+ return dest;
+}
+
+s_buf_rw * file_open_rw (const s_str *path, s_buf_rw *dest)
+{
+ s_buf_rw tmp = {0};
+ assert(path);
+ assert(dest);
+ tmp.r = alloc(sizeof(s_buf));
+ if (! file_open_r(path, tmp.r)) {
+ free(tmp.r);
+ return NULL;
+ }
+ tmp.w = alloc(sizeof(s_buf));
+ if (! file_open_w(path, tmp.w)) {
+ free(tmp.w);
+ buf_file_close(tmp.r);
+ free(tmp.r);
+ return NULL;
+ }
+ *dest = tmp;
+ return dest;
+}
+
+s_buf * file_open_w (const s_str *path, s_buf *dest)
+{
+ FILE *fp;
+ s_buf tmp;
+ assert(path);
+ assert(dest);
+ fp = file_open(path->ptr.pchar, "wb");
+ if (! fp)
+ return NULL;
+ if (! buf_init_alloc(&tmp, BUF_SIZE)) {
+ fclose(fp);
+ return NULL;
+ }
+ if (! buf_file_open_w(&tmp, fp)) {
+ buf_clean(&tmp);
+ fclose(fp);
+ return NULL;
+ }
+ *dest = tmp;
+ return dest;
+}
+
s_str * file_pwd (s_str *dest)
{
char buf[PATH_MAX];
diff --git a/libkc3/file.h b/libkc3/file.h
index 5dfd21c..33678c4 100644
--- a/libkc3/file.h
+++ b/libkc3/file.h
@@ -36,7 +36,10 @@ s_str * file_search (const s_str *suffix, const s_sym *mode,
s_file_stat * file_stat (const s_str *path, s_file_stat *dest);
/* Operators. */
-s_str * file_pwd (s_str *dest);
-FILE * file_open (const char *path, const char *mode);
+s_str * file_pwd (s_str *dest);
+FILE * file_open (const char *path, const char *mode);
+s_buf * file_open_r (const s_str *path, s_buf *dest);
+s_buf_rw * file_open_rw (const s_str *path, s_buf_rw *dest);
+s_buf * file_open_w (const s_str *path, s_buf *dest);
#endif /* LIBKC3_FILE_H */
diff --git a/libkc3/sym.c b/libkc3/sym.c
index e11b7d1..d4575dc 100644
--- a/libkc3/sym.c
+++ b/libkc3/sym.c
@@ -32,6 +32,7 @@ const s_sym g_sym_Array = {{{NULL}, 5, {"Array"}}};
const s_sym g_sym_Block = {{{NULL}, 5, {"Block"}}};
const s_sym g_sym_Bool = {{{NULL}, 4, {"Bool"}}};
const s_sym g_sym_Buf = {{{NULL}, 3, {"Buf"}}};
+const s_sym g_sym_BufRW = {{{NULL}, 5, {"BufRW"}}};
const s_sym g_sym_Call = {{{NULL}, 4, {"Call"}}};
const s_sym g_sym_Cfn = {{{NULL}, 3, {"Cfn"}}};
const s_sym g_sym_Character = {{{NULL}, 9, {"Character"}}};
@@ -347,6 +348,7 @@ void sym_init_g_sym (void)
sym_register(&g_sym_Block, NULL);
sym_register(&g_sym_Bool, NULL);
sym_register(&g_sym_Buf, NULL);
+ sym_register(&g_sym_BufRW, NULL);
sym_register(&g_sym_Call, NULL);
sym_register(&g_sym_Cfn, NULL);
sym_register(&g_sym_Character, NULL);
diff --git a/libkc3/sym.h b/libkc3/sym.h
index 75779dd..9646ec3 100644
--- a/libkc3/sym.h
+++ b/libkc3/sym.h
@@ -36,6 +36,7 @@ extern const s_sym g_sym_Array;
extern const s_sym g_sym_Block;
extern const s_sym g_sym_Bool;
extern const s_sym g_sym_Buf;
+extern const s_sym g_sym_BufRW;
extern const s_sym g_sym_Call;
extern const s_sym g_sym_Cfn;
extern const s_sym g_sym_Character;
diff --git a/libkc3/types.h b/libkc3/types.h
index 0b1bdd4..d7c54db 100644
--- a/libkc3/types.h
+++ b/libkc3/types.h
@@ -374,7 +374,7 @@ struct buf {
s_buf_save *save;
sw (*seek) (s_buf *buf, sw offset, u8 whence);
uw size;
- void *user_ptr;
+ void * user_ptr;
uw wpos;
};