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/01/31


その1 3桁ごとに区切る - PleasureDelayerDiary はてなブックマーク数


Number.prototype.split3_1 = function() {
    var r = ""; 
    var s = this.toString().split("").reverse();
    for(var i = 0; i < s.length; i++) {
        if(i % 3 == 0 && i != 0 && s[i] != "-") {
            r = s[i] + "," + r
        } else {
            r = s[i] + r;
        }
    }  
    return r;
}

その2 iandeth. - javascriptで数値をカンマ区切り文字列に変換する関数メモ はてなブックマーク数


Number.prototype.split3_2 = function () {
    var to = String(this);
    var tmp = "";
    while (to != (tmp = to.replace(/^([+-]?\d+)(\d\d\d)/,"$1,$2"))){
        to = tmp;
    }
    return to;
}

その3 JavaScriptで数値を3桁ごとに区切る - 0x集積蔵 はてなブックマーク数


Number.prototype.split3_3 = function() {
    var m = (this &lt; 0) ? -1 : 1;
    var str = String(this*m).split('.');
    var arr = String(str[0]).split(''), len = Math.ceil(arr.length/3), res = [];
    for (var i =0;i&lt;len;++i) res.push(arr.splice(-3,3).join(''));
    return (m == -1 ? '-' : '') + res.reverse().join(',') + (str[1] ? '.' + str[1] : '');
};

その4 [JavaScript]数値を3桁ごとに区切る はてなブックマーク数


Number.prototype.split3_ore = function() {
  ('' + this).match(/(-?)([0-9]+)(\.[0-9]*)?/);
  var sp = [RegExp.$1, RegExp.$2, RegExp.$3];
  var x = Math.floor(sp[1].length / 3) * 3;
  var len = sp[1].length;
  return sp[0] + (sp[1].substr(0, len - x)) + (len - x == 0 ? '' : ',') +
         (sp[1].substr(len - x, x).match(/[0-9]{3}/g).join(',')) + sp[2];
}
私ならこう書く。
Number.prototype.split3 = function() {
  var r = "", s = this.toString().split("").reverse().join("").replace(/\d{3}/g,
    function(v){r+=v+',';return ''});
  return (r + s).split("").reverse().join("");
}
alert((1000000).split3()) // 1,000,000
文字列を逆にして、replaceに指定した関数で3桁毎にカンマを入れた結果と、空で置換したsubstituteの結果(あまった結果)を足す。その後文字列を逆にして戻す。
マイナスもたぶんOK。


追記1
しまった。チェック甘すぎ。
Number.prototype.split3 = function() {
  var r = "", s = this.toString().split("").reverse().join("").replace(/\d{3}/g,
    function(v){r+=v+',';return ''});
  if (!s.match(/\d/)) r = r.substr(0, r.length-1);
  return (r + s).split("").reverse().join("");
}
計測してみる!
mattnおそ!www
関数呼び出しコストか?
追記2
うむ。小数か...
Number.prototype.split3_mattn2 = function() {
  var r = '', s = this.toString();
  s.match(/(-?)([0-9]+)(\.[0-9]*)?/);
  var sp = [RegExp.$1, s = parseInt(RegExp.$2), RegExp.$3];
  while(s >= 1000) {
    r = ',' + (s%1000) + r;
    s = parseInt(s/1000);
  }
  return sp[0] + s + r + sp[2];
}
-12345678.2356を3桁ごとに区切るテスト

タイム測定



うむ。それでも遅い。
Posted at by