Fix build warnings under MinGW
[jansson.git] / doc / github_commits.c
1 /*
2  * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
3  *
4  * Jansson is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <jansson.h>
12 #include <curl/curl.h>
13
14 #define BUFFER_SIZE  (256 * 1024)  /* 256 KB */
15
16 #define URL_FORMAT   "https://api.github.com/repos/%s/%s/commits"
17 #define URL_SIZE     256
18
19 /* Return the offset of the first newline in text or the length of
20    text if there's no newline */
21 static int newline_offset(const char *text)
22 {
23     const char *newline = strchr(text, '\n');
24     if(!newline)
25         return strlen(text);
26     else
27         return (int)(newline - text);
28 }
29
30 struct write_result
31 {
32     char *data;
33     int pos;
34 };
35
36 static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream)
37 {
38     struct write_result *result = (struct write_result *)stream;
39
40     if(result->pos + size * nmemb >= BUFFER_SIZE - 1)
41     {
42         fprintf(stderr, "error: too small buffer\n");
43         return 0;
44     }
45
46     memcpy(result->data + result->pos, ptr, size * nmemb);
47     result->pos += size * nmemb;
48
49     return size * nmemb;
50 }
51
52 static char *request(const char *url)
53 {
54     CURL *curl;
55     CURLcode status;
56     char *data;
57     long code;
58
59     curl = curl_easy_init();
60     data = malloc(BUFFER_SIZE);
61     if(!curl || !data)
62         return NULL;
63
64     struct write_result write_result = {
65         .data = data,
66         .pos = 0
67     };
68
69     curl_easy_setopt(curl, CURLOPT_URL, url);
70     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
71     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
72
73     status = curl_easy_perform(curl);
74     if(status != 0)
75     {
76         fprintf(stderr, "error: unable to request data from %s:\n", url);
77         fprintf(stderr, "%s\n", curl_easy_strerror(status));
78         return NULL;
79     }
80
81     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
82     if(code != 200)
83     {
84         fprintf(stderr, "error: server responded with code %ld\n", code);
85         return NULL;
86     }
87
88     curl_easy_cleanup(curl);
89     curl_global_cleanup();
90
91     /* zero-terminate the result */
92     data[write_result.pos] = '\0';
93
94     return data;
95 }
96
97 int main(int argc, char *argv[])
98 {
99     size_t i;
100     char *text;
101     char url[URL_SIZE];
102
103     json_t *root;
104     json_error_t error;
105
106     if(argc != 3)
107     {
108         fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]);
109         fprintf(stderr, "List commits at USER's REPOSITORY.\n\n");
110         return 2;
111     }
112
113     snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]);
114
115     text = request(url);
116     if(!text)
117         return 1;
118
119     root = json_loads(text, 0, &error);
120     free(text);
121
122     if(!root)
123     {
124         fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
125         return 1;
126     }
127
128     if(!json_is_array(root))
129     {
130         fprintf(stderr, "error: root is not an array\n");
131         return 1;
132     }
133
134     for(i = 0; i < json_array_size(root); i++)
135     {
136         json_t *data, *sha, *commit, *message;
137         const char *message_text;
138
139         data = json_array_get(root, i);
140         if(!json_is_object(data))
141         {
142             fprintf(stderr, "error: commit data %d is not an object\n", i + 1);
143             return 1;
144         }
145
146         sha = json_object_get(data, "sha");
147         if(!json_is_string(sha))
148         {
149             fprintf(stderr, "error: commit %d: sha is not a string\n", i + 1);
150             return 1;
151         }
152
153         commit = json_object_get(data, "commit");
154         if(!json_is_object(commit))
155         {
156             fprintf(stderr, "error: commit %d: commit is not an object\n", i + 1);
157             return 1;
158         }
159
160         message = json_object_get(commit, "message");
161         if(!json_is_string(message))
162         {
163             fprintf(stderr, "error: commit %d: message is not a string\n", i + 1);
164             return 1;
165         }
166
167         message_text = json_string_value(message);
168         printf("%.8s %.*s\n",
169                json_string_value(sha),
170                newline_offset(message_text),
171                message_text);
172     }
173
174     json_decref(root);
175     return 0;
176 }