追記
shebangから使えるようにした。
#!/usr/bin/dansh
以下コード
// for MSVC: cl -I.. /Tp dansh.cpp curl.lib readline.lib ..\Release\json.lib
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
namespace json {
#include "json.h"
}
#define READLINE_STATIC
#include <readline/readline.h>
#include <curl/curl.h>
#define API_URL "http://api.dan.co.jp/perleval.cgi?c=callback&s="
typedef struct {
char* data; // response data from server
size_t size; // response size of data
} MEMFILE;
MEMFILE*
memfopen() {
MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE));
mf->data = NULL;
mf->size = 0;
return mf;
}
void
memfclose(MEMFILE* mf) {
if (mf->data) free(mf->data);
free(mf);
}
size_t
memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) {
MEMFILE* mf = (MEMFILE*) stream;
int block = size * nmemb;
if (!mf->data)
mf->data = (char*) malloc(block);
else
mf->data = (char*) realloc(mf->data, mf->size + block);
if (mf->data) {
memcpy(mf->data + mf->size, ptr, block);
mf->size += block;
}
return block;
}
char*
memfstrdup(MEMFILE* mf) {
char* buf = (char*) malloc(mf->size + 1);
memcpy(buf, mf->data, mf->size);
buf[mf->size] = 0;
return buf;
}
char*
url_encode_alloc(const char* str, int force_encode) {
const char* hex = "0123456789abcdef";
char* buf = NULL;
unsigned char* pbuf = NULL;
int len = 0;
if (!str) return NULL;
len = strlen(str)*3;
buf = (char*) malloc(len+1);
memset(buf, 0, len+1);
pbuf = (unsigned char*)buf;
while(*str) {
unsigned char c = (unsigned char)*str;
if (c == ' ')
*pbuf++ = '+';
else if (c & 0x80 || force_encode) {
*pbuf++ = '%';
*pbuf++ = hex[c >> 4];
*pbuf++ = hex[c & 0x0f];
} else
*pbuf++ = c;
str++;
}
return buf;
}
void do_dan(const char* line) {
char* source = url_encode_alloc(line, TRUE);
char* url = (char*) malloc(strlen(API_URL) + strlen(source) + 1);
strcpy(url, API_URL);
strcat(url, source);
MEMFILE* mf = memfopen();
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
CURLcode res = curl_easy_perform(curl);
free(url);
if (res == CURLE_OK) {
char* data = memfstrdup(mf);
memfclose(mf);
// remove callback function
char* ptr;
ptr = strrchr(data, ')');
if (ptr) *ptr = 0;
ptr = strchr(data, '(');
if (ptr) *ptr++ = 0;
else ptr = data;
json::json_object *obj = json::json_tokener_parse(ptr);
if (!is_error(obj)) {
json::json_object *result = json::json_object_object_get(obj, "result");
if (!is_error(result)) {
printf("%s\n", json::json_object_to_json_string(result));
json_object_put(result);
}
}
free(data);
}
curl_easy_cleanup(curl);
}
int main(int argc, char **argv)
{
char* line = NULL;
//json::mc_set_debug(1);
if (argc == 2) {
FILE* fp = fopen(argv[1], "rb");
if (!fp) {
perror("can't open file");
exit(-1);
}
char buf[BUFSIZ];
while (fgets(buf, sizeof(buf), fp)) {
if (!line) {
if (strncmp(buf, "#!", 2))
line = strdup(buf);
} else {
line = (char*) realloc(line, strlen(line) + strlen(buf) + 1);
strcat(line, buf);
}
}
fclose(fp);
do_dan(line);
free(line);
}
if (!isatty(fileno(stdin))) {
char buf[BUFSIZ];
while (fgets(buf, sizeof(buf), stdin)) {
if (!line) {
if (strncmp(buf, "#!", 2))
line = strdup(buf);
} else {
line = (char*) realloc(line, strlen(line) + strlen(buf) + 1);
strcat(line, buf);
}
}
do_dan(line);
free(line);
} else {
while (line = readline("dan> ")) {
do_dan(line);
free(line);
}
}
return 0;
}
参考文献: 404 Blog Not Found:Ajax - perlを実行するAPI