init here
This commit is contained in:
46
си/pstruya.c
Normal file
46
си/pstruya.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "pstruya.h"
|
||||
|
||||
typedef struct {
|
||||
struya_vnutr__TStruya routine;
|
||||
TTagPair arg;
|
||||
} tri_thread_launch_compound;
|
||||
|
||||
void* tri_thread_wrapper(void* arg) {
|
||||
tri_thread_launch_compound* compound = (tri_thread_launch_compound*) arg;
|
||||
compound->routine.func(compound->routine.receiver, compound->arg);
|
||||
|
||||
free(compound);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t tri_thread_create(struya_vnutr__TStruya routine, TTagPair arg) {
|
||||
pthread_t thread;
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, 512 * 1024);
|
||||
|
||||
tri_thread_launch_compound* compound = malloc(sizeof(tri_thread_launch_compound));
|
||||
compound->routine = routine;
|
||||
compound->arg = arg;
|
||||
|
||||
int result = pthread_create(&thread, &attr, tri_thread_wrapper, (void*) compound);
|
||||
|
||||
if (result != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t)(uintptr_t)thread;
|
||||
}
|
||||
|
||||
void tri_thread_join(int64_t thread) {
|
||||
if (!thread) return;
|
||||
|
||||
pthread_join((pthread_t)(uintptr_t)thread, NULL);
|
||||
}
|
||||
|
||||
void tri_thread_detach(int64_t thread) {
|
||||
if (!thread) return;
|
||||
|
||||
pthread_detach((pthread_t)(uintptr_t)thread);
|
||||
}
|
||||
14
си/pstruya.h
Normal file
14
си/pstruya.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef STRUYA_H
|
||||
#define STRUYA_H
|
||||
|
||||
#include "rt_api.h"
|
||||
#include "struya_vnutr.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int64_t tri_thread_create(struya_vnutr__TStruya routine, TTagPair arg);
|
||||
void tri_thread_join(int64_t thread);
|
||||
void tri_thread_detach(int64_t thread);
|
||||
|
||||
#endif // STRUYA_H
|
||||
160
си/sckulya.c
Normal file
160
си/sckulya.c
Normal file
@@ -0,0 +1,160 @@
|
||||
#include "sckulya.h"
|
||||
|
||||
int64_t tri_sqlite_open(TString filename, TString *error) {
|
||||
sqlite3* out_db = 0;
|
||||
|
||||
int rc = sqlite3_open((const char*) filename->body, &out_db);
|
||||
|
||||
if(rc != SQLITE_OK) {
|
||||
if(out_db) {
|
||||
sqlite3_close(out_db);
|
||||
}
|
||||
|
||||
const char* msg = sqlite3_errmsg(out_db);
|
||||
|
||||
if(!msg) {
|
||||
msg = "Unknown error";
|
||||
}
|
||||
|
||||
int64_t len = (int64_t)strlen(msg);
|
||||
*error = tri_newString(len, len, (char*)msg);
|
||||
}
|
||||
|
||||
sqlite3_busy_timeout(out_db, 5000);
|
||||
|
||||
return (int64_t) out_db;
|
||||
}
|
||||
|
||||
int tri_sqlite_close(int64_t db) {
|
||||
if (!db) return SQLITE_MISUSE;
|
||||
return sqlite3_close((sqlite3*) db);
|
||||
}
|
||||
|
||||
void tri_sqlite_exec(int64_t db, TString query, TString *error) {
|
||||
char* errmsg = NULL;
|
||||
int rc = sqlite3_exec((sqlite3*) db, (const char*) query->body, NULL, NULL, &errmsg);
|
||||
|
||||
if (errmsg) {
|
||||
int64_t len = (int64_t)strlen(errmsg);
|
||||
*error = tri_newString(len, len, errmsg);
|
||||
|
||||
sqlite3_free(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
void escape_and_append (const unsigned char *s, char* buf, size_t* len) {
|
||||
for (; *s; ++s) {
|
||||
char esc = 0;
|
||||
|
||||
switch (*s) {
|
||||
case '\\': esc = '\\'; break;
|
||||
case '\b': esc = 'b'; break;
|
||||
case '\f': esc = 'f'; break;
|
||||
case '\n': esc = 'n'; break;
|
||||
case '\r': esc = 'r'; break;
|
||||
case '\t': esc = 't'; break;
|
||||
default: break;
|
||||
}
|
||||
if (esc) {
|
||||
buf[(*len)++] = '\\';
|
||||
buf[(*len)++] = esc;
|
||||
} else {
|
||||
buf[(*len)++] = *s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int tri_sqlite_query(int64_t db, TString query, TString *result, TString *error) {
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int rc = sqlite3_prepare_v2((sqlite3*)db, (const char*) query->body, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
if (error) {
|
||||
const char *msg = sqlite3_errmsg((sqlite3*)db);
|
||||
if (!msg) msg = "Unknown error";
|
||||
int64_t len = (int64_t)strlen(msg);
|
||||
*error = tri_newString(len, len, (char*)msg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
size_t cap = 1024;
|
||||
size_t len = 0;
|
||||
char *buf = malloc(cap);
|
||||
|
||||
if (!buf) {
|
||||
sqlite3_finalize(stmt);
|
||||
if (error) *error = tri_newString(0,0,"Out of memory");
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
buf[len++] = '[';
|
||||
int first_row = 1;
|
||||
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||
if (!first_row) { buf[len++] = ','; } else first_row = 0;
|
||||
buf[len++] = '{';
|
||||
|
||||
int ncol = sqlite3_column_count(stmt);
|
||||
for (int i = 0; i < ncol; ++i) {
|
||||
if (i) { buf[len++] = ','; }
|
||||
const char *colname = sqlite3_column_name(stmt, i);
|
||||
/* "colname": */
|
||||
// strlen(colname) + 4;
|
||||
buf[len++] = '\"';
|
||||
escape_and_append((const unsigned char*)colname, buf, &len);
|
||||
buf[len++] = '\"';
|
||||
buf[len++] = ':';
|
||||
|
||||
int type = sqlite3_column_type(stmt, i);
|
||||
if (type == SQLITE_INTEGER) {
|
||||
long long v = sqlite3_column_int64(stmt, i);
|
||||
char tmp[32];
|
||||
int n = snprintf(tmp, sizeof(tmp), "%lld", v);
|
||||
memcpy(buf + len, tmp, n); len += n;
|
||||
} else if (type == SQLITE_FLOAT) {
|
||||
double v = sqlite3_column_double(stmt, i);
|
||||
char tmp[64];
|
||||
int n = snprintf(tmp, sizeof(tmp), "%g", v);
|
||||
memcpy(buf + len, tmp, n); len += n;
|
||||
} else if (type == SQLITE_NULL) {
|
||||
memcpy(buf + len, "null", 4); len += 4;
|
||||
} else {
|
||||
const unsigned char *txt = sqlite3_column_text(stmt, i);
|
||||
if (!txt) {
|
||||
memcpy(buf + len, "null", 4); len += 4;
|
||||
} else {
|
||||
buf[len++] = '\"';
|
||||
escape_and_append(txt, buf, &len);
|
||||
buf[len++] = '\"';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf[len++] = '}';
|
||||
}
|
||||
|
||||
/* finalize and handle errors */
|
||||
if (rc != SQLITE_DONE) {
|
||||
const char *msg = sqlite3_errmsg((sqlite3*)db);
|
||||
if (error) {
|
||||
if (!msg) msg = "Unknown error";
|
||||
int64_t mlen = (int64_t)strlen(msg);
|
||||
*error = tri_newString(mlen, mlen, (char*)msg);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
buf[len++] = ']';
|
||||
buf[len] = '\0';
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
if (result) {
|
||||
*result = tri_newString((int64_t)len, (int64_t)len, buf);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
17
си/sckulya.h
Normal file
17
си/sckulya.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef SCKULYA_H
|
||||
#define SCKULYA_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rt_api.h"
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
int64_t tri_sqlite_open(TString filename, TString *error);
|
||||
int tri_sqlite_close(int64_t db);
|
||||
void tri_sqlite_exec(int64_t db, TString query, TString *error);
|
||||
int tri_sqlite_query(int64_t db, TString query, TString *result, TString *error);
|
||||
|
||||
#endif // SCKULYA_H
|
||||
34
си/stdin.c
Normal file
34
си/stdin.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rt_api.h"
|
||||
|
||||
TString stdin_read_to_string(int bytes) {
|
||||
if (bytes <= 0) {
|
||||
return tri_newString(0, 0, "");
|
||||
}
|
||||
|
||||
char* buffer = (char*)malloc((size_t)bytes + 1);
|
||||
if (!buffer) {
|
||||
return tri_newString(0, 0, "");
|
||||
}
|
||||
|
||||
ssize_t bytes_read = read(0, buffer, (size_t)bytes);
|
||||
if (bytes_read < 0) {
|
||||
bytes_read = 0;
|
||||
}
|
||||
|
||||
TString string = tri_newString((int64_t)bytes_read, (int64_t)bytes_read, buffer);
|
||||
|
||||
free(buffer);
|
||||
return string;
|
||||
}
|
||||
|
||||
// Writes TString data to STDERR (fd 2)
|
||||
void stderr_write_string(TString data) {
|
||||
if (!data) return;
|
||||
char* datastring = (char*)data->body;
|
||||
if (!datastring) return;
|
||||
write(2, datastring, (size_t)strlen(datastring));
|
||||
}
|
||||
|
||||
9
си/stdin.h
Normal file
9
си/stdin.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef STDIN_H
|
||||
#define STDIN_H
|
||||
|
||||
#include "rt_api.h"
|
||||
|
||||
TString stdin_read_to_string(int bytes);
|
||||
void stderr_write_string(TString data);
|
||||
|
||||
#endif // STDIN_H
|
||||
121
си/suckit.c
Normal file
121
си/suckit.c
Normal file
@@ -0,0 +1,121 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include "rt_api.h"
|
||||
|
||||
|
||||
int create_socket_fd(int port) {
|
||||
int server_fd;
|
||||
struct sockaddr_in address;
|
||||
int opt = 1;
|
||||
|
||||
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
||||
perror("socket failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
perror("setsockopt SO_REUSEADDR");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
|
||||
perror("setsockopt SO_REUSEPORT");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
|
||||
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
|
||||
perror("bind failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (listen(server_fd, 3) < 0) {
|
||||
perror("listen");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return server_fd;
|
||||
}
|
||||
|
||||
int accept_socket(int fd) {
|
||||
int server_fd = fd;
|
||||
struct sockaddr_in client_addr;
|
||||
socklen_t addrlen = sizeof(client_addr);
|
||||
|
||||
int new_socket = accept(server_fd, (struct sockaddr*)&client_addr, &addrlen);
|
||||
|
||||
if (new_socket < 0) {
|
||||
perror("accept");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return new_socket;
|
||||
}
|
||||
|
||||
void write_string(int socket, TString data) {
|
||||
char* datastring = (char*) data->body;
|
||||
write(socket, datastring, strlen(datastring));
|
||||
}
|
||||
|
||||
void close_socket(int socket){
|
||||
close(socket);
|
||||
}
|
||||
|
||||
TString read_to_string(int socket, int bytes) {
|
||||
char* buffer = malloc(bytes + 1);
|
||||
int bytes_read = read(socket, buffer, bytes);
|
||||
|
||||
if(bytes_read < 0) {
|
||||
bytes_read = 0;
|
||||
}
|
||||
|
||||
TString string = tri_newString(bytes_read, bytes_read, buffer);
|
||||
|
||||
free(buffer);
|
||||
return string;
|
||||
}
|
||||
|
||||
int connect_socket(TString host, int port) {
|
||||
char* chost = (char*) host->body;
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res = NULL;
|
||||
char portstr[16];
|
||||
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
int gai = getaddrinfo(chost, portstr, &hints, &res);
|
||||
if (gai != 0) {
|
||||
perror("getaddrinfo");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sockfd = -1;
|
||||
for (struct addrinfo* p = res; p != NULL; p = p->ai_next) {
|
||||
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if (sockfd < 0) continue;
|
||||
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == 0) {
|
||||
break; // connected
|
||||
}
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return sockfd;
|
||||
}
|
||||
13
си/suckit.h
Normal file
13
си/suckit.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef SUCKIT_H
|
||||
#define SUCKIT_H
|
||||
|
||||
#include "rt_api.h"
|
||||
|
||||
int create_socket_fd(int port);
|
||||
int accept_socket(int fd);
|
||||
void write_string(int socket, TString data);
|
||||
void close_socket(int socket);
|
||||
TString read_to_string(int socket, int bytes);
|
||||
int connect_socket(TString host, int port);
|
||||
|
||||
#endif // SUCKIT_H
|
||||
Reference in New Issue
Block a user