'configure.in'
],
{
- '_LT_AC_TAGCONFIG' => 1,
'AM_PROG_F77_C_O' => 1,
- 'AC_INIT' => 1,
+ '_LT_AC_TAGCONFIG' => 1,
'm4_pattern_forbid' => 1,
- 'AC_CANONICAL_TARGET' => 1,
+ 'AC_INIT' => 1,
'_AM_COND_IF' => 1,
- 'AC_CONFIG_LIBOBJ_DIR' => 1,
+ 'AC_CANONICAL_TARGET' => 1,
'AC_SUBST' => 1,
- 'AC_CANONICAL_HOST' => 1,
+ 'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_FC_SRCEXT' => 1,
+ 'AC_CANONICAL_HOST' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
- 'AC_REQUIRE_AUX_FILE' => 1,
'AC_CONFIG_LINKS' => 1,
- 'LT_SUPPORTED_TAG' => 1,
+ 'AC_REQUIRE_AUX_FILE' => 1,
'm4_sinclude' => 1,
+ 'LT_SUPPORTED_TAG' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'_m4_warn' => 1,
'AC_CANONICAL_BUILD' => 1,
'AC_FC_FREEFORM' => 1,
'AH_OUTPUT' => 1,
- 'AC_CONFIG_AUX_DIR' => 1,
'_AM_SUBST_NOTMAKE' => 1,
- 'm4_pattern_allow' => 1,
- 'AM_PROG_CC_C_O' => 1,
+ 'AC_CONFIG_AUX_DIR' => 1,
'sinclude' => 1,
- 'AM_CONDITIONAL' => 1,
+ 'AM_PROG_CC_C_O' => 1,
+ 'm4_pattern_allow' => 1,
'AC_CANONICAL_SYSTEM' => 1,
+ 'AM_CONDITIONAL' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'm4_include' => 1,
'configure.in'
],
{
- '_LT_AC_TAGCONFIG' => 1,
'AM_PROG_F77_C_O' => 1,
- 'AC_INIT' => 1,
+ '_LT_AC_TAGCONFIG' => 1,
'm4_pattern_forbid' => 1,
- '_AM_COND_IF' => 1,
+ 'AC_INIT' => 1,
'AC_CANONICAL_TARGET' => 1,
- 'AC_SUBST' => 1,
+ '_AM_COND_IF' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
- 'AC_FC_SRCEXT' => 1,
+ 'AC_SUBST' => 1,
'AC_CANONICAL_HOST' => 1,
+ 'AC_FC_SRCEXT' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
- 'AC_REQUIRE_AUX_FILE' => 1,
'AC_CONFIG_LINKS' => 1,
- 'm4_sinclude' => 1,
+ 'AC_REQUIRE_AUX_FILE' => 1,
'LT_SUPPORTED_TAG' => 1,
+ 'm4_sinclude' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'_m4_warn' => 1,
'AC_CANONICAL_BUILD' => 1,
'AC_FC_FREEFORM' => 1,
'AH_OUTPUT' => 1,
- '_AM_SUBST_NOTMAKE' => 1,
'AC_CONFIG_AUX_DIR' => 1,
- 'sinclude' => 1,
- 'm4_pattern_allow' => 1,
+ '_AM_SUBST_NOTMAKE' => 1,
'AM_PROG_CC_C_O' => 1,
- 'AC_CANONICAL_SYSTEM' => 1,
+ 'm4_pattern_allow' => 1,
+ 'sinclude' => 1,
'AM_CONDITIONAL' => 1,
+ 'AC_CANONICAL_SYSTEM' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'm4_include' => 1,
config.status:777: creating src/test/Makefile
config.status:1051: executing depfiles commands
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status src/Makefile
+
+on vaio_z
+
+config.status:777: creating src/Makefile
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status src/test/Makefile depfiles
+
+on vaio_z
+
+config.status:777: creating src/test/Makefile
+config.status:1051: executing depfiles commands
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status Makefile
+
+on vaio_z
+
+config.status:777: creating Makefile
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status src/Makefile
+
+on vaio_z
+
+config.status:777: creating src/Makefile
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status src/test/Makefile depfiles
+
+on vaio_z
+
+config.status:777: creating src/test/Makefile
+config.status:1051: executing depfiles commands
AM_CPPFLAGS = -Wall
LC_ALL=C
+SUBDIRS=./test
# bin_PROGRAMS = utakata
CONFIG_CLEAN_FILES =
SOURCES =
DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = -Wall
LC_ALL = C
-all: all-am
+SUBDIRS = ./test
+all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
tags: TAGS
-TAGS:
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
ctags: CTAGS
-CTAGS:
-
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|| exit 1; \
fi; \
done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
-check: check-am
+check: check-recursive
all-am: Makefile
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-installcheck: installcheck-am
+installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
+clean: clean-recursive
clean-am: clean-generic mostlyclean-am
-distclean: distclean-am
+distclean: distclean-recursive
-rm -f Makefile
-distclean-am: clean-am distclean-generic
+distclean-am: clean-am distclean-generic distclean-tags
-dvi: dvi-am
+dvi: dvi-recursive
dvi-am:
-html: html-am
+html: html-recursive
-info: info-am
+info: info-recursive
info-am:
install-data-am:
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
install-exec-am:
-install-html: install-html-am
+install-html: install-html-recursive
-install-info: install-info-am
+install-info: install-info-recursive
install-man:
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
-install-ps: install-ps-am
+install-ps: install-ps-recursive
installcheck-am:
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
-pdf: pdf-am
+pdf: pdf-recursive
pdf-am:
-ps: ps-am
+ps: ps-recursive
ps-am:
uninstall-am:
-.MAKE: install-am install-strip
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
-.PHONY: all all-am check check-am clean clean-generic distclean \
- distclean-generic distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic ctags \
+ ctags-recursive distclean distclean-generic distclean-tags \
+ distdir dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+ tags-recursive uninstall uninstall-am
# bin_PROGRAMS = utakata
// smart_ptr<CHoge> h(new CHoge());
//
// smart_ptr<CHoge> ha();
-// h.addArray(true,10);
-// h.addArray(new SHoge[10],true,10);
+// h.add(new CHuga);
#ifndef _UTAKATA_SRC_COMMON_SMART_PTR_H_
#define _UTAKATA_SRC_COMMON_SMART_PTR_H_
namespace utility {
-/**
- smart_ptr
- スマートポインタ。
- smart_ptr<CHoge> h(new CHoge);
- とやれば、後はコピーしても解体責任を委譲したりして、
- ちゃんとdeleteしてくれるようなクラス。
- また、配列もとれるようにして、配列であっても
- 通常のポインタであっても、ちゃんとdeleteとdelete[]を
- 分けてくれる。
-
- 配列を生成する際には、
-
-
- のようにする。
-*/
-template<class T>
-class smart_ptr {
+template<class T> class smart_ptr {
public:
-
- //暗黙の型変換を行わない。
- //このコンストラクタでは、配列の生成は出来ないことになっている。
- template<class S> explicit
- smart_ptr(S* p, bool owner = true, ref_delete_base* ref = NULL) :
- obj_(NULL),ref_obj_(NULL),index_(0) {
+ template<class S> explicit
+ smart_ptr(S* p, bool owner = true, ref_delete_base* ref = NULL) :
+ obj_(NULL),ref_obj_(NULL) {
if (p != NULL) {
- init(p,owner,1, ref);
+ init(p,owner, ref);
}
}
//デフォルトコンストラクタ
- smart_ptr() : obj_(NULL),ref_obj_(NULL),index_(0) {
- }
-
+ smart_ptr() : obj_(NULL),ref_obj_(NULL) {}
+
//コピーコンストラクタ
- smart_ptr(const smart_ptr<T>& p) :
- obj_(NULL),ref_obj_(NULL),index_(0) {
+ smart_ptr(const smart_ptr<T>& p) :
+ obj_(NULL),ref_obj_(NULL) {
//参照カウントを増やしつつ、コピー。
inc(p);
}
+ // 自分にコピーされる前に、前のオブジェクトの参照カウントを
+ // 減らしておく。
smart_ptr<T>& operator=(const smart_ptr<T>& obj) {
- // 自分にコピーされる前に、前のオブジェクトの参照カウントを
- // 減らしておく。
dec();
-
+
smart_ptr<T> tmp(obj);
swap(tmp);
return *this;
T& operator*() const {return *get();}
T* operator->() const {return get();}
- //擬似的な配列操作のため。
- smart_ptr<T>& operator++() {incIndex();return *this;}
- smart_ptr<T> operator++(int n) {
- smart_ptr<T> tmp(*this);
- incIndex();
- return tmp;
- }
- smart_ptr<T>& operator--() {decIndex();return *this;}
- smart_ptr<T> operator--(int n) {
- smart_ptr<T> tmp(*this);
- decIndex();
- return tmp;
- }
-
// 同一かどうかをチェックする。
- bool operator==(const smart_ptr<T>& rh)
- {
+ bool operator==(const smart_ptr<T>& rh) {
return obj_ == rh.obj_;
}
- bool operator!=(const smart_ptr<T>& rh)
- {
- return !(*this == rh);
+ bool operator!=(const smart_ptr<T>& rh) {
+ return !(*this.obj_ == rh.obj_);
}
- //配列からの取得のため。
- T& operator[](int n) const {return *get(n + 1);}
-
- /**
- get
- 保持するメモリから、指定された場所のメモリを取得する。
- @param int n デフォルトは1
- @access public
- @return 指定された位置のテンプレートで指定されたオブジェクト
- */
- T* get(int n = 1) const {
- //配列、単一変数どちらにでも対応するため、
- //引数で場所を取る。
-
-
+ // 現在保持しているポインタを明示的に返します。
+ T* get() const {
if (ref_obj_ == NULL) {
return NULL;
}
- if (index_ + n > ref_obj_->getMaxNum() || index_ + n < 0) {
- return NULL;
- }
-
- //取得すべきメモリは、
- //オブジェクトの先頭アドレス+オブジェクトのサイズ*(インデックス+引数)
- //なお、この際に、index_ = 0かつ、n = 1である場合、
- //先頭アドレス+オブジェクトサイズということになり、どう考えてもアクセス違反になる。
- return (T*)((unsigned char*)obj_ + (ref_obj_->getObjSize() * (index_ + n - 1)));
+ return obj_;
}
- //==============================================
- //疑似イテレーターとして使用するための関数群
- //==============================================
-
- /**
- isEnd
- インデックスが、限界に達していないかどうか
- ここで言う限界とは、MaxNumで、つまり添え字+1をさす。
- @access public
- @return bool 達している場合はtrue
- */
- bool isEnd() {
- if (ref_obj_ != NULL) {
- return ref_obj_->getMaxNum()-1 < index_?true:false;
- } else {
- return true;
- }
- }
-
- /**
- isBegin
- インデックスが、先頭であるかどうか
- @access public
- @return bool 先頭である場合はtrue
- */
- bool isBegin() {
- return index_ == 0?true:false;
- }
-
- /**
- オブジェクトがNULLかどうか
- @access public
- @return bool
- */
- bool isNull() const {
- return ref_obj_==NULL&&obj_==NULL?true:false;
+ // 内部で参照しているオブジェクトがNULLであるかどうかを返します。
+ bool is_null() const {
+ return ref_obj_ == NULL && obj_ == NULL;
}
// オブジェクトが単一の場所からのみ参照されているか。
- bool isOnlyRef() const {
- return ref_obj_->getRef() == 1 ? true : false;
- }
-
- /**
- end
- インデックスを、最後尾に位置させる
- @access public
- @return void
- */
- void end() {
- if (ref_obj_ != NULL) {
- index_ = ref_obj_->getMaxNum()-1;
- } else {
- index_ = 0;
- }
- }
-
- /**
- begin
- インデックスを、先頭に位置させる
- @access public
- @return void
- */
- void begin() {
- index_ = 0;
+ bool is_only_ref() const {
+ return ref_obj_->reference() == 1;
}
//=============================================
//追加生成関数群
//=============================================
- /**
- * @brief アップキャストを行う。SはTの派生クラスであること。
- * また、その特性上同一性チェックが困難であるので、こればかりは仕方がない。
- * @param const smart_ptr<S>& スマートポインタ
- * @return smart_ptr<T>& アップキャスト後の自身。
- */
+ // 渡されたsmart_ptrが格納しているオブジェクトを参照するようにします。
+ // テンプレートパラメータSは、Tの派生クラスである必要があります。
template<class S>
- smart_ptr<T>& upcast(const smart_ptr<S>& p) {
-
- if (reinterpret_cast<void*>(this) !=
- reinterpret_cast<void*>(const_cast<smart_ptr<S>*>(&p)) ) {
- //pがさすオブジェクトをこのオブジェクトもさすことになるので、
- //まずはdec
+ void upcast(const smart_ptr<S>& p) {
+ if (reinterpret_cast<void*>(this) != reinterpret_cast<void*>(&p)) {
dec();
-
- //あとはincとほぼ同じ処理になる。
- obj_ = p.getObj();
- ref_obj_ = p.getRefObj();
- index_ = p.getIndex();
+
+ obj_ = p.object();
+ ref_obj_ = p.ref_obj();
if (ref_obj_ != NULL) {
ref_obj_->inc_ref();
}
}
-
- return *this;
}
- /**
- * @brief 指定した型の追加生成構文
- * コンストラクタで何も指定しない場合、これを実行することで、再生成を行う。
- */
+ // 現在保持している型を新規に生成します。新規の生成では、デフォルトコ
+ // ンストラクタが使用されます。
void add() {
dec();
- init(new T, true, 1);
+ init(new T, true);
}
- /**
- add
- 新しく生成させる。
- 関数テンプレートを使ってはいるが、必ずTとおなじ、
- もしくはTの派生クラスであること。
- @param S* p 対象とするオブジェクト
- @param bool owner 所有権の有無
- @access public
- @return void
- */
+ // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
+ // ownerが指定されない場合、デフォルトで管理が行われます。
template<class S>
- void add(S* _p, bool owner = true) {
+ void add(S* object, bool owner = true) {
dec();
- if (_p != NULL) {
- init(_p,owner,1);
+ if (object != NULL) {
+ init(object, owner);
}
}
- /**
- * @brief デリータを指定した追加生成構文。
- * これは配列では使用できない。
- */
+ // 外部より明示的に新しい管理対象オブジェクトを渡して初期化を行います。
+ // ownerが指定されない場合、デフォルトで管理が行われます。
+ // 削除時には、渡されたdeleterによって処理が行われます。
template<class S>
- void add(S* _p, bool owner, ref_delete_base* ref) {
+ void add(S* _p, ref_delete_base* ref, bool owner = true) {
dec();
if (_p != NULL && ref != NULL) {
- init(_p, owner, 1, ref);
- }
- }
-
- /**
- addArray
- 配列オブジェクト生成関数
- 現在のオブジェクトの型を、指定個数作成する場合。
- @param bool owner 所有権の有無
- @param int n 個数
- @access public
- @return void
- */
- void addArray(bool owner, int n) {
- dec();
- if (n > 1) {
- init(new T[n], owner, n);
- } else if (n == 1) {
- init(new T, owner, 1);
+ init(_p, owner, ref);
}
}
- /**
- addArray
- 配列オブジェクト生成関数
- こちらは、配列オブジェクトを生成する際に使用される関数。
- @param S p 対象とするオブジェクト
- @param bool owner 所有権の有無
- @param int n 個数
- @access public
- @return void
- */
- template<class S>
- void addArray(S _p, bool owner, int n) {
- dec();
- if (n > 1) {
- init(new S[n], owner, n);
- }
- }
-
-
private:
- /**
- init
- スマートポインタの初期化補助関数
- 渡されたオブジェクトを元にして、所有権、
- 参照カウント、オブジェクトの個数を設定する。
- @param template _p 保持するべきオブジェクト
- @param bool owner 所有権の湯有無
- @param int n オブジェクトの個数
- @param ref_delete_base* ref デフォルトはNULL。外部からのコピーならば非NULL
- @access protected
- @return void
- */
+ // smart_ptrの初期化処理を行います。ref_delete_baseが指定されている場合
+ // には、渡されたオブジェクトが解体オブジェクトとして利用されます。
template<class S>
- void init(S* _p, bool owner, int n, ref_delete_base* ref = NULL) {
-
- index_ = 0;
+ void init(S* _p, bool owner, ref_delete_base* ref = NULL) {
obj_ = _p;
if (ref_obj_ != NULL) {
- //このとき、すでにdec_refとかはやってあることが前提。
ref_obj_ = NULL;
}
if (ref != NULL) {
ref_obj_ = ref;
} else if (owner) {
- if (n == 1) {
- //非配列オブジェクト
- ref_obj_ = new ref_noarray_object<S>(_p);
- } else if (n > 1){
- ref_obj_ = new ref_array_object<S>(_p);
- }
+ ref_obj_ = new ref_noarray_object<S>(_p);
} else {
- //非所有権オブジェクト
ref_obj_ = new ref_null_object<S>(_p);
}
- //オブジェクトの情報を追加
- ref_obj_->setRef(1);
- ref_obj_->setMaxNum(n);
- ref_obj_->setObjSize(sizeof(S));
- ref_obj_->setOwner(owner);
-
+ ref_obj_->set_reference(1);
+ ref_obj_->set_maxnum(1);
+ ref_obj_->set_objsize(sizeof(S));
+ ref_obj_->set_owner(owner);
}
- /**
- inc
- 渡されたsmart_ptrの参照数を一つ増やす。
- @param const smart_ptr<T>& p 参照カウントを増やすオブジェクト
- @access protected
- @return void
- */
+ // 渡されたsmart_ptrを参照するように変更し、参照数を加算します。
void inc(const smart_ptr<T>& p) {
- index_ = p.getIndex();
- ref_obj_ = p.getRefObj();
- obj_ = p.getObj();
-
+ swap(p);
if (ref_obj_ != NULL) {
ref_obj_->inc_ref();
}
}
- void swap(smart_ptr<T>& p)
- {
- // 対象となっているオブジェクトとデータを入れ替える。
- std::swap(index_, p.index_);
+ void swap(smart_ptr<T>& p) {
std::swap(ref_obj_, p.ref_obj_);
std::swap(obj_, p.obj_);
}
- /**
- dec
- 自分の分の参照カウントを減らす。
- 実行されたら、ref_obj_およびobj_は
- NULLになる。
- @access protected
- @return void
- */
+ // 現在自身が参照しているオブジェクトの参照数を減算し、
+ // オブジェクトの参照を初期化します。
+ // 参照数の減算時、参照数がゼロになった場合にのみ、ref_objをdeleteします。
void dec() {
- //dec_refは、オブジェクトを削除したかどうかを返す。
- //削除されている場合は、参照オブジェクトを削除しなければならない。
if (ref_obj_ != NULL) {
if (ref_obj_->dec_ref()) {
delete ref_obj_;
obj_ = NULL;
}
- /**
- incIndex
- インデックスカウントを増やす
- @access protected
- @return void
- */
- void incIndex() {index_++;}
-
- /**
- decIndex
- インデックスカウントを減らす
- @access protected
- @return void
- */
- void decIndex() {index_--;}
-
//========================================
//コピーの際に使用するconst関数群
//========================================
- /**
- getIndex
- 現在のインデックスを返す
- @access public
- @return int 現在のインデックス
- */
- int getIndex() const {return index_;}
-
- /**
- getRefObj
- 削除オブジェクトを返す
- @access public
- @return ref_delete_base* 削除オブジェクトのポインタ
- */
- ref_delete_base* getRefObj() const {return ref_obj_;}
-
- /**
- getObj
- オブジェクトを返す
- @access public
- @return T* オブジェクトのポインタ
- */
- T* getObj() const {return obj_;}
+ // 現在保持しているデリータを返します。
+ ref_delete_base* ref_obj() const {return ref_obj_;}
+
+ // 現在保持しているオブジェクトを返します
+ T* obj() const {return obj_;}
private:
T* obj_; //保持すべきオブジェクト。参照カウントオブジェクトと同一
ref_delete_base* ref_obj_; //参照カウントオブジェクト
-
- int index_; //現在のインデックス
-
};
}; // end of namespace utility
// このフロントエンドは、文字列・ファイル等からデータを読出すだけの
// 機能を持つ別のインターフェースと組み合わせ、ITranscoderを適用した
// データを取得します。
-#ifndef _UTAKATA_SRC_READER_H_
-#define _UTAKATA_SRC_READER_H_
+#ifndef _UTAKATA_SRC_ENCODING_READER_H_
+#define _UTAKATA_SRC_ENCODING_READER_H_
-#include <iostream>
#include <vector>
-#include <string>
-#include <exception>
#include "smart_ptr.h"
namespace reader {
-
+class IReader;
class EncodingReader {
- // 渡されたistreamから、Unicodeスカラー値を抽出する。
- // istreamからUnicodeスカラー値を抽出するのは、全て
- // Transcoderを介するようにする。
+ // 渡されたReaderからデータを読出す際に、ITranscoder::Encodeを利用して、
+ // バイナリデータを文字列として読み出します。
+ // 文字列として読出しますが、EncodingReaderから読出された時点で、全て
+ // unicode文字列として読出されます。
public:
// 利用するistreamを指定する。
- StreamReader(smart_ptr<std::istream>& s,
- const smart_ptr<transcoder::ITranscoder>& t);
- virtual ~StreamReader() {}
-
- virtual unsigned long read();
- virtual std::vector<unsigned long> read(size_t num);
+ StreamReader(const smart_ptr<reader::IReader>& reader,
+ const smart_ptr<transcoder::ITranscoder>& transcoder);
+ ~StreamReader() {}
- virtual unsigned long peek();
+ unsigned int Read();
+ std::vector<unsigned int> Read(size_t num);
- // 現在streamのどこまでを読んでいるのかを返す。
- virtual size_t pos() const;
+ // 一文字分だけ先読みして返します。
+ // 先読みのため、Readerの読み出し位置は更新されません。
+ unsigned int Peek();
- // 渡されたvectorをstreamに戻す。
- virtual void unget(unsigned long ch);
+ // 指定された文字の分だけ先読みして返します。
+ // 先読みのため、Readerの読み出し位置は更新されません。
+ // num以下の文字しか読出せなかった場合、読出せた分だけ返されます。
+ std::vector<unsigned int> Peek(size_t num);
- // 現在のportが終了時点かどうかを返す。
- virtual bool isEOF();
+ // 保持しているreaderが末尾に到達しているか返します。
+ bool IsEof() const;
private:
- // 内部のvalidチェックを行う。
- // validチェックは成功しない場合にはPortExceptionが発生する。
- void validate();
-
- smart_ptr<std::istream> stream_;
+ smart_ptr<reader::IReader> reader_;
smart_ptr<transcoder::ITranscoder> trans_;
-
- // 文字の変換単位で取得した文字の個数
- size_t pos_;
};
};
-
};
-#endif /* __HOME_DERUI_DEVELOP_UTAKATA_SRC_READER_H_ */
+#endif /* _UTAKATA_SRC_ENCODING_READER_H_ */
#ifndef _UTAKATA_SRC_READER_INTERFACE_H_
#define _UTAKATA_SRC_READER_INTERFACE_H_
+#include <string>
#include <vector>
#include <exception>
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
-bin_PROGRAMS = string_reader_test$(EXEEXT) file_reader_test$(EXEEXT)
+bin_PROGRAMS = string_reader_test$(EXEEXT) file_reader_test$(EXEEXT) \
+ utf8_transcoder_test$(EXEEXT)
subdir = src/test
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
string_reader.$(OBJEXT) gtest-all.$(OBJEXT)
string_reader_test_OBJECTS = $(am_string_reader_test_OBJECTS)
string_reader_test_LDADD = $(LDADD)
+am_utf8_transcoder_test_OBJECTS = utf8_transcoder.$(OBJEXT) \
+ utf8_transcoder_test.$(OBJEXT) string_reader.$(OBJEXT) \
+ gtest-all.$(OBJEXT)
+utf8_transcoder_test_OBJECTS = $(am_utf8_transcoder_test_OBJECTS)
+utf8_transcoder_test_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I. -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
CXXLD = $(CXX)
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
-o $@
-SOURCES = $(file_reader_test_SOURCES) $(string_reader_test_SOURCES)
+SOURCES = $(file_reader_test_SOURCES) $(string_reader_test_SOURCES) \
+ $(utf8_transcoder_test_SOURCES)
DIST_SOURCES = $(file_reader_test_SOURCES) \
- $(string_reader_test_SOURCES)
+ $(string_reader_test_SOURCES) $(utf8_transcoder_test_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
INCLUDES = -I$(top_srcdir) -Isrc/test/gtest/gtest.h
SRC_DIR = ..
LC_ALL = C
-
-# unicode_test_SOURCES = unicode_test.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp \
-# ${SRC_DIR}/reader.cpp
-# utf8_transcoder_test_SOURCES = utf8_transcoder_test.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/simpletest.cpp \
-# ${SRC_DIR}/reader.cpp
-# textarrayformat_test_SOURCES = textarrayformat_test.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/simpletest.cpp
-# lexer_test_SOURCES = ${SRC_DIR}/lexeme_id.h lexer_test.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/lexeme_impl.cpp \
-# ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/lexer.cpp ${SRC_DIR}/lexeme_data.cpp \
-# ${SRC_DIR}/reader.cpp
-# sublexer_test_SOURCES = sublexer_test.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/utf8_transcoder.cpp \
-# ${SRC_DIR}/lexeme_impl.cpp ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/lexeme_data.cpp
-# parser_test_SOURCES = parser_test.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/unicode.cpp \
-# ${SRC_DIR}/lexeme_impl.cpp ${SRC_DIR}/parser.cpp ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/lexer.cpp \
-# ${SRC_DIR}/parser_handler.cpp ${SRC_DIR}/reader.cpp ${SRC_DIR}/object.cpp ${SRC_DIR}/type.cpp ${SRC_DIR}/data_structure.cpp \
-# ${SRC_DIR}/primitive.cpp ${SRC_DIR}/lexeme_data.cpp ${SRC_DIR}/primitive_util.cpp ${SRC_DIR}/gc.cpp
-# environment_test_SOURCES = ${SRC_DIR}/environment.cpp environment_test.cpp ${SRC_DIR}/simpletest.cpp \
-# ${SRC_DIR}/unicode.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/object.cpp ${SRC_DIR}/type.cpp ${SRC_DIR}/data_structure.cpp
-# type_test_SOURCES = ${SRC_DIR}/type.cpp type_test.cpp ${SRC_DIR}/simpletest.cpp
-# bignum_test_SOURCES = ${SRC_DIR}/bignum.cpp bignum_test.cpp ${SRC_DIR}/simpletest.cpp
check_PROGRANS = $(bin_PROGRAMS)
TESTS = $(bin_PROGRAMS)
string_reader_test_SOURCES = string_reader_test.cpp ../string_reader.cpp gtest/gtest-all.cc
file_reader_test_SOURCES = file_reader_test.cpp ../file_reader.cpp gtest/gtest-all.cc
+utf8_transcoder_test_SOURCES = ../utf8_transcoder.cpp utf8_transcoder_test.cpp ../string_reader.cpp gtest/gtest-all.cc
all: all-am
.SUFFIXES:
string_reader_test$(EXEEXT): $(string_reader_test_OBJECTS) $(string_reader_test_DEPENDENCIES)
@rm -f string_reader_test$(EXEEXT)
$(CXXLINK) $(string_reader_test_OBJECTS) $(string_reader_test_LDADD) $(LIBS)
+utf8_transcoder_test$(EXEEXT): $(utf8_transcoder_test_OBJECTS) $(utf8_transcoder_test_DEPENDENCIES)
+ @rm -f utf8_transcoder_test$(EXEEXT)
+ $(CXXLINK) $(utf8_transcoder_test_OBJECTS) $(utf8_transcoder_test_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
include ./$(DEPDIR)/gtest-all.Po
include ./$(DEPDIR)/string_reader.Po
include ./$(DEPDIR)/string_reader_test.Po
+include ./$(DEPDIR)/utf8_transcoder.Po
+include ./$(DEPDIR)/utf8_transcoder_test.Po
.cc.o:
$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o string_reader.obj `if test -f '../string_reader.cpp'; then $(CYGPATH_W) '../string_reader.cpp'; else $(CYGPATH_W) '$(srcdir)/../string_reader.cpp'; fi`
+utf8_transcoder.o: ../utf8_transcoder.cpp
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_transcoder.o -MD -MP -MF $(DEPDIR)/utf8_transcoder.Tpo -c -o utf8_transcoder.o `test -f '../utf8_transcoder.cpp' || echo '$(srcdir)/'`../utf8_transcoder.cpp
+ mv -f $(DEPDIR)/utf8_transcoder.Tpo $(DEPDIR)/utf8_transcoder.Po
+# source='../utf8_transcoder.cpp' object='utf8_transcoder.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_transcoder.o `test -f '../utf8_transcoder.cpp' || echo '$(srcdir)/'`../utf8_transcoder.cpp
+
+utf8_transcoder.obj: ../utf8_transcoder.cpp
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_transcoder.obj -MD -MP -MF $(DEPDIR)/utf8_transcoder.Tpo -c -o utf8_transcoder.obj `if test -f '../utf8_transcoder.cpp'; then $(CYGPATH_W) '../utf8_transcoder.cpp'; else $(CYGPATH_W) '$(srcdir)/../utf8_transcoder.cpp'; fi`
+ mv -f $(DEPDIR)/utf8_transcoder.Tpo $(DEPDIR)/utf8_transcoder.Po
+# source='../utf8_transcoder.cpp' object='utf8_transcoder.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_transcoder.obj `if test -f '../utf8_transcoder.cpp'; then $(CYGPATH_W) '../utf8_transcoder.cpp'; else $(CYGPATH_W) '$(srcdir)/../utf8_transcoder.cpp'; fi`
+
.cpp.o:
$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
LC_ALL=C
# SIBDIRS = .
-bin_PROGRAMS = string_reader_test file_reader_test
-
-# unicode_test_SOURCES = unicode_test.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp \
-# ${SRC_DIR}/reader.cpp
-# utf8_transcoder_test_SOURCES = utf8_transcoder_test.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/simpletest.cpp \
-# ${SRC_DIR}/reader.cpp
-# textarrayformat_test_SOURCES = textarrayformat_test.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/simpletest.cpp
-# lexer_test_SOURCES = ${SRC_DIR}/lexeme_id.h lexer_test.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/lexeme_impl.cpp \
-# ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/lexer.cpp ${SRC_DIR}/lexeme_data.cpp \
-# ${SRC_DIR}/reader.cpp
-# sublexer_test_SOURCES = sublexer_test.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/utf8_transcoder.cpp \
-# ${SRC_DIR}/lexeme_impl.cpp ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/lexeme_data.cpp
-# parser_test_SOURCES = parser_test.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/unicode.cpp \
-# ${SRC_DIR}/lexeme_impl.cpp ${SRC_DIR}/parser.cpp ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/lexer.cpp \
-# ${SRC_DIR}/parser_handler.cpp ${SRC_DIR}/reader.cpp ${SRC_DIR}/object.cpp ${SRC_DIR}/type.cpp ${SRC_DIR}/data_structure.cpp \
-# ${SRC_DIR}/primitive.cpp ${SRC_DIR}/lexeme_data.cpp ${SRC_DIR}/primitive_util.cpp ${SRC_DIR}/gc.cpp
-# environment_test_SOURCES = ${SRC_DIR}/environment.cpp environment_test.cpp ${SRC_DIR}/simpletest.cpp \
-# ${SRC_DIR}/unicode.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/object.cpp ${SRC_DIR}/type.cpp ${SRC_DIR}/data_structure.cpp
-# type_test_SOURCES = ${SRC_DIR}/type.cpp type_test.cpp ${SRC_DIR}/simpletest.cpp
-# bignum_test_SOURCES = ${SRC_DIR}/bignum.cpp bignum_test.cpp ${SRC_DIR}/simpletest.cpp
+bin_PROGRAMS = string_reader_test file_reader_test utf8_transcoder_test
check_PROGRANS = $(bin_PROGRAMS)
TESTS = $(bin_PROGRAMS)
string_reader_test_SOURCES = string_reader_test.cpp ../string_reader.cpp gtest/gtest-all.cc
file_reader_test_SOURCES = file_reader_test.cpp ../file_reader.cpp gtest/gtest-all.cc
+utf8_transcoder_test_SOURCES = ../utf8_transcoder.cpp utf8_transcoder_test.cpp ../string_reader.cpp gtest/gtest-all.cc
\ No newline at end of file
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
-bin_PROGRAMS = string_reader_test$(EXEEXT) file_reader_test$(EXEEXT)
+bin_PROGRAMS = string_reader_test$(EXEEXT) file_reader_test$(EXEEXT) \
+ utf8_transcoder_test$(EXEEXT)
subdir = src/test
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
string_reader.$(OBJEXT) gtest-all.$(OBJEXT)
string_reader_test_OBJECTS = $(am_string_reader_test_OBJECTS)
string_reader_test_LDADD = $(LDADD)
+am_utf8_transcoder_test_OBJECTS = utf8_transcoder.$(OBJEXT) \
+ utf8_transcoder_test.$(OBJEXT) string_reader.$(OBJEXT) \
+ gtest-all.$(OBJEXT)
+utf8_transcoder_test_OBJECTS = $(am_utf8_transcoder_test_OBJECTS)
+utf8_transcoder_test_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
CXXLD = $(CXX)
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
-o $@
-SOURCES = $(file_reader_test_SOURCES) $(string_reader_test_SOURCES)
+SOURCES = $(file_reader_test_SOURCES) $(string_reader_test_SOURCES) \
+ $(utf8_transcoder_test_SOURCES)
DIST_SOURCES = $(file_reader_test_SOURCES) \
- $(string_reader_test_SOURCES)
+ $(string_reader_test_SOURCES) $(utf8_transcoder_test_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
INCLUDES = -I$(top_srcdir) -Isrc/test/gtest/gtest.h
SRC_DIR = ..
LC_ALL = C
-
-# unicode_test_SOURCES = unicode_test.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp \
-# ${SRC_DIR}/reader.cpp
-# utf8_transcoder_test_SOURCES = utf8_transcoder_test.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/simpletest.cpp \
-# ${SRC_DIR}/reader.cpp
-# textarrayformat_test_SOURCES = textarrayformat_test.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/simpletest.cpp
-# lexer_test_SOURCES = ${SRC_DIR}/lexeme_id.h lexer_test.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/lexeme_impl.cpp \
-# ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/lexer.cpp ${SRC_DIR}/lexeme_data.cpp \
-# ${SRC_DIR}/reader.cpp
-# sublexer_test_SOURCES = sublexer_test.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/unicode.cpp ${SRC_DIR}/utf8_transcoder.cpp \
-# ${SRC_DIR}/lexeme_impl.cpp ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/lexeme_data.cpp
-# parser_test_SOURCES = parser_test.cpp ${SRC_DIR}/sublexer_impl.cpp ${SRC_DIR}/simpletest.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/unicode.cpp \
-# ${SRC_DIR}/lexeme_impl.cpp ${SRC_DIR}/parser.cpp ${SRC_DIR}/delimiter.cpp ${SRC_DIR}/textarrayformat.cpp ${SRC_DIR}/lexer.cpp \
-# ${SRC_DIR}/parser_handler.cpp ${SRC_DIR}/reader.cpp ${SRC_DIR}/object.cpp ${SRC_DIR}/type.cpp ${SRC_DIR}/data_structure.cpp \
-# ${SRC_DIR}/primitive.cpp ${SRC_DIR}/lexeme_data.cpp ${SRC_DIR}/primitive_util.cpp ${SRC_DIR}/gc.cpp
-# environment_test_SOURCES = ${SRC_DIR}/environment.cpp environment_test.cpp ${SRC_DIR}/simpletest.cpp \
-# ${SRC_DIR}/unicode.cpp ${SRC_DIR}/utf8_transcoder.cpp ${SRC_DIR}/object.cpp ${SRC_DIR}/type.cpp ${SRC_DIR}/data_structure.cpp
-# type_test_SOURCES = ${SRC_DIR}/type.cpp type_test.cpp ${SRC_DIR}/simpletest.cpp
-# bignum_test_SOURCES = ${SRC_DIR}/bignum.cpp bignum_test.cpp ${SRC_DIR}/simpletest.cpp
check_PROGRANS = $(bin_PROGRAMS)
TESTS = $(bin_PROGRAMS)
string_reader_test_SOURCES = string_reader_test.cpp ../string_reader.cpp gtest/gtest-all.cc
file_reader_test_SOURCES = file_reader_test.cpp ../file_reader.cpp gtest/gtest-all.cc
+utf8_transcoder_test_SOURCES = ../utf8_transcoder.cpp utf8_transcoder_test.cpp ../string_reader.cpp gtest/gtest-all.cc
all: all-am
.SUFFIXES:
string_reader_test$(EXEEXT): $(string_reader_test_OBJECTS) $(string_reader_test_DEPENDENCIES)
@rm -f string_reader_test$(EXEEXT)
$(CXXLINK) $(string_reader_test_OBJECTS) $(string_reader_test_LDADD) $(LIBS)
+utf8_transcoder_test$(EXEEXT): $(utf8_transcoder_test_OBJECTS) $(utf8_transcoder_test_DEPENDENCIES)
+ @rm -f utf8_transcoder_test$(EXEEXT)
+ $(CXXLINK) $(utf8_transcoder_test_OBJECTS) $(utf8_transcoder_test_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtest-all.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_reader_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8_transcoder.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8_transcoder_test.Po@am__quote@
.cc.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o string_reader.obj `if test -f '../string_reader.cpp'; then $(CYGPATH_W) '../string_reader.cpp'; else $(CYGPATH_W) '$(srcdir)/../string_reader.cpp'; fi`
+utf8_transcoder.o: ../utf8_transcoder.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_transcoder.o -MD -MP -MF $(DEPDIR)/utf8_transcoder.Tpo -c -o utf8_transcoder.o `test -f '../utf8_transcoder.cpp' || echo '$(srcdir)/'`../utf8_transcoder.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/utf8_transcoder.Tpo $(DEPDIR)/utf8_transcoder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../utf8_transcoder.cpp' object='utf8_transcoder.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_transcoder.o `test -f '../utf8_transcoder.cpp' || echo '$(srcdir)/'`../utf8_transcoder.cpp
+
+utf8_transcoder.obj: ../utf8_transcoder.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT utf8_transcoder.obj -MD -MP -MF $(DEPDIR)/utf8_transcoder.Tpo -c -o utf8_transcoder.obj `if test -f '../utf8_transcoder.cpp'; then $(CYGPATH_W) '../utf8_transcoder.cpp'; else $(CYGPATH_W) '$(srcdir)/../utf8_transcoder.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/utf8_transcoder.Tpo $(DEPDIR)/utf8_transcoder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../utf8_transcoder.cpp' object='utf8_transcoder.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o utf8_transcoder.obj `if test -f '../utf8_transcoder.cpp'; then $(CYGPATH_W) '../utf8_transcoder.cpp'; else $(CYGPATH_W) '$(srcdir)/../utf8_transcoder.cpp'; fi`
+
.cpp.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
EXPECT_THROW(reader.Read(), reader::EndOfDeviceException);
}
-int main(int argc, char** argv)
-{
+int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
+
-#include <iostream>
-#include <sstream>
-#include <string>
#include <algorithm>
+#include <gtest/gtest.h>
-#include <functional>
+#include "src/utf8_transcoder.h"
+#include "src/string_reader.h"
-#include "../simpletest.h"
-#include "../utf8_transcoder.h"
-#include "../reader.h"
-#include "../textarrayformat.h"
+namespace reader = utakata::reader;
+namespace transcoder = utakata::transcoder;
-using namespace std;
-using namespace utakata;
+TEST(UTF8TranscoderTest, EncodingTest) {
+ reader::StringReader reader("UTF8");
+ transcoder::UTF8Transcoder trans;
-struct identity_local
-{
- char operator()(int t) {return static_cast<char>(t);}
-};
+ unsigned int checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 'U');
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 'T');
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 'F');
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, '8');
-bool utf8_charcheck_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
-{
- // UTF-8の文字を認識するテスト。
-
- // ソースがすでにUTF8で記述されているので、そのまま簡単にだが
- // テストが行える。
- std::string tmp("UTF8");
- // 1byteの文字のみの場合
- smart_ptr<std::istream> ss(new std::stringstream(tmp));
-
- reader::StreamReader stream(ss,
- smart_ptr<transcoder::ITranscoder>(
- new transcoder::UTF8Transcoder()));
-
- // 単独のreadを試す。
- asserter->check(stream.read(), 'U', "error compare to U!");
- // peekが問題なく働いていることのテスト
- asserter->check(stream.peek(), 'T', "error compare to T and peek");
- asserter->check(stream.read(), 'T', "error compare to T and read");
-
- // ここの時点ではまだeofではない。
- asserter->check(stream.isEOF(), false, "not end of file");
- // 読み込んだ文字数を返すメンバ関数のチェック。
- asserter->check(stream.pos(), 2, "wrong position");
-
- // 複数文字の読み出しのチェック
- std::vector<unsigned long> f = stream.read(2);
- std::string t("", f.size());
-
- std::transform(f.begin(), f.end(), t.begin(),
- identity_local());
-
- asserter->check(t, "F8", "複数文字チェック");
-
- // この時点でeofがtrueとなる
- asserter->check(stream.isEOF(), false, "why not eof?");
-
- return asserter->isOk();
+ EXPECT_NO_THROW(trans.Encode(&reader));
+ EXPECT_TRUE(reader.IsEof());
}
-bool utf8_decode_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
-{
- // Unicodeスカラー値からUTF-8のデータへとデコードする。
-
- // ソースがすでにUTF8で記述されているので、そのまま簡単にだが
- // テストが行える。
- std::string tmp("あいうえお");
- // 1byteの文字のみの場合
- smart_ptr<std::istream> ss(new std::stringstream(tmp));
+TEST(UTF8TranscoderTest, MultiByteTest) {
+ reader::StringReader reader("あいuうえお");
+ // 1byteの文字のみの場合
+ transcoder::UTF8Transcoder trans;
- reader::StreamReader stream(ss,
- smart_ptr<transcoder::ITranscoder>(
- new transcoder::UTF8Transcoder()));
+ unsigned int checker = trans.Encode(&reader);
- // 原則として、一文字ずつ分割できればそれで問題は発生しない。
- transcoder::UTF8Transcoder t;
- unsigned long p = stream.peek();
- unsigned long p2 = stream.peek();
+ EXPECT_EQ(checker, 0x3042);
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 0x3044);
- asserter->check(p, p2, "not equal p and p2");
-
- std::vector<char> d(3, 0);
- ss->get(&d[0], 4);
- std::vector<unsigned char> retval;
- retval.insert(retval.begin(), d.begin(), d.end());
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 'u');
- std::vector<int> dec = t.decode(p);
- asserter->check(dec[0] == retval[0], true, "error compare to U1!");
- asserter->check(dec[1] == retval[1], true, "error compare to U2!");
- asserter->check(dec[2] == retval[2], true, "error compare to U3!");
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 0x3046);
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 0x3048);
+ checker = trans.Encode(&reader);
+ EXPECT_EQ(checker, 0x304A);
- return asserter->isOk();
+ EXPECT_NO_THROW(trans.Encode(&reader));
+ EXPECT_TRUE(reader.IsEof());
}
-int main(int argc, char *argv[])
-{
- simpletest::SimpleTestSuite suite("UTF-8 基本テスト");
- suite.addTester(sfcr::screate(utf8_charcheck_test, suite.getAsserter()));
- suite.addTester(sfcr::screate(utf8_decode_test, suite.getAsserter()));
- suite.run();
- return 0;
-}
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+++ /dev/null
-#ifndef _TRANSCODER_H_
-#define _TRANSCODER_H_
-
-#include <iostream>
-#include <vector>
-
-namespace utakata {
-
- namespace transcoder {
-
- class ITranscoder
- {
- // 入力されたバイト列を、それぞれの判定によってUniCharに
- // 変換する。
- // このインターフェースは入力値を変換するためだけのものであり、
- // schemeのtranscoderとは多少機能が異なる。
- // これはlexerのインターフェースで利用される。
- public:
- ITranscoder() {}
- virtual ~ITranscoder() {}
-
- // 渡されたInputPortから一文字分だけ読み出して、unicode値を返す。
- virtual unsigned long encode(std::istream& bytes) = 0;
- // 渡されたcodeに対応する、自身のエンコードとなるバイト列を返す。
- virtual std::vector<int> decode(unsigned long code) = 0;
- };
- };
-
-};
-
-#endif /* _TRANSCODER_H_ */
#include <algorithm>
-#include <sstream>
-#include <assert.h>
-#include "utf8_transcoder.h"
-#include "smart_ptr.h"
+#include "src/reader_interface.h"
+#include "src/utf8_transcoder.h"
-using namespace std;
-using namespace utakata::transcoder;
-using namespace utakata;
+namespace trans = utakata::transcoder;
+namespace reader = utakata::reader;
-transcoder::UTF8Transcoder::UTF8Transcoder() : utf8_max_bit_pos(21)
-{
-}
-
-unsigned long transcoder::UTF8Transcoder::encode(std::istream& p)
-{
- // 渡されたバイナリポートから、一文字を読みとる。
- // 最初に一文字だけ読みだして、チェックをかける。
+// UTF8として認識するバイト列は、次のような判断を行います。
+// 先頭1文字が、IsUTF8FirstByteからtrueが返された場合、
+// IsUTF8FirstByteから返された、文字のサイズ分だけ読み出します。
+// サイズ分の読み出しが行えなかった場合、例外が発生します。
+// 生成などは、Generateメソッドをチェックする必要があります。
+unsigned int trans::UTF8Transcoder::Encode(reader::IReader* reader) {
+ if (!reader->IsEof()) {
+ unsigned int first_byte = reader->Peek();
+ int utf8_size = 0;
- // まずは読み取りをおこなう。
- int c = 0;
- c = p.peek();
+ if (IsUTF8FirstByte(first_byte, &utf8_size)) {
+ std::vector<unsigned int> utf8_bytes;
+ for (int i = 0; i < utf8_size; ++i) {
+ utf8_bytes.push_back(reader->Read());
+ }
- std::vector<int> bytes;
- if (c != std::istream::traits_type::eof())
- {
- // 末尾でない場合のみ、以降のチェックに入る。
- size_t size = 0;
- // 先頭1バイトが正常でなかった場合はそのまま抜ける
- if (utf8::is_utf8_first_byte(c, size))
- {
- bytes.push_back(p.get());
- if ((size - 1) > 0)
- {
- // sizeが0より大きい場合には、この時複数バイトで文字が構成
- // されていると考えられるため、明示的に複数文字を取得する。
- // peekされているので、読み取り位置は変化しない。
- for (size_t i = 0; i < size - 1; ++i)
- {
- bytes.push_back(p.get());
- }
- }
- }
+ return GenerateUnicode(utf8_bytes);
}
+ }
- return generate(bytes);
+ return 0;
}
-unsigned long transcoder::UTF8Transcoder::generate(const std::vector<int>& bytes)
-{
- // 1文字分のUTF8のバイト列を受け取って、コードに変換して返す。
- // 先頭の値によって、次のように値を決定することができる。
- // x = utf8の先頭バイト
- // y1〜yN = utf8の先頭バイト以降のバイト
- // N = utf8の先頭バイトを含むバイト数
- // code = (y1 & ((1 << 7) - 1)) << (6 * n-1) + (y2 & ((1 << 7) -1)) << (6 * (n - 1))...+ x & ((1 << N) -1) << (6 * N-1)
- // 先頭バイト以外は、全て先頭に10とうビットが設定されている。このビットを除いた6ビットをする。
- // つまり、末尾のバイトから順次やっていけばよい。
-
- const unsigned char max_c = (1 << (sizeof(unsigned char) * 8 - 1)) - 1;
- // 固定の範囲外である値を設定しておく。
- unsigned long code = 0x110000;
-
- // 一文字も読みだせていないなら0を返す。
- if (!bytes.empty())
- {
- code = 0;
- if (bytes.size() == 1)
- {
- // asciiコードは7bitなのでそこだけ切り取って返す。
- code = bytes[0] & max_c;
- }
- else
- {
- // 一時的に利用されるクラス。
- struct Lambda
- {
- unsigned long operator()(unsigned char c, int s) {
- return c << (6 * s);
- }
- };
-
- std::vector<int> cl = bytes;
- int first = cl[0];
- cl.erase(cl.begin());
- // サイズが1以外の場合、ここからがちと違う。
- std::vector<int>::const_reverse_iterator beg = cl.rbegin(),
- end = cl.rend();
- const unsigned char char_bit = (1 << 6) - 1;
- for (int i = 0; beg != end; ++i,++beg)
- {
- code += Lambda()((*beg & char_bit), i);
- }
-
- // 最後だけ、別の計算が必要になる。
- const unsigned char byte_size = sizeof(unsigned char) * 8;
- const unsigned char first_byte = (1 << (byte_size - bytes.size() - 1)) - 1;
- code += Lambda()(first & first_byte, bytes.size() - 1);
- }
- }
-
- return code;
-}
-
-std::vector<int> utakata::transcoder::UTF8Transcoder::decode(unsigned long ch)
-{
- // encodeされたunicode文字列を、UTF8に変更する。
- // 基本的には単純な逆変換のようなものになるため、それほど難しくは無いと
- // 思いたい。
-
- // まずは抽出したデータの最上位bitを抽出する。
- // utf-8のため、最大21bitなので、20bitシフトした時点から始める。
-
- unsigned long max_bit = 1 << (utf8_max_bit_pos - 1);
- int pos = utf8_max_bit_pos;
- while (max_bit > 0 && !(ch & max_bit))
- {
- // 先頭bitが1ではない場合には、1bit右へシフトする。
- max_bit >>= 1;
- --pos;
- }
-
- if (max_bit == 0)
- {
- // この場合、null文字であるはずなのでこれを出力する。
- return std::vector<int>(1, 0x0);
- }
-
- // 先頭bitが無事発見できた場合には、bit位置と現在位置の兼ね合いから、
- // それぞれbitを設定していく。
- std::vector<int> ret;
+// UnicodeをUTF8へと変換する場合、先頭から一番最初に1が立っているbit
+// を検索し、1が立っている位置を元として、下位6bitずつ抽出していきます。
+// 最終的に、殘ったbit列に、byte数だけ1を先頭から付与し、これらを
+// 反転させることで、逆変換を行います。
+std::vector<unsigned int> trans::UTF8Transcoder::Decode(unsigned int unicode) {
+ unsigned int max_bit = 1 << (kUTF8MaxBitPos - 1);
+ int bit_pos = kUTF8MaxBitPos;
+ while (max_bit > 0 && !(unicode & max_bit)) {
+ max_bit >>= 1;
+ --bit_pos;
+ }
+
+ // この場合、結果としてNULL文字と判断されます。
+ if (max_bit == 0) {
+ return std::vector<unsigned int>(1, 0x0);
+
+ } else {
+ std::vector<unsigned int> ret;
const int utf8_byte_base = 0x80;
- const int byte_base_bit_size = 6;
- const int utf8_byte_mask = (1 << byte_base_bit_size) - 1;
- unsigned long target = ch;
- for (int i = pos; i > byte_base_bit_size; i -= byte_base_bit_size)
- {
- // それぞれ算出していく。
- ret.push_back(utf8_byte_base | (target & utf8_byte_mask));
- target >>= byte_base_bit_size;
- }
+ const int byte_base_size = 6;
+ unsigned int work_unicode = unicode;
- // 残ったbit分を、それまでに算出した文字の分+1だけ1を先頭に付けてやる。
- {
- const int bit_first_head = ((1 << (ret.size() + 2)) - 1) - 1;
- const int byte_size = sizeof(unsigned char) * 8;
- // 上の例は,1 << 3 = 1000 - 1 = 0111 - = 0110 みたいな感じ。
+ // 6bit分ずつ抽出しています。work_unicodeはその後6bitだけ右シフト
+ // しています。
+ for (int i = bit_pos; i >= byte_base_size; i -= byte_base_size) {
+ ret.push_back(utf8_byte_base | (work_unicode & kSamplingUTF8Bits));
+ work_unicode >>= byte_base_size;
+ }
- // 先頭のbitを、retのサイズ + 2したのをbyte_sizeから引いて、
- // その値だけfirst_headをシフトさせて、それに残っている
- // targetを or する。
- // 110 << ( 8 - 1 - 2 ) = 11000000 | 11100 = 11011100
- ret.push_back((bit_first_head << (byte_size - ret.size() - 2)) |
- target);
- }
+ // 最後の1バイトを構築しています。ret.size() + 1で、全体のサイズ
+ // となります。
+ const int bit_first_head = ((1 << (ret.size() + 1)) - 1);
+ ret.push_back((bit_first_head << bit_pos) | work_unicode);
- // 結果はそのまま反転させることで、正しい形となる。
std::reverse(ret.begin(), ret.end());
return ret;
+ }
}
-// utf8関連の便利関数
-
-bool utakata::transcoder::utf8::is_utf8_one(const std::vector<int>& bytes, size_t& size)
-{
- //渡したバイト列がUTF8の一文字に該当するかどうかを返す。
- size_t back = size;
-
- if (bytes.size() == 0)
- {
- size = back;
- return false;
- }
-
- size_t num = 0;
-
- if (!is_utf8_first_byte(bytes[0], num))
- {
- size = back;
- return false;
- }
-
- // そもそもbytesのサイズが足りない場合にも失敗とする。
- if (num > bytes.size())
- {
- size = back;
- return false;
- }
-
- // 先頭要素以外が正しければそれで問題ないとする。
- if (num > 1)
- {
-
- const CheckUTF8Byte& checker = for_each(bytes.begin() + 1, bytes.begin() + num,
- CheckUTF8Byte());
-
- if (checker.good)
- {
- size = num;
- } else {
- size = back;
- return false;
- }
- } else {
- // sizeが0の場合には、この時点で1を設定するようにする。
- size = num;
- }
-
- // 最後まで到達した時点で成功とする。
- return true;
-}
-
-bool utakata::transcoder::utf8::is_utf8_all(const std::vector<int>& bytes)
-{
- // 与えられたバイト列全てがUTF-8であるかどうかを返す。
- size_t size = 0;
- std::vector<int>::const_iterator it = bytes.begin();
- while (is_utf8_one(std::vector<int>(it, bytes.end()), size)) {
- it += size;
- size = 0;
- }
-
- if (it == bytes.end()) {
- return true;
- }
-
- return false;
-}
-
-bool utakata::transcoder::utf8::is_utf8_first_byte(int c, size_t& size)
-{
- // UTf-8の先頭バイトであるかどうかを返す。
- // 先頭バイトである場合には、その先頭バイトを含む、一文字のサイズを返す。
- // 先頭バイトではない場合には、
- const unsigned char max_c = 1 << (sizeof(unsigned char) * 8 - 1);
-
- size_t back = size;
-
- // 最上位ビットが0である場合、これはasciiコードを指す。
- if (!(c & max_c))
- {
- size = 1;
- return true;
- }
-
- unsigned char first = c << 1;
- size_t num = 1;
- while (first & max_c) {
- first <<= 1;
- num += 1;
- }
-
- // ここまできたとき、最上位ビットは0であるはず。
- // numが5未満である場合、とりあえず正常としておくこととする。
- const unsigned char max_utf8_sequence = 5;
- if (num < max_utf8_sequence) {
- size = num;
- return true;
- }
- else if (num == 1)
- {
- // numが1の場合、何らかの理由で先頭が欠落したと見られる。
- // この場合、スキップするべきバイト数を返す。
- size = 1;
- return false;
-
- } else {
- size = back;
- return false;
- }
-}
-
-
-bool utakata::transcoder::utf8::is_utf8_ascii(const std::vector<int>& bytes)
-{
- // 一文字かつ、0x00〜0x7fの範囲であるデータであることが条件となる。
- size_t s = 0;
- bool b = is_utf8_one(bytes, s);
-
- if (b && s == 1)
- {
- return true;
- }
- return false;
-}
-
-bool utakata::transcoder::utf8::is_utf8_numeric(const std::vector<int>& bytes)
-{
- // 一文字分だけが渡されていると判断する。
- if (!is_utf8_ascii(bytes))
- {
- return false;
- }
-
- if (bytes[0] >= '0' && bytes[0] <= '9')
- {
- return true;
- }
-
- return false;
+// 1文字分のUTF8のバイト列を受け取って、コードに変換して返します。
+// 与えられたutf8_bytesの先頭バイトから、データの構築が行えます。
+// x = utf8の先頭バイト
+// y1〜yN = utf8の先頭バイト以降のバイトを順番
+// N = utf8の先頭バイトを含むバイト数
+// としたとき、Unicodeの文字とした場合、
+// code = (y1 & ((1 << 7) - 1)) << (6 * n-1) + (y2 & ((1 << 7) -1)) << (6 * (n - 1))...+ x & ((1 << N) -1) << (6 * N-1)
+// という形でUnicodeを生成します。
+unsigned int trans::UTF8Transcoder::GenerateUnicode(
+ const std::vector<unsigned int>& bytes) {
+ if (bytes.size() == 1){
+ return bytes[0] & kByteMaxValue;
+
+ } else {
+ std::vector<unsigned int> expecting_first(bytes.begin() + 1, bytes.end());
+ std::vector<unsigned int>::const_reverse_iterator begin = expecting_first.rbegin(),
+ end = expecting_first.rend();
+
+ unsigned int code = 0;
+ for (int i = 0; begin != end; ++i,++begin) {
+ code += SamplingUTF8Data(*begin, i);
+ }
+
+ // 先頭バイトは、8ビットの先頭から、先頭バイト以外で必要なバイトの個数だけ
+ // 1が連続しており、その1は不要であるため、その部分だけ取り除きます。
+ const unsigned char first_byte = (1 << (8 - bytes.size())) - 1;
+ code += (bytes[0] & first_byte) << (6 * (bytes.size() - 1));
+ return code;
+ }
}
-bool utakata::transcoder::utf8::is_utf8_alpha(const std::vector<int>& bytes)
-{
- // 同じく一文字であると判別する。
- // asciiのサブセットなので、先にasciiであると判別しておく。
- if (!is_utf8_ascii(bytes))
- {
- return false;
- }
+// 先頭バイトであるかどうかの判断は、次の基準で判断されます。
+// - 先頭が0 :asciiコード部として認識します。
+// - 先頭が1 :2バイト以上を使用するUTF8と判断します。
+// この場合には、先頭から1がバイト数と同じ数だけ
+// 続いていない場合に、falseとします。
+bool trans::UTF8Transcoder::IsUTF8FirstByte(int check_byte, int* utf8_size) {
+ const unsigned int max_char_bit = 1 << 7;
+ if (!(check_byte & max_char_bit)) {
+ *utf8_size = 1;
+ return true;
+ }
- if ((bytes[0] >= 'a' && bytes[0] <= 'z') ||
- (bytes[0] >= 'A' && bytes[0] <= 'Z'))
-
- {
- return true;
- }
+ unsigned int bit_checker = max_char_bit;
+ int bit_num = 0;
+ for (; check_byte & bit_checker; ++bit_num, bit_checker >>= 1) {}
+ if (bit_num < static_cast<int>(kMaxUTF8MultiByteSize)) {
+ *utf8_size = bit_num;
+ return true;
+ } else {
return false;
+ }
}
-#ifndef _UTF8_TRANSCODER_H_
-#define _UTF8_TRANSCODER_H_
+// バイナリデータをutf-8のデータとして解釈するTranscoderです。
+#ifndef _UTAKATA_SRC_UTF8_TRANSCODER_H_
+#define _UTAKATA_SRC_UTF8_TRANSCODER_H_
-#include <iostream>
-#include <string>
#include <vector>
-
-#include "smart_ptr.h"
-#include "transcoder.h"
+#include "src/transcoder_interface.h"
namespace utakata {
- namespace transcoder {
-
- class UTF8Transcoder : public ITranscoder
- {
- // UTF-8のバイト列が与えられた場合に利用されるTranscoder
-
- unsigned long utf8_max_bit_pos;
-
- public:
- UTF8Transcoder();
- virtual ~UTF8Transcoder() {}
-
- virtual unsigned long encode(std::istream& p);
- virtual std::vector<int> decode(unsigned long code);
-
- private:
-
- unsigned long generate(const std::vector<int>& bytes);
-
- };
-
- namespace utf8 {
-
- // これらの便利関数は、とりあえずこの中に定義しておく。
-
- struct CheckUTF8Byte
- {
- // UTF8の先頭バイト以外であるかどうかをチェックする。
- const int checker;
- bool good;
- CheckUTF8Byte() : checker(0x2), good(true) {}
-
- template<class T>
- void operator()(const T& t) {
- // 先頭ビットが10ではない場合、チェックに失敗する。
- T tmp = t >> 6;
- if ( ((tmp & 0x3)) != checker) {
- good = false;
- }
- }
- };
-
- struct PutBack
- {
- // 渡されたデータをistreamにputbackする。
- std::istream& strm_;
- PutBack(std::istream& strm) : strm_(strm) {}
-
- template<class T>
- void operator()(T t)
- {
- strm_.unget(t);
- }
- };
-
- // 与えられたバイト列の先頭から、UTF8一文字に該当しているかどうかを返す。
- // バイト列がUTF8に該当する場合、そのバイト列のサイズを返す。
- bool is_utf8_one(const std::vector<int>& bytes, size_t& size);
-
- // 与えられたバイト列全てが、UTF8に該当しているかどうかを返す。
- bool is_utf8_all(const std::vector<int>& bytes);
-
- // UTF-8の先頭バイトとして正しいフォーマットであるかどうか。
- // 正しいフォーマットである場合、渡したバイトを含めた、一文字である
- // バイト数を返す。
- bool is_utf8_first_byte(int c, size_t& size);
-
- // 渡したバイト列が、0-9で判別される数値文字と一致するかどうかを返す。
- // is_asciiのサブセットを判別するものである。
- bool is_utf8_numeric(const std::vector<int>& bytes);
-
- // 渡したバイト列が、a-zA-Zの領域であるかどうかを調べる。
- // is_asciiのサブセットを判別するものである。
- bool is_utf8_alpha(const std::vector<int>& bytes);
-
- // 渡したバイト列が、0x00〜0x7fの領域であるかどうかを返す。
- // is_utf8_alpha, is_utf8_numericのスーパーセットとなる。
- bool is_utf8_ascii(const std::vector<int>& bytes);
- };
- };
+namespace reader {
+class IReader;
}
-#endif /* _UTF8_TRANSCODER_H_ */
+namespace transcoder {
+
+class UTF8Transcoder : public ITranscoder {
+ // バイト列をUTF8と解釈して読出すためのTranscoderです。
+ // UTF8Transcoder::Encode/Decodeで、変換不可能であるバイナリデータ
+ // があった場合、それぞれEncodeException、DecodeExceptionが送出されます。
+ public:
+ UTF8Transcoder() : kUTF8MaxBitPos(21),
+ kByteMaxValue((1 << 7) - 1),
+ kExternalCodeLimit(0x110000),
+ kSamplingUTF8Bits((1 << 6) - 1),
+ kMaxUTF8MultiByteSize(5) {}
+ virtual ~UTF8Transcoder() {}
+
+ // 渡されたreaderから、一文字分のデータを読出し、結果をunicodeとして
+ // 返します。
+ // 完全なUTF8のバイト列として解釈できない場合、例外を送出します。
+ virtual unsigned int Encode(reader::IReader* reader);
+
+ // 渡されたunicodeから、UTF-8へと解釈して、バイト列として返します。
+ // 不正なunicodeか、UTF-8へと変換できないunicodeである場合、DecodeException
+ // が送出されます。
+ virtual std::vector<unsigned int> Decode(unsigned int unicode);
+
+ private:
+
+ // UTF8として認識できる最大のbitサイズです。これは完全な固定値であるため、
+ // 変更は不可能です。
+ const unsigned int kUTF8MaxBitPos;
+
+ // 1バイトの最大値を表します。16進数で表わした場合、0x7Fとなります。
+ const unsigned int kByteMaxValue;
+
+ // Unicodeとして認識可能な最大値を表します。16進数での表現は、0x110000となります。
+ const unsigned int kExternalCodeLimit;
+
+ // 先頭バイト以外のUTF8のバイト列からデータを抽出する際のサンプリングを
+ // 行うバイト列です。16進数では0x3Fとなります。
+ const unsigned int kSamplingUTF8Bits;
+
+ // UTF8として認識可能な最大のマルチバイト数です。この値以上
+ // はUTF8として認識することができません。
+ const unsigned int kMaxUTF8MultiByteSize;
+
+ // 渡されたバイト列から、一文字分のunicodeを生成します。
+ // 内部でのみ利用されます。
+ unsigned int GenerateUnicode(const std::vector<unsigned int>& bytes);
+
+ // UTF8の先頭バイト以外のデータ列から、実際に利用するビットのみを
+ // 抽出し、先頭バイトからの個数分だけシフトします。
+ unsigned int SamplingUTF8Data(unsigned int data, int byte_number) {
+ return (data & kSamplingUTF8Bits) << (6 * byte_number);
+ }
+
+ // UTF-8の先頭バイトとして正しいフォーマットであるかをチェックします。
+ // 正しいフォーマットである場合、trueを返します。
+ // utf8_sizeには、先頭バイトも含めたUTF8一文字のサイズが返されます。
+ // 正しいフォーマットでは無い場合、utf8_sizeは編集されません。
+ // utf8_sizeには有効なポインタを渡さなければなりません。
+ bool IsUTF8FirstByte(int check_byte, int* utf8_size);
+
+};
+};
+};
+
+#endif /* _UTAKATA_SRC_UTF8_TRANSCODER_H_ */