components/jansson/doc/html/_downloads/github_commits.c
changeset 2190 0e3f360be1b9
equal deleted inserted replaced
2189:8231387581aa 2190:0e3f360be1b9
       
     1 /*
       
     2  * Copyright (c) 2009-2014 Petri Lehtinen <[email protected]>
       
     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 = NULL;
       
    55     CURLcode status;
       
    56     struct curl_slist *headers = NULL;
       
    57     char *data = NULL;
       
    58     long code;
       
    59 
       
    60     curl_global_init(CURL_GLOBAL_ALL);
       
    61     curl = curl_easy_init();
       
    62     if(!curl)
       
    63         goto error;
       
    64 
       
    65     data = malloc(BUFFER_SIZE);
       
    66     if(!data)
       
    67         goto error;
       
    68 
       
    69     struct write_result write_result = {
       
    70         .data = data,
       
    71         .pos = 0
       
    72     };
       
    73 
       
    74     curl_easy_setopt(curl, CURLOPT_URL, url);
       
    75 
       
    76     /* GitHub commits API v3 requires a User-Agent header */
       
    77     headers = curl_slist_append(headers, "User-Agent: Jansson-Tutorial");
       
    78     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
       
    79 
       
    80     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
       
    81     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
       
    82 
       
    83     status = curl_easy_perform(curl);
       
    84     if(status != 0)
       
    85     {
       
    86         fprintf(stderr, "error: unable to request data from %s:\n", url);
       
    87         fprintf(stderr, "%s\n", curl_easy_strerror(status));
       
    88         goto error;
       
    89     }
       
    90 
       
    91     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
       
    92     if(code != 200)
       
    93     {
       
    94         fprintf(stderr, "error: server responded with code %ld\n", code);
       
    95         goto error;
       
    96     }
       
    97 
       
    98     curl_easy_cleanup(curl);
       
    99     curl_slist_free_all(headers);
       
   100     curl_global_cleanup();
       
   101 
       
   102     /* zero-terminate the result */
       
   103     data[write_result.pos] = '\0';
       
   104 
       
   105     return data;
       
   106 
       
   107 error:
       
   108     if(data)
       
   109         free(data);
       
   110     if(curl)
       
   111         curl_easy_cleanup(curl);
       
   112     if(headers)
       
   113         curl_slist_free_all(headers);
       
   114     curl_global_cleanup();
       
   115     return NULL;
       
   116 }
       
   117 
       
   118 int main(int argc, char *argv[])
       
   119 {
       
   120     size_t i;
       
   121     char *text;
       
   122     char url[URL_SIZE];
       
   123 
       
   124     json_t *root;
       
   125     json_error_t error;
       
   126 
       
   127     if(argc != 3)
       
   128     {
       
   129         fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]);
       
   130         fprintf(stderr, "List commits at USER's REPOSITORY.\n\n");
       
   131         return 2;
       
   132     }
       
   133 
       
   134     snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]);
       
   135 
       
   136     text = request(url);
       
   137     if(!text)
       
   138         return 1;
       
   139 
       
   140     root = json_loads(text, 0, &error);
       
   141     free(text);
       
   142 
       
   143     if(!root)
       
   144     {
       
   145         fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
       
   146         return 1;
       
   147     }
       
   148 
       
   149     if(!json_is_array(root))
       
   150     {
       
   151         fprintf(stderr, "error: root is not an array\n");
       
   152         json_decref(root);
       
   153         return 1;
       
   154     }
       
   155 
       
   156     for(i = 0; i < json_array_size(root); i++)
       
   157     {
       
   158         json_t *data, *sha, *commit, *message;
       
   159         const char *message_text;
       
   160 
       
   161         data = json_array_get(root, i);
       
   162         if(!json_is_object(data))
       
   163         {
       
   164             fprintf(stderr, "error: commit data %d is not an object\n", (int)(i + 1));
       
   165             json_decref(root);
       
   166             return 1;
       
   167         }
       
   168 
       
   169         sha = json_object_get(data, "sha");
       
   170         if(!json_is_string(sha))
       
   171         {
       
   172             fprintf(stderr, "error: commit %d: sha is not a string\n", (int)(i + 1));
       
   173             return 1;
       
   174         }
       
   175 
       
   176         commit = json_object_get(data, "commit");
       
   177         if(!json_is_object(commit))
       
   178         {
       
   179             fprintf(stderr, "error: commit %d: commit is not an object\n", (int)(i + 1));
       
   180             json_decref(root);
       
   181             return 1;
       
   182         }
       
   183 
       
   184         message = json_object_get(commit, "message");
       
   185         if(!json_is_string(message))
       
   186         {
       
   187             fprintf(stderr, "error: commit %d: message is not a string\n", (int)(i + 1));
       
   188             json_decref(root);
       
   189             return 1;
       
   190         }
       
   191 
       
   192         message_text = json_string_value(message);
       
   193         printf("%.8s %.*s\n",
       
   194                json_string_value(sha),
       
   195                newline_offset(message_text),
       
   196                message_text);
       
   197     }
       
   198 
       
   199     json_decref(root);
       
   200     return 0;
       
   201 }