[前][次][番号順一覧][スレッド一覧]

ruby-changes:22922

From: naruse <ko1@a...>
Date: Sun, 11 Mar 2012 22:36:22 +0900 (JST)
Subject: [ruby-changes:22922] naruse:r34971 (trunk): * ext/json: Merge 164a75c8bd2007d32c4d7665d53140d8fc126dcd.

naruse	2012-03-11 22:36:06 +0900 (Sun, 11 Mar 2012)

  New Revision: 34971

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=34971

  Log:
    * ext/json: Merge 164a75c8bd2007d32c4d7665d53140d8fc126dcd.
      [ruby-core:41917] [Bug #5846]

  Modified files:
    trunk/ChangeLog
    trunk/ext/json/generator/extconf.rb
    trunk/ext/json/generator/generator.c
    trunk/ext/json/generator/generator.h
    trunk/ext/json/lib/json/add/core.rb
    trunk/ext/json/lib/json/common.rb
    trunk/ext/json/lib/json/ext.rb
    trunk/ext/json/lib/json/version.rb
    trunk/ext/json/parser/extconf.rb
    trunk/ext/json/parser/parser.c
    trunk/ext/json/parser/parser.h
    trunk/ext/json/parser/parser.rl
    trunk/test/json/test_json.rb
    trunk/test/json/test_json_addition.rb
    trunk/test/json/test_json_generate.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 34970)
+++ ChangeLog	(revision 34971)
@@ -1,3 +1,8 @@
+Sun Mar 11 22:32:43 2012  NARUSE, Yui  <naruse@r...>
+
+	* ext/json: Merge 164a75c8bd2007d32c4d7665d53140d8fc126dcd.
+	  [ruby-core:41917] [Bug #5846]
+
 Sun Mar 11 17:10:04 2012  Shota Fukumori  <sorah@t...>
 
 	* lib/test/unit.rb: Put error message into STDERR if failed to launch
Index: ext/json/generator/generator.c
===================================================================
--- ext/json/generator/generator.c	(revision 34970)
+++ ext/json/generator/generator.c	(revision 34971)
@@ -1,3 +1,4 @@
+#include "../fbuffer/fbuffer.h"
 #include "generator.h"
 
 #ifdef HAVE_RUBY_ENCODING_H
@@ -14,7 +15,8 @@
 static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
           i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
           i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
-          i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth, i_dup;
+          i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
+          i_buffer_initial_length, i_dup;
 
 /*
  * Copyright 2001-2004 Unicode, Inc.
@@ -292,123 +294,6 @@
   return result;
 }
 
-/* fbuffer implementation */
-
-static FBuffer *fbuffer_alloc()
-{
-    FBuffer *fb = ALLOC(FBuffer);
-    memset((void *) fb, 0, sizeof(FBuffer));
-    fb->initial_length = FBUFFER_INITIAL_LENGTH;
-    return fb;
-}
-
-static FBuffer *fbuffer_alloc_with_length(unsigned long initial_length)
-{
-    FBuffer *fb;
-    assert(initial_length > 0);
-    fb = ALLOC(FBuffer);
-    memset((void *) fb, 0, sizeof(FBuffer));
-    fb->initial_length = initial_length;
-    return fb;
-}
-
-static void fbuffer_free(FBuffer *fb)
-{
-    if (fb->ptr) ruby_xfree(fb->ptr);
-    ruby_xfree(fb);
-}
-
-static void fbuffer_clear(FBuffer *fb)
-{
-    fb->len = 0;
-}
-
-static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
-{
-    unsigned long required;
-
-    if (!fb->ptr) {
-        fb->ptr = ALLOC_N(char, fb->initial_length);
-        fb->capa = fb->initial_length;
-    }
-
-    for (required = fb->capa; requested > required - fb->len; required <<= 1);
-
-    if (required > fb->capa) {
-        REALLOC_N(fb->ptr, char, required);
-        fb->capa = required;
-    }
-}
-
-static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
-{
-    if (len > 0) {
-        fbuffer_inc_capa(fb, len);
-        MEMCPY(fb->ptr + fb->len, newstr, char, len);
-        fb->len += len;
-    }
-}
-
-static void fbuffer_append_str(FBuffer *fb, VALUE str)
-{
-    const char *newstr = StringValuePtr(str);
-    unsigned long len = RSTRING_LEN(str);
-
-    RB_GC_GUARD(str);
-
-    fbuffer_append(fb, newstr, len);
-}
-
-static void fbuffer_append_char(FBuffer *fb, char newchr)
-{
-    fbuffer_inc_capa(fb, 1);
-    *(fb->ptr + fb->len) = newchr;
-    fb->len++;
-}
-
-static void freverse(char *start, char *end)
-{
-    char c;
-
-    while (end > start) {
-        c = *end, *end-- = *start, *start++ = c;
-    }
-}
-
-static long fltoa(long number, char *buf)
-{
-    static char digits[] = "0123456789";
-    long sign = number;
-    char* tmp = buf;
-
-    if (sign < 0) number = -number;
-    do *tmp++ = digits[number % 10]; while (number /= 10);
-    if (sign < 0) *tmp++ = '-';
-    freverse(buf, tmp - 1);
-    return tmp - buf;
-}
-
-static void fbuffer_append_long(FBuffer *fb, long number)
-{
-    char buf[20];
-    unsigned long len = fltoa(number, buf);
-    fbuffer_append(fb, buf, len);
-}
-
-static FBuffer *fbuffer_dup(FBuffer *fb)
-{
-    unsigned long len = fb->len;
-    FBuffer *result;
-
-    if (len > 0) {
-        result = fbuffer_alloc_with_length(len);
-        fbuffer_append(result, FBUFFER_PAIR(fb));
-    } else {
-        result = fbuffer_alloc();
-    }
-    return result;
-}
-
 /*
  * Document-module: JSON::Ext::Generator
  *
@@ -694,6 +579,16 @@
             state->depth = 0;
         }
     }
+    tmp = ID2SYM(i_buffer_initial_length);
+    if (option_given_p(opts, tmp)) {
+        VALUE buffer_initial_length = rb_hash_aref(opts, tmp);
+        if (RTEST(buffer_initial_length)) {
+            long initial_length;
+            Check_Type(buffer_initial_length, T_FIXNUM);
+            initial_length = FIX2LONG(buffer_initial_length);
+            if (initial_length > 0) state->buffer_initial_length = initial_length;
+        }
+    }
     tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
     state->allow_nan = RTEST(tmp);
     tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
@@ -723,6 +618,7 @@
     rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
     rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
     rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
+    rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
     return result;
 }
 
@@ -920,19 +816,20 @@
 
 static FBuffer *cState_prepare_buffer(VALUE self)
 {
-    FBuffer *buffer = fbuffer_alloc();
+    FBuffer *buffer;
     GET_STATE(self);
+    buffer = fbuffer_alloc(state->buffer_initial_length);
 
     if (state->object_delim) {
         fbuffer_clear(state->object_delim);
     } else {
-        state->object_delim = fbuffer_alloc_with_length(16);
+        state->object_delim = fbuffer_alloc(16);
     }
     fbuffer_append_char(state->object_delim, ',');
     if (state->object_delim2) {
         fbuffer_clear(state->object_delim2);
     } else {
-        state->object_delim2 = fbuffer_alloc_with_length(16);
+        state->object_delim2 = fbuffer_alloc(16);
     }
     fbuffer_append_char(state->object_delim2, ':');
     if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
@@ -940,21 +837,13 @@
     if (state->array_delim) {
         fbuffer_clear(state->array_delim);
     } else {
-        state->array_delim = fbuffer_alloc_with_length(16);
+        state->array_delim = fbuffer_alloc(16);
     }
     fbuffer_append_char(state->array_delim, ',');
     if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
     return buffer;
 }
 
-static VALUE fbuffer_to_s(FBuffer *fb)
-{
-    VALUE result = rb_str_new(FBUFFER_PAIR(fb));
-    fbuffer_free(fb);
-    FORCE_UTF8(result);
-    return result;
-}
-
 static VALUE cState_partial_generate(VALUE self, VALUE obj)
 {
     FBuffer *buffer = cState_prepare_buffer(self);
@@ -1003,12 +892,15 @@
  *   encountered. This options defaults to false.
  * * *quirks_mode*: Enables quirks_mode for parser, that is for example
  *   generating single JSON values instead of documents is possible.
+ * * *buffer_initial_length*: sets the initial length of the generator's
+ *   internal buffer.
  */
 static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
 {
     VALUE opts;
     GET_STATE(self);
     state->max_nesting = 19;
+    state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
     rb_scan_args(argc, argv, "01", &opts);
     if (!NIL_P(opts)) cState_configure(self, opts);
     return self;
@@ -1349,12 +1241,42 @@
 {
     GET_STATE(self);
     Check_Type(depth, T_FIXNUM);
-    return state->depth = FIX2LONG(depth);
+    state->depth = FIX2LONG(depth);
+    return Qnil;
 }
 
 /*
+ * call-seq: buffer_initial_length
  *
+ * This integer returns the current inital length of the buffer.
  */
+static VALUE cState_buffer_initial_length(VALUE self)
+{
+    GET_STATE(self);
+    return LONG2FIX(state->buffer_initial_length);
+}
+
+/*
+ * call-seq: buffer_initial_length=(length)
+ *
+ * This sets the initial length of the buffer to +length+, if +length+ > 0,
+ * otherwise its value isn't changed.
+ */
+static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
+{
+    long initial_length;
+    GET_STATE(self);
+    Check_Type(buffer_initial_length, T_FIXNUM);
+    initial_length = FIX2LONG(buffer_initial_length);
+    if (initial_length > 0) {
+        state->buffer_initial_length = initial_length;
+    }
+    return Qnil;
+}
+
+/*
+ *
+ */
 void Init_generator()
 {
     rb_require("json/common");
@@ -1391,6 +1313,8 @@
     rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
     rb_define_method(cState, "depth", cState_depth, 0);
     rb_define_method(cState, "depth=", cState_depth_set, 1);
+    rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
+    rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
     rb_define_method(cState, "configure", cState_configure, 1);
     rb_define_alias(cState, "merge", "configure");
     rb_define_method(cState, "to_h", cState_to_h, 0);
@@ -1438,6 +1362,7 @@
     i_ascii_only = rb_intern("ascii_only");
     i_quirks_mode = rb_intern("quirks_mode");
     i_depth = rb_intern("depth");
+    i_buffer_initial_length = rb_intern("buffer_initial_length");
     i_pack = rb_intern("pack");
     i_unpack = rb_intern("unpack");
     i_create_id = rb_intern("create_id");
Index: ext/json/generator/extconf.rb
===================================================================
--- ext/json/generator/extconf.rb	(revision 34970)
+++ ext/json/generator/extconf.rb	(revision 34971)
@@ -1,10 +1,3 @@
 require 'mkmf'
-require 'rbconfig'
 
-if RUBY_VERSION < "1.9"
-  have_header("re.h")
-else
-  have_header("ruby/re.h")
-  have_header("ruby/encoding.h")
-end
 create_makefile 'json/ext/generator'
Index: ext/json/generator/generator.h
===================================================================
--- ext/json/generator/generator.h	(revision 34970)
+++ ext/json/generator/generator.h	(revision 34971)
@@ -7,21 +7,12 @@
 
 #include "ruby.h"
 
-#if HAVE_RUBY_RE_H
+#ifdef HAVE_RUBY_RE_H
 #include "ruby/re.h"
-#endif
-
-#if HAVE_RE_H
+#else
 #include "re.h"
 #endif
 
-#ifdef HAVE_RUBY_ENCODING_H
-#include "ruby/encoding.h"
-#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
-#else
-#define FORCE_UTF8(obj)
-#endif
-
 #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
 
 #ifndef RHASH_SIZE
@@ -45,38 +36,6 @@
 #define RSTRING_LEN(string) RSTRING(string)->len
 #endif
 
-/* We don't need to guard objects for rbx, so let's do nothing at all. */
-#ifndef RB_GC_GUARD
-#define RB_GC_GUARD(object)
-#endif
-
-/* fbuffer implementation */
-
-typedef struct FBufferStruct {
-    unsigned long initial_length;
-    char *ptr;
-    unsigned long len;
-    unsigned long capa;
-} FBuffer;
-
-#define FBUFFER_INITIAL_LENGTH 4096
-
-#define FBUFFER_PTR(fb) (fb->ptr)
-#define FBUFFER_LEN(fb) (fb->len)
-#define FBUFFER_CAPA(fb) (fb->capa)
-#define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
-
-static char *fstrndup(const char *ptr, unsigned long len);
-static FBuffer *fbuffer_alloc();
-static FBuffer *fbuffer_alloc_with_length(unsigned long initial_length);
-static void fbuffer_free(FBuffer *fb);
-static void fbuffer_clear(FBuffer *fb);
-static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
-static void fbuffer_append_long(FBuffer *fb, long number);
-static void fbuffer_append_char(FBuffer *fb, char newchr);
-static FBuffer *fbuffer_dup(FBuffer *fb);
-static VALUE fbuffer_to_s(FBuffer *fb);
-
 /* unicode defintions */
 
 #define UNI_STRICT_CONVERSION 1
@@ -106,6 +65,7 @@
 static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
 static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
 static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
+static char *fstrndup(const char *ptr, unsigned long len);
 
 /* ruby api and some helpers */
 
@@ -128,6 +88,7 @@
     char ascii_only;
     char quirks_mode;
     long depth;
+    long buffer_initial_length;
 } JSON_Generator_State;
 
 #define GET_STATE(self)                       \
Index: ext/json/lib/json/ext.rb
===================================================================
--- ext/json/lib/json/ext.rb	(revision 34970)
+++ ext/json/lib/json/ext.rb	(revision 34971)
@@ -1,3 +1,9 @@
+if ENV['SIMPLECOV_COVERAGE'].to_i == 1
+  require 'simplecov'
+  SimpleCov.start do
+    add_filter "/tests/"
+  end
+end
 require 'json/common'
 
 module JSON
Index: ext/json/lib/json/version.rb
===================================================================
--- ext/json/lib/json/version.rb	(revision 34970)
+++ ext/json/lib/json/version.rb	(revision 34971)
@@ -1,6 +1,6 @@
 module JSON
   # JSON version
-  VERSION         = '1.5.4'
+  VERSION         = '1.6.6'
   VERSION_ARRAY   = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
   VERSION_MAJOR   = VERSION_ARRAY[0] # :nodoc:
   VERSION_MINOR   = VERSION_ARRAY[1] # :nodoc:
Index: ext/json/lib/json/add/core.rb
===================================================================
--- ext/json/lib/json/add/core.rb	(revision 34970)
+++ ext/json/lib/json/add/core.rb	(revision 34971)
@@ -1,243 +1,11 @@
-# This file contains implementations of ruby core's custom objects for
+# This file requires the implementations of ruby core's custom objects for
 # serialisation/deserialisation.
 
-unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
-  require 'json'
-end
-require 'date'
-
-# Symbol serialization/deserialization
-class Symbol
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id => self.class.name,
-      's'            => to_s,
-    }
-  end
-
-  # Stores class name (Symbol) with String representation of Symbol as a JSON string.
-  def to_json(*a)
-    as_json.to_json(*a)
-  end
-
-  # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
-  def self.json_create(o)
-    o['s'].to_sym
-  end
-end
-
-# Time serialization/deserialization
-class Time
-
-  # Deserializes JSON string by converting time since epoch to Time
-  def self.json_create(object)
-    if usec = object.delete('u') # used to be tv_usec -> tv_nsec
-      object['n'] = usec * 1000
-    end
-    if respond_to?(:tv_nsec)
-      at(*object.values_at('s', 'n'))
-    else
-      at(object['s'], object['n'] / 1000)
-    end
-  end
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id => self.class.name,
-      's'            => tv_sec,
-      'n'            => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
-    }
-  end
-
-  # Stores class name (Time) with number of seconds since epoch and number of
-  # microseconds for Time as JSON string
-  def to_json(*args)
-    as_json.to_json(*args)
-  end
-end
-
-# Date serialization/deserialization
-class Date
-
-  # Deserializes JSON string by converting Julian year <tt>y</tt>, month
-  # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
-  def self.json_create(object)
-    civil(*object.values_at('y', 'm', 'd', 'sg'))
-  end
-
-  alias start sg unless method_defined?(:start)
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id => self.class.name,
-      'y' => year,
-      'm' => month,
-      'd' => day,
-      'sg' => start,
-    }
-  end
-
-  # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
-  # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
-  def to_json(*args)
-    as_json.to_json(*args)
-  end
-end
-
-# DateTime serialization/deserialization
-class DateTime
-
-  # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
-  # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
-  # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
-  def self.json_create(object)
-    args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
-    of_a, of_b = object['of'].split('/')
-    if of_b and of_b != '0'
-      args << Rational(of_a.to_i, of_b.to_i)
-    else
-      args << of_a
-    end
-    args << object['sg']
-    civil(*args)
-  end
-
-  alias start sg unless method_defined?(:start)
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id => self.class.name,
-      'y' => year,
-      'm' => month,
-      'd' => day,
-      'H' => hour,
-      'M' => min,
-      'S' => sec,
-      'of' => offset.to_s,
-      'sg' => start,
-    }
-  end
-
-  # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
-  # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
-  # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
-  def to_json(*args)
-    as_json.to_json(*args)
-  end
-end
-
-# Range serialization/deserialization
-class Range
-
-  # Deserializes JSON string by constructing new Range object with arguments
-  # <tt>a</tt> serialized by <tt>to_json</tt>.
-  def self.json_create(object)
-    new(*object['a'])
-  end
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id  => self.class.name,
-      'a'             => [ first, last, exclude_end? ]
-    }
-  end
-
-  # Stores class name (Range) with JSON array of arguments <tt>a</tt> which
-  # include <tt>first</tt> (integer), <tt>last</tt> (integer), and
-  # <tt>exclude_end?</tt> (boolean) as JSON string.
-  def to_json(*args)
-    as_json.to_json(*args)
-  end
-end
-
-# Struct serialization/deserialization
-class Struct
-
-  # Deserializes JSON string by constructing new Struct object with values
-  # <tt>v</tt> serialized by <tt>to_json</tt>.
-  def self.json_create(object)
-    new(*object['v'])
-  end
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    klass = self.class.name
-    klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
-    {
-      JSON.create_id => klass,
-      'v'            => values,
-    }
-  end
-
-  # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
-  # Only named structs are supported.
-  def to_json(*args)
-    as_json.to_json(*args)
-  end
-end
-
-# Exception serialization/deserialization
-class Exception
-
-  # Deserializes JSON string by constructing new Exception object with message
-  # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt>
-  def self.json_create(object)
-    result = new(object['m'])
-    result.set_backtrace object['b']
-    result
-  end
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id => self.class.name,
-      'm'            => message,
-      'b'            => backtrace,
-    }
-  end
-
-  # Stores class name (Exception) with message <tt>m</tt> and backtrace array
-  # <tt>b</tt> as JSON string
-  def to_json(*args)
-    as_json.to_json(*args)
-  end
-end
-
-# Regexp serialization/deserialization
-class Regexp
-
-  # Deserializes JSON string by constructing new Regexp object with source
-  # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
-  # <tt>to_json</tt>
-  def self.json_create(object)
-    new(object['s'], object['o'])
-  end
-
-  # Returns a hash, that will be turned into a JSON object and represent this
-  # object.
-  def as_json(*)
-    {
-      JSON.create_id => self.class.name,
-      'o'            => options,
-      's'            => source,
-    }
-  end
-
-  # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
-  # (Regexp or String) as JSON string
-  def to_json(*)
-    as_json.to_json
-  end
-end
+require 'json/add/date'
+require 'json/add/date_time'
+require 'json/add/exception'
+require 'json/add/range'
+require 'json/add/regexp'
+require 'json/add/struct'
+require 'json/add/symbol'
+require 'json/add/time'
Index: ext/json/lib/json (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]