2008/02/07


JSON-Cという、C言語からJSONを扱う為のライブラリを見つけました。
Index of /json-c
C言語って言いながら、実際もともと/TPオプションでCPPビルドしてるし、それJSON-CPPちゃうんかいという気もしなくないですが...。
foreachなんかもあり、結構使い勝手は良さそうです。

ただ、同梱されている物の中には*.vcprojしか入っておらず、Makefileでゴニョゴニョするのが好きな私には絶えられないものであったり...
最近はMakefileを書く習慣って無くなってきたんですかねぇ...
で、VC6でビルドしようと思ったけどエラーがワンサカ。
どうやら
  • キャスト漏れ
  • 変数名に「this」を使用
  • C99の可変個引数マクロを使用
とはっきり言ってVC6を捨てているコードだったりしました。
なにくそーとパッチを書いたので、公開しておきます。
ただ大したパッチでもないので、オフィシャルに送るのはやめときます。
しかもトリッキーな事やってます。
デバッグ用の可変個引数マクロ #define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_DEBUG if (0)
みたくして無理やり殺しています。
で、できたパッチは以下の通り。
Index: json_object.c
===================================================================
--- json_object.c   (revision 21)
+++ json_object.c   (working copy)
@@ -28,7 +28,9 @@
   char* strndup(const char* str, size_t n);
 #endif /* !HAVE_STRNDUP */
 
+#if _MSC_VER >= 1400
 #define REFCOUNT_DEBUG 1
+#endif
 
 char *json_number_chars = "0123456789.+-eE";
 char *json_hex_chars = "0123456789abcdef";
@@ -160,7 +162,7 @@
 
 static struct json_object* json_object_new(enum json_type o_type)
 {
-  struct json_object *this = calloc(sizeof(struct json_object), 1);
+  struct json_object *this = (struct json_object*)calloc(sizeof(struct json_object), 1);
   if(!this) return NULL;
   this->o_type = o_type;
   this->_ref_count = 1;
Index: json_tokener.c
===================================================================
--- json_tokener.c  (revision 21)
+++ json_tokener.c  (working copy)
@@ -57,7 +57,7 @@
 
 struct json_tokener* json_tokener_new()
 {
-  struct json_tokener *tok = calloc(1, sizeof(struct json_tokener));
+  struct json_tokener *tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
   tok->pb = printbuf_new();
   json_tokener_reset(tok);
   return tok;
@@ -97,7 +97,7 @@
   tok = json_tokener_new();
   obj = json_tokener_parse_ex(tok, str, -1);
   if(tok->err != json_tokener_success)
-    obj = error_ptr(-tok->err);
+    obj = (struct json_object*)error_ptr(-tok->err);
   json_tokener_free(tok);
   return obj;
 }
Index: linkhash.c
===================================================================
--- linkhash.c  (revision 21)
+++ linkhash.c  (working copy)
@@ -42,7 +42,7 @@
 unsigned long lh_char_hash(void *k)
 {
    unsigned int h = 0;
-   const char* data = k;
+   const char* data = (const char*)k;
  
    while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
 
@@ -62,12 +62,12 @@
    int i;
    struct lh_table *t;
 
-   t = calloc(1, sizeof(struct lh_table));
+   t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
    if(!t) lh_abort("lh_table_new: calloc failed\n");
    t->count = 0;
    t->size = size;
    t->name = name;
-   t->table = calloc(size, sizeof(struct lh_entry));
+   t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
    if(!t->table) lh_abort("lh_table_new: calloc failed\n");
    t->free_fn = free_fn;
    t->hash_fn = hash_fn;
Index: json_util.c
===================================================================
--- json_util.c (revision 21)
+++ json_util.c (working copy)
@@ -62,11 +62,11 @@
   if((fd = open(filename, O_RDONLY)) < 0) {
     MC_ERROR("json_object_from_file: error reading file %s: %s\n",
         filename, strerror(errno));
-    return error_ptr(-1);
+    return (struct json_object*)error_ptr(-1);
   }
   if(!(pb = printbuf_new())) {
     MC_ERROR("json_object_from_file: printbuf_new failed\n");
-    return error_ptr(-1);
+    return (struct json_object*)error_ptr(-1);
   }
   while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
     printbuf_memappend(pb, buf, ret);
@@ -76,7 +76,7 @@
     MC_ABORT("json_object_from_file: error reading file %s: %s\n",
         filename, strerror(errno));
     printbuf_free(pb);
-    return error_ptr(-1);
+    return (struct json_object*)error_ptr(-1);
   }
   obj = json_tokener_parse(pb->buf);
   printbuf_free(pb);
Index: debug.h
===================================================================
--- debug.h (revision 21)
+++ debug.h (working copy)
@@ -21,6 +21,7 @@
 extern void mc_error(const char *msg, ...);
 extern void mc_info(const char *msg, ...);
 
+#if _MSC_VER >= 1400
 #ifdef MC_MAINTAINER_MODE
 #define MC_SET_DEBUG(x) mc_set_debug(x)
 #define MC_GET_DEBUG() mc_get_debug()
@@ -38,5 +39,14 @@
 #define MC_ERROR(x, ...) if (0) mc_error(x, ##__VA_ARGS__)
 #define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
 #endif
+#else
+#define MC_SET_DEBUG(x)
+#define MC_GET_DEBUG()
+#define MC_SET_SYSLOG(x)
+#define MC_ABORT if (0)
+#define MC_DEBUG if (0)
+#define MC_ERROR if (0)
+#define MC_INFO if (0)
+#endif
 
 #endif
Index: arraylist.c
===================================================================
--- arraylist.c (revision 21)
+++ arraylist.c (working copy)
@@ -28,11 +28,11 @@
 {
   struct array_list *this;
 
-  if(!(this = calloc(1, sizeof(struct array_list)))) return NULL;
+  if(!(this = (struct array_list*)calloc(1, sizeof(struct array_list)))) return NULL;
   this->size = ARRAY_LIST_DEFAULT_SIZE;
   this->length = 0;
   this->free_fn = free_fn;
-  if(!(this->array = calloc(sizeof(void*), this->size))) {
+  if(!(this->array = (void**)calloc(sizeof(void*), this->size))) {
     free(this);
     return NULL;
   }
@@ -64,7 +64,7 @@
   if(max < this->size) return 0;
   new_size = max(this->size << 1, max);
   if(!(t = realloc(this->array, new_size*sizeof(void*)))) return -1;
-  this->array = t;
+  this->array = (void**)t;
   (void)memset(this->array + this->size, 0, (new_size-this->size)*sizeof(void*));
   this->size = new_size;
   return 0;
Index: json.h
===================================================================
--- json.h  (revision 21)
+++ json.h  (working copy)
@@ -13,8 +13,10 @@
 #define _json_h_
 
 #ifdef __cplusplus
+#if _MSC_VER >= 1400
 extern "C" {
 #endif
+#endif
 
 #include "bits.h"
 #include "debug.h"
@@ -25,7 +27,9 @@
 #include "json_tokener.h"
 
 #ifdef __cplusplus
+#if _MSC_VER >= 1400
 }
 #endif
+#endif
 
 #endif
Index: printbuf.c
===================================================================
--- printbuf.c  (revision 21)
+++ printbuf.c  (working copy)
@@ -29,10 +29,10 @@
 {
   struct printbuf *p;
 
-  if(!(p = calloc(1, sizeof(struct printbuf)))) return NULL;
+  if(!(p = (struct printbuf*)calloc(1, sizeof(struct printbuf)))) return NULL;
   p->size = 32;
   p->bpos = 0;
-  if(!(p->buf = malloc(p->size))) {
+  if(!(p->buf = (char*)malloc(p->size))) {
     free(p);
     return NULL;
   }
@@ -50,7 +50,7 @@
         "bpos=%d wrsize=%d old_size=%d new_size=%d\n",
         p->bpos, size, p->size, new_size);
 #endif /* PRINTBUF_DEBUG */
-    if(!(t = realloc(p->buf, new_size))) return -1;
+    if(!(t = (char*)realloc(p->buf, new_size))) return -1;
     p->size = new_size;
     p->buf = t;
   }
@@ -70,7 +70,7 @@
 /* CAW: compliant version of vasprintf */
 static int vasprintf(char **buf, const char *fmt, va_list ap)
 {
-#ifndef WIN32
+#if !defined(WIN32) || _MSC_VER < 1400
    static char _T_emptybuffer = '\0';
 #endif /* !defined(WIN32) */
    int chars;
@@ -78,7 +78,7 @@
 
    if(!buf) { return -1; }
 
-#ifdef WIN32
+#if defined(WIN32) && _MSC_VER >= 1400
    chars = _vscprintf(fmt, ap)+1;
 #else /* !defined(WIN32) */
    /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
さらにVC6でビルドする為のMakefile CFLAGS = -DWIN32 -Dthis=o_this -O2 -MT -W3 -nologo -TP -EHsc
SRC = arraylist.c json_object.c json_tokener.c json_util.c linkhash.c printbuf.c
OBJ = $(SRC:.c=.obj)

all : json.lib

json.lib : $(OBJ)
    lib /out:json.lib $(OBJ)

hoge.exe : hoge.obj
    cl /Fohoge.exe hoge.obj json.lib

clean :
    del /Q *.obj *.lib
あと、サンプル「hoge.c」 #include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

#include "json.h"

int main(int argc, char **argv)
{
    struct json_object *obj;
    int i;

    obj = json_tokener_parse("[1,2,3]");
    for(i=0; i < json_object_array_length(obj); i++) {
        struct json_object *a = json_object_array_get_idx(obj, i);
        printf("\t[%d]=%s\n", i, json_object_to_json_string(a));
    }
    obj = json_tokener_parse("{'a':1,'b':2,'c':3}");
    json_object_object_foreach(obj, key, val) {
        printf("\t%s: %s\n", key, json_object_to_json_string(val));
    }

    return 0;
}
「hoge.c」の実行結果は     [0]=1
    [1]=2
    [2]=3
    a: 1
    b: 2
    c: 3
こんな感じ。
うむ。これでgtkwassrにTODO機能が付けれるかも...
Posted at by




あわせて読みたいがRSSとJSONを出されている様です。
試しに使ってみました。
コードはこんな感じ。
<script type="text/javascript"><!--
function awasete_yomitai(data) {
    var d = document;
    var container = d.getElementById('awasete_content');
    while(container.hasChildNodes())
        container.removeChild(container.firstChild);

    var ol = d.createElement('ol');
    for(var n = 0; n < data.length; n++) {
        var li = d.createElement('li');
        var favicon = d.createElement('img');
        favicon.src = data[n].favicon;
        li.appendChild(favicon);
        li.appendChild(d.createTextNode(' '));
        var anchor = d.createElement('a');
        anchor.appendChild(d.createTextNode(data[n].title));
        anchor.href = data[n].url;
        li.appendChild(anchor);
        li.appendChild(d.createTextNode(' '));
        var awasete = d.createElement('a');
        awasete.appendChild(d.createTextNode('[ナビゲーション]'));
        awasete.href = data[n].navigation;
        li.appendChild(awasete);
        li.appendChild(d.createTextNode(' '));
        var more = d.createElement('a');
        more.appendChild(d.createTextNode('[もっと見る]'));
        more.href = data[n].more;
        li.appendChild(more);
        ol.appendChild(li);
    }
    container.appendChild(ol);
}
function awasete_yomitai_do(url) {
    var s = document.createElement('script');
    s.charset = 'utf-8';
    s.src = 'http://api.awasete.com/showjson.phtml?u=' + encodeURIComponent(url);
    document.body.appendChild(s);
}
--></script>
<a href="javascript:awasete_yomitai_do('http://mattn.kaoriya.net');void 0">あわせて読みたい</a>
<div id="awasete_content"></div>
実行確認。
[あわせて読みたい]を表示

callback指定出来ないのが少し悲しい。
Posted at by



2008/02/06


たぶんこんなんでいけるはず。
Control-C - ロックスターになりたい
あと日本語文字化けする。VBからSJISで送ってサーバでutf8で読んでるとかだろうか。
パッチ
diff -u winsource.orig/modUrlEncode.bas winsource/modUrlEncode.bas
--- winsource.orig/modUrlEncode.bas Tue Jan 08 02:14:04 2008
+++ winsource/modUrlEncode.bas  Wed Feb 06 18:12:35 2008
@@ -1,6 +1,57 @@
 Attribute VB_Name = "modUrlEncode"
 Option Explicit
 
+Private Declare Function WideCharToMultiByte Lib "kernel32" ( _
+    ByVal CodePage As Long, _
+    ByVal dwFlags As Long, _
+    ByVal lpWideCharStr As Long, _
+    ByVal cchWideChar As Long, _
+    ByRef lpMultiByteStr As Any, _
+    ByVal cchMultiByte As Long, _
+    ByVal lpDefaultChar As String, _
+    ByVal lpUsedDefaultChar As Long) As Long
+    
+Private Const CP_UTF8 = 65001
+
+Private Function EncodeUTF8(ByRef strUni As String) As Byte()
+    On Error GoTo ErrHandler
+
+    Dim lngUniLen As Long
+    Dim lngBufLen As Long
+    Dim lngRtn As Long
+    Dim bytOut() As Byte
+
+    lngUniLen = Len(strUni)
+    If lngUniLen = 0 Then
+        Exit Function
+    End If
+    lngBufLen = lngUniLen * 5
+    ReDim bytOut(lngBufLen - 1)
+    lngRtn = WideCharToMultiByte( _
+        CP_UTF8, _
+        0, _
+        StrPtr(strUni), _
+        lngUniLen, _
+        bytOut(0), _
+        lngBufLen, _
+        vbNullString, _
+        0)
+    If lngRtn Then
+        ReDim Preserve bytOut(lngRtn - 1)
+        EncodeUTF8 = bytOut
+    End If
+    
+    Exit Function
+ErrHandler:
+End Function
+
+Private Function SafeUBound(ByRef arr() As Byte) As Long
+    On Error Resume Next
+    Dim lngLen As Long
+    lngLen = UBound(arr) - LBound(arr) + 1
+    SafeUBound = lngLen
+End Function
+
 Public Function UrlEncode(ByRef strSource As String) As String
 
  Dim lngLength As Long                                          '???????(S-JIS ???)?????
@@ -11,10 +62,13 @@
  Dim lngReadCount As Long                                       'bytSource ??????????
  Dim lngWriteCount As Long                                      'strBuffer ??????????
  
-    lngLength = LenB(StrConv(strSource, vbFromUnicode))         'ANSI/S-JIS ???????????
-    If Not CBool(lngLength) Then Exit Function                  '0 ????????????
-    ReDim bytSource(lngLength - 1)                              'ANSI/S-JIS ???????????????
-    bytSource = StrConv(strSource, vbFromUnicode)               'ANSI/S-JIS ???? bytSource ???
+    'lngLength = LenB(StrConv(strSource, vbFromUnicode))         'ANSI/S-JIS ???????????
+    'If Not CBool(lngLength) Then Exit Function                  '0 ????????????
+    'ReDim bytSource(lngLength - 1)                              'ANSI/S-JIS ???????????????
+    'bytSource = StrConv(strSource, vbFromUnicode)               'ANSI/S-JIS ???? bytSource ???
+    bytSource = EncodeUTF8(strSource)
+    lngLength = SafeUBound(bytSource)
+    If Not CBool(lngLength) Then Exit Function
    
     strBuffer = String$(lngLength * 3, vbNullChar)              'URL ???????????????????
     strSingleHex = "%00"                                        '16 ?????????????????????

あ、Control-Cのアカウント持ってなかった
Posted at by