/* Collection of code snippets by Arne Vajhøj */
/* (from articles on eksperten.dk / vajhoej.dk written sometime between 2004 and now) */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "xmlrpc_format.h"
#include "vms_http.h"
#include "xmlrpc_parse.h"

struct data
{
    int ival;
    char *sval;
};

void test(const char *host, int port)
{
    printf("http://%s:%d/\n", host, port);
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getInt", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        int v; 
        xmlrpc_response(resp, &v);
        printf("%d\n", v);
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getString", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        char *s;
        xmlrpc_response(resp, &s);
        printf("%s\n", s);
        free(s);
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getData", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data d;
        struct xmlrpc_struct_i4_or_str gas[2];
        xmlrpc_response(resp, gas);
        for(int i = 0; i < 2; i++)
        {
            if(strcmp(gas[i].name, "ival") == 0)
            {
                d.ival = gas[i].value.i4;
            }
            if(strcmp(gas[i].name, "sval") == 0)
            {
                d.sval = gas[i].value.str;
            }
        }
        printf("(%d,%s)\n", d.ival, d.sval);
        free(d.sval);
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getData", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data d;
        STRUCT_PARSE(resp, 1000)
        {
            RECFLD(i4, d, ival);
            RECFLD(str, d, sval);
        }
        printf("(%d,%s)\n", d.ival, d.sval);
        free(d.sval);
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getData", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data d;
        void *stctx = xmlrpc_struct_init(resp, 2);
        d.ival = xmlrpc_struct_unpack_i4(stctx, 0, "ival");
        d.sval = xmlrpc_struct_unpack_string(stctx, 0, "sval");
        xmlrpc_struct_cleanup(stctx);
        printf("(%d,%s)\n", d.ival, d.sval);
        free(d.sval);
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getListOfInts", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[100000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        int a[1000];
        int nelm = xmlrpc_response(resp, a);
        printf("[");
        for(int i = 0; i < nelm; i++) 
        {
            if(i > 0) printf(",");
            printf("%d", a[i]);
        }
        printf("]\n");
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getListOfStrings", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[100000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        char *a[1000];
        int nelm = xmlrpc_response(resp, a);
        printf("[");
        for(int i = 0; i < nelm; i++) 
        {
            if(i > 0) printf(",");
            printf("%s", a[i]);
            free(a[i]);
        }
        printf("]\n");
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getListOfData", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[100000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data da[1000];
        struct xmlrpc_struct_i4_or_str gas[2000];
        int nelm = xmlrpc_response(resp, gas);
        for(int i = 0; i < nelm; i++)
        {
            if(strcmp(gas[i].name, "ival") == 0)
            {
                da[i / 2].ival = gas[i].value.i4;
            }
            if(strcmp(gas[i].name, "sval") == 0)
            {
                da[i / 2].sval = gas[i].value.str;
            }
        }
        printf("[");
        for(int i = 0; i < nelm / 2; i++) 
        {
            if(i > 0) printf(",");
            printf("(%d,%s)", da[i].ival, da[i].sval);
            free(da[i].sval);
        }
        printf("]\n");
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getListOfData", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[100000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data da[1000];
        STRUCT_PARSE(resp, 1000)
        {
            RECFLD(i4, da[i / 2], ival);
            RECFLD(str, da[i / 2], sval);
        }
        printf("[");
        for(int i = 0; i < nitms / 2; i++) 
        {
            if(i > 0) printf(",");
            printf("(%d,%s)", da[i].ival, da[i].sval);
            free(da[i].sval);
        }
        printf("]\n");
    }
    {
        char req[1000];
        xmlrpc_request(req, sizeof(req), "Test.getListOfData", 0);
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[100000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data da[1000];
        void *stctx = xmlrpc_struct_init(resp, 2);
        int n = xmlrpc_struct_n(stctx);
        for(int i = 0; i < n; i++)
        {
            da[i].ival = xmlrpc_struct_unpack_i4(stctx, i, "ival");
            da[i].sval = xmlrpc_struct_unpack_string(stctx, i, "sval");
        }
        xmlrpc_struct_cleanup(stctx);
        printf("[");
        for(int i = 0; i < n; i++) 
        {
            if(i > 0) printf(",");
            printf("(%d,%s)", da[i].ival, da[i].sval);
            free(da[i].sval);
        }
        printf("]\n");
    }
    {
        char req[1000];
        int v1 = 123;
        int v2 = 456;
        xmlrpc_request(req, sizeof(req), "Test.add", 2, xmlrpc_i4(v1), xmlrpc_i4(v2));
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        int v3;
        xmlrpc_response(resp, &v3);
        printf("%d\n", v3);
    }
    {
        char req[1000];
        char *s1 = "ABC";
        char *s2 = "DEF";
        xmlrpc_request(req, sizeof(req), "Test.concat", 2, xmlrpc_string(s1), xmlrpc_string(s2));
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        char *s3;
        xmlrpc_response(resp, &s3);
        printf("%s\n", s3);
        free(s3);
    }
    {
        char req[1000];
        struct data d;
        d.ival = 123;
        d.sval = "ABC";
        xmlrpc_request(req, sizeof(req), "Test.modify", 1, xmlrpc_struct(2, "ival", xmlrpc_i4(d.ival), "sval", xmlrpc_string(d.sval)));
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data d2;
        struct xmlrpc_struct_i4_or_str gas[2];
        xmlrpc_response(resp, gas);
        for(int i = 0; i < 2; i++)
        {
            if(strcmp(gas[i].name, "ival") == 0)
            {
                d2.ival = gas[i].value.i4;
            }
            if(strcmp(gas[i].name, "sval") == 0)
            {
                d2.sval = gas[i].value.str;
            }
        }
        printf("(%d,%s)\n", d2.ival, d2.sval);
        free(d2.sval);
    }
    {
        char req[1000];
        struct data d;
        d.ival = 123;
        d.sval = "ABC";
        xmlrpc_request(req, sizeof(req), "Test.modify", 1, xmlrpc_struct(2, "ival", xmlrpc_i4(d.ival), "sval", xmlrpc_string(d.sval)));
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data d2;
        STRUCT_PARSE(resp, 1000)
        {
            RECFLD(i4, d2, ival);
            RECFLD(str, d2, sval);
        }
        printf("(%d,%s)\n", d2.ival, d2.sval);
        free(d2.sval);
    }
    {
        char req[1000];
        struct data d;
        d.ival = 123;
        d.sval = "ABC";
        xmlrpc_request(req, sizeof(req), "Test.modify", 1, xmlrpc_struct(2, "ival", xmlrpc_i4(d.ival), "sval", xmlrpc_string(d.sval)));
        struct vms_http *ctx = http_post(host, port, "/", "text/xml", "text/xml", req);
        char resp[10000];
        short resplen;
        http_recv_all(ctx, resp, sizeof(resp), &resplen);
        resp[resplen] = 0;
        http_close(ctx);
        struct data d2;
        void *stctx = xmlrpc_struct_init(resp, 2);
        d2.ival = xmlrpc_struct_unpack_i4(stctx, 0, "ival");
        d2.sval = xmlrpc_struct_unpack_string(stctx, 0, "sval");
        xmlrpc_struct_cleanup(stctx);
        printf("(%d,%s)\n", d2.ival, d2.sval);
        free(d2.sval);
    }
}

int main()
{
    test("localhost", 8001);
    test("localhost", 8002);
    return 0;
}
