4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Zephir、PHP-CPP で UTF-8 対応の文字列関数を開発する

Last updated at Posted at 2015-10-22

Zephir と PHP-CPP の学習および比較のために、UTF-8 の文字列関数の開発に取り組みました。今後、複数の関数や C 言語の例を追加してゆく予定です。

インストール

Zephir

ビルドツールをインストールした上で、git のリポジトリからビルドします。

git clone https://github.com/phalcon/zephir
cd zephir
./install -c

PHP-CPP

git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP.git
cd PHP-CPP
sudo make install

Mac OS X の場合、Makefile を次のように修正しました。

INSTALL_PREFIX                  =       /usr/local

LINKER_FLAGS                    =       -shared -undefined dynamic_lookup


${PHP_SHARED_LIBRARY}: ...
...     ${LINKER} ${PHP_LINKER_FLAGS} -Wl -o libphpcpp.so.$(SONAME)

プロジェクトのセットアップとビルド

Zephir

zephir init myproject

ビルドには zephir compile を実行します。zephir build はインストールも実行されます。

PHP-CPP

Your first extension のチュートリアルページから EmptyExtension.zip および EmptyExtension.tar.gz をダウンロードします。ビルドとインストールのために make および make install を実行します。

Mac OS X の場合、Makefile を次のように修正しました。

INI_DIR                         =       /usr/local/etc/php/5.6/conf.d

COMPILER_FLAGS          =       -I /usr/local/include/ -I /usr/local/include/phpcpp -Wall -c -O2 -std=c++11 -fpic -o
LINKER_FLAGS            =       -shared -L /usr/local/lib 
LINKER_DEPENDENCIES     =       -lphpcpp

C 言語

プロジェクトのセットアップには ext_skel コマンドを使います。

cd /path/to/ext
./ext_skel --extname=helloworld

config.m4 の次の3行のコメントを解除します。

PHP_ARG_WITH(helloworld, for helloworld support,
Make sure that the comment is aligned:
[  --with-helloworld             Include helloworld support])

Makefile の生成には phpize を実行します。make および make install でビルドおよびインストールを実行します。

phpize
./configure
make
make install

PHP 7.0 対応

zend_string API と smart_string が導入されました Upgrading PHP extensions from PHP5 to NG。また引数の解析のパフォーマンス改善のために Fast Parameter Parsing API が導入されました。

UTF-8 の仕様

Unicode 8.0 の3章 で定義されています (Table 3-7. Well-Formed UTF-8 Byte Sequences)。

      コードポイント  1番目のバイト 2番目のバイト 3番目のバイト 4番目のバイト
  U+0000 -   U+007F   00 - 7F
  U+0080 -   U+07FF   C2 - DF    80 - BF
  U+0800 -   U+0FFF   E0         A0 - BF     80 - BF
  U+1000 -   U+CFFF   E1 - EC    80 - BF     80 - BF
  U+D000 -   U+D7FF   ED         80 - 9F     80 - BF
  U+E000 -   U+FFFF   EE - EF    80 - BF     80 - BF
 U+10000 -  U+3FFFF   F0         90 - BF     80 - BF    80 - BF
 U+40000 -  U+FFFFF   F1 - F3    80 - BF     80 - BF    80 - BF
U+100000 - U+10FFFF   F4         80 - 8F     80 - BF    80 - BF

拡張書記素クラスターの境界の仕様

旧字体や色違いの絵文字、梵字など、1つの文字が基底文字と結合記号の組み合わせで表現されることがあります。このような複数のコードポイントで構成される基本単位を拡張書記素クラスターと呼びます。拡張書記素クラスターの境界は UNICODE TEXT SEGMENTATION の仕様の Grapheme Cluster Boundary Rules で定義されます。

PCRE は拡張書記素クラスターをあらわすメタ文字の \X を定義しており、(?>\PM\pM*) と同等とのことです。

C 言語で書記素を1つずつ取り出して表示するコードの例は gist で公開しています。

文字とコードポイントの相互変換

C 言語

コードの例はこちらの記事をご参照ください。

文字数を求める

記事の公開時点では不正なバイト列は考慮しない状態です。

Zephir

namespace StrUtils;

function length(string str)
{
    int bytesize;
    int len, current, size;
    uchar lead;

    let bytesize = str->length();
    let len = 0;
    let current = 0;
    let size = 0;

    while bytesize > current {
        let lead = str[current];

        if lead < 0x80 {
            let size = 1;
        } elseif lead < 0xE0 {
            let size = 2;
        } elseif lead < 0xF0 {
            let size = 3;
        } elseif lead < 0xF5 {
            let size = 4;
        } else {
            let size = 1;
        }

        let current += size;
        let len++;
    }

    return len;
}

PHP-CPP

# include <phpcpp.h>
# include <string>

Php::Value length(Php::Parameters &amp;params)
{
    std::string str = params[0];

    int pos;
    unsigned char lead;
    int size;

    Php::Value len = 0;

    for (pos = 0; pos < str.size(); pos += size) {

        lead = str.at(pos);

        if (lead < 0x80) {
            size = 1;
        } else if (lead < 0xE0) {
            size = 2;
        } else if (lead < 0xF0) {
            size = 3;
        } else {
            size = 4;
        }

        len += 1;
    }

    return len;
}


extern "C" {
    
    PHPCPP_EXPORT void *get_module() 
    {
        static Php::Extension extension("strutils", "1.0");

        extension.add("StrUtils\\length", length);

        return extension;
    }

}

C 言語

standard/html.c で定義される php_next_utf8_char を使うことができます。この関数は htmlspecialchars の実装に使われています。コードの例はこちらの記事をご参照ください。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?