pax_global_header 0000666 0000000 0000000 00000000064 14142237372 0014517 g ustar 00root root 0000000 0000000 52 comment=b09d3de5e8e866b99139eaeac9322ff9a477bf40 tbox-1.6.7/ 0000775 0000000 0000000 00000000000 14142237372 0012506 5 ustar 00root root 0000000 0000000 tbox-1.6.7/.github/ 0000775 0000000 0000000 00000000000 14142237372 0014046 5 ustar 00root root 0000000 0000000 tbox-1.6.7/.github/workflows/ 0000775 0000000 0000000 00000000000 14142237372 0016103 5 ustar 00root root 0000000 0000000 tbox-1.6.7/.github/workflows/android.yml 0000664 0000000 0000000 00000001117 14142237372 0020246 0 ustar 00root root 0000000 0000000 name: Android on: pull_request: push: jobs: build: strategy: matrix: os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Prepare run: | wget -q https://dl.google.com/android/repository/android-ndk-r21-linux-x86_64.zip unzip -q -o ./android-ndk-r21-linux-x86_64.zip - name: Tests run: | xmake f -p android --ndk=`pwd`/android-ndk-r21 xmake tbox-1.6.7/.github/workflows/cross_musl.yml 0000664 0000000 0000000 00000001304 14142237372 0021015 0 ustar 00root root 0000000 0000000 name: Cross (Musl) on: pull_request: push: jobs: build: strategy: matrix: os: [ubuntu-latest] cross: [arm-linux-musleabi, aarch64-linux-musl] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Installation run: | wget https://github.com/xmake-mirror/musl.cc/releases/download/20210202/${{ matrix.cross }}-cross.linux.tgz tar -xvf ${{ matrix.cross }}-cross.linux.tgz - name: Tests run: | xmake f -p cross --toolchain=muslcc --sdk=`pwd`/${{ matrix.cross }}-cross xmake tbox-1.6.7/.github/workflows/fedora.yml 0000664 0000000 0000000 00000001555 14142237372 0020074 0 ustar 00root root 0000000 0000000 name: Fedora on: pull_request: push: release: types: [published] jobs: build: container: fedora:latest runs-on: ubuntu-latest steps: - name: Prepare build tools run: | uname -a dnf -y install @development-tools @rpm-development-tools dnf -y install copr-cli make gcc-c++ dnf -y install perl dnf -y upgrade git - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Tests env: XMAKE_ROOT: y run: | xmake xmake run demo xmake f -m debug xmake -r xmake run demo xmake f --micro=y xmake -r xmake run demo xmake f --small=y -m debug xmake -r xmake run demo tbox-1.6.7/.github/workflows/iphoneos.yml 0000664 0000000 0000000 00000000570 14142237372 0020454 0 ustar 00root root 0000000 0000000 name: iPhoneOS on: pull_request: push: jobs: build: strategy: matrix: os: [macOS-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Tests run: | xmake f -p iphoneos xmake tbox-1.6.7/.github/workflows/linux.yml 0000664 0000000 0000000 00000001121 14142237372 0017760 0 ustar 00root root 0000000 0000000 name: Linux on: pull_request: push: jobs: build: strategy: matrix: os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Tests run: | xmake xmake run demo xmake f -m debug xmake -r xmake run demo xmake f --micro=y xmake -r xmake run demo xmake f --small=y -m debug xmake -r xmake run demo tbox-1.6.7/.github/workflows/macos.yml 0000664 0000000 0000000 00000001120 14142237372 0017722 0 ustar 00root root 0000000 0000000 name: macOS on: pull_request: push: jobs: build: strategy: matrix: os: [macOS-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Tests run: | xmake xmake run demo xmake f -m debug xmake -r xmake run demo xmake f --micro=y xmake -r xmake run demo xmake f --small=y -m debug xmake -r xmake run demo tbox-1.6.7/.github/workflows/mingw_macos.yml 0000664 0000000 0000000 00000000702 14142237372 0021130 0 ustar 00root root 0000000 0000000 name: MingW (MacOS) on: pull_request: push: jobs: build: strategy: matrix: os: [macOS-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Prepare run: | brew install mingw-w64 - name: Tests run: | xmake f -p mingw xmake tbox-1.6.7/.github/workflows/mingw_msys2.yml 0000664 0000000 0000000 00000002140 14142237372 0021101 0 ustar 00root root 0000000 0000000 name: MingW (Msys2) on: push: pull_request: jobs: build: runs-on: windows-latest strategy: fail-fast: false matrix: include: [ { msystem: MINGW64, arch: x86_64, prefix: /mingw64 }, { msystem: MINGW32, arch: i686, prefix: /mingw32 } ] steps: - uses: actions/checkout@v1 - uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} install: git base-devel unzip mingw-w64-${{ matrix.arch }}-toolchain update: true - name: Prepare shell: msys2 {0} run: | git clone https://github.com/xmake-io/xmake.git --recurse-submodules -b dev cd xmake make build make install PREFIX=${{ matrix.prefix }} xmake --version cd .. git reset --hard HEAD git clean -fdx - name: Tests shell: msys2 {0} run: | if [ "${{ matrix.arch }}" == "x86_64" ]; then xmake f -p mingw -a x86_64 else xmake f -p mingw -a i386 fi xmake tbox-1.6.7/.github/workflows/windows.yml 0000664 0000000 0000000 00000001307 14142237372 0020321 0 ustar 00root root 0000000 0000000 name: Windows on: pull_request: push: jobs: build: strategy: matrix: os: [windows-latest] arch: [x64, x86] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: branch@dev - name: Tests run: | xmake f -a ${{ matrix.arch }} xmake run demo xmake f -m debug -a ${{ matrix.arch }} xmake -r xmake run demo xmake f --micro=y -a ${{ matrix.arch }} xmake -r xmake run demo xmake f --small=y -m debug -a ${{ matrix.arch }} xmake -r xmake run demo tbox-1.6.7/.gitignore 0000775 0000000 0000000 00000000371 14142237372 0014502 0 ustar 00root root 0000000 0000000 *.a *.b *.o *.exe *.obj *.dll *.lib *.out *.suo *~ *.swp *.swo *.bak *.orig *.pdb *.idb *.ilk *.gcov *.gcda *.gcno *.gch *.gch.d *.stackdump *.manifest .ccache .xmake build .svn .DS_Store cscope.* gmon.out tags Doxyfile .vscode .idea CMakeLists.txt tbox-1.6.7/CHANGELOG.md 0000664 0000000 0000000 00000035436 14142237372 0014332 0 ustar 00root root 0000000 0000000 # Changelog ([中文](#中文)) ## master (unreleased) ## v1.6.7 ### Changes * Support coroutine for mingw * Improve process poller to support to wait more processes on windows ### Bugs Fixed * [#175](https://github.com/tboox/tbox/issues/175): Fix coroutine crash on windows * Fix some compilation errors ## v1.6.6 ### New features * Support *BSD system, e.g. FreeBSD .. ### Changes * Support to change the current directory for process * Support stdin for creating process * Fix some compilation errors for mingw ## v1.6.5 ### New features * [#112](https://github.com/tboox/tbox/issues/112): Support unix socket,thanks [@Codehz](https://github.com/codehz) * Support to wait pipe, socket and process in coroutine and poller at same time ### Changes * improve uuid and improve uuid v4 * support msys/mingw and cygwin/gcc toolchains ## v1.6.4 ### New features * [#70](https://github.com/tboox/tbox/issues/70): Add `tb_stream_init_from_sock_ref()` to open a given socket as stream * Add stdfile api to read/write stdin, stdout and stderr. * [#81](https://github.com/tboox/tbox/issues/81): Add set/get thread/process cpu affinity * Add filelock api * Add anonymous and named pipe ### Changes * Optimize queue_buffer module * Improve stream interfaces * Improve charset encoding and add ANSI support * Improve atomic and add c11-like atomic apis * Improve spinlock * Support to redirect process output to pipe * Uses virtual memory for coroutine stack * Improve openssl/mbedtls for https ## v1.6.3 ### New features * [#24](https://github.com/tboox/tbox/issues/24): Support IOCP for coroutine on windows ### Changes * Move docs directory to tbox-docs repo * Support tinyc compiler * Remove deprecated module (asio), please use coroutine module * Improve memory for container * Help valgrind to understand coroutines ### Bugs fixed * Fix the charset problem of envirnoment variables * Fix process exit bug * Fix setenv empty value crash * Fix coroutine.sleep bug * Fix windows root path bug * Fix thread local memory leak * Fix context bug for coroutine * Fix `tb_vsnprintf` overflow * [#43](https://github.com/tboox/tbox/issues/43): Fix read dns server and stream bug ## v1.6.2 ### New features * Add ping demo for network ### Changes * Modify license to Apache License 2.0 * Rename `--smallest=y|n` option to `--small=y|n` * Support stat64 * Improve copy speed and fix permissions for `tb_file_copy` * Improve path operation for posix platform * Improve socket interfaces and support icmp ### Bugs fixed * Fix create file mode to 0644 * Fix file and directory path bug * Fix remove directory with dead symbol link failed * Fix remove readonly file failed * [#34](https://github.com/tboox/tbox/issues/34): Fix cache time and coroutine sleep bug * [#35](https://github.com/tboox/tbox/issues/35): Fix epoll bug with the edge trigger mode ## v1.6.1 ### New features * Support coroutine context switch for mips * Add `__tb_thread_local__` keyword macro * Add `--micro=y|n` option to compiling micro library (~64K) for the embed system * Add `tb_addrinfo_addr` and `tb_addrinfo_name` interfaces * Add stackless coroutine * Add semaphone and lock for the stackless coroutine ### Changes * Optimize io scheduler for coroutine, cache events for poller * Add c11 `_Static_assert` * Remove some deprecated interfaces for hash and platform ## v1.6.0 ### New features * Support make command and compile directly without xmake * Add switch context interfaces into platform module * Add coroutine module (supports i386, x86_64, arm, arm64, mips ..) * Add simple http server demo using coroutine * Add simple spider using coroutine * Add io poller interfaces(with epoll, poll, kqueue, select) * Support mbedtls ssl library * All io modules(stream, socket, http, ..) support coroutine mode * Provide lock, semaphone and channel for coroutine ### Changes * Optimize and rewrite thread local store module * Modify thread interfaces * Mark the asio module as deprecated * Optimize exception interfaces ### Bugs fixed * Fix some warning and errors for compiler * Fix some thread bugs * Fix parse bplist uid type ## v1.5.3 ### New features * Add wait multi-processes interface * Add uuid generator * Add hash library module * Add `__tb_deprecated__` keyword and option ### Changes * Move some utils interfaces to the hash module * Rewrite random generator ### Bugs fixed * Fix stdout compatibility issue for vs2015 * Fix process arguments length limit ## v1.5.2 ### New features * Add smallest configure option * Add process operation interfaces ### Changes * Improve envirnoment interfaces * Modify xmake.lua for supporting xmake v2.x ### Bugs fixed * Fix ltimer bug * Fix asio memory leaks bug * Fix asio httpd response bug on linux * Fix path bug for windows ## v1.5.1 ### New features * Add automaticlly check libc interfaces * Support custom allocator * Add trace for allocator in the debug mode * Add `static_pool` module * Add stream interfaces for reading all data to string * Add adler32 hash algorithm * Add `tb_memmem` interface * Add regex module with pcre, pcre2 or posix regex ### Changes * Optimize stream and support read/write character device file * Modify `tb_init` api and support allocator arguments * Improve memory manager and use the allocator mode * Redefine `assert` and will abort for debug mode ### Bugs fixed * Fix some bugs for android * Fix seek bug for stream
# 更新日志 ## master (开发中) ## v1.6.7 ### 改进 * 改进协程,增加对 mingw 支持 * 改进 process poller 支持在 windows 上等待更多进程 ### Bugs 修复 * [#175](https://github.com/tboox/tbox/issues/175): 修复协程在 windows 上崩溃 * 修复一些编译问题 ## v1.6.6 ### 新特性 * 支持*BSD系统,例如:FreeBSD ### 改进 * 创建进程支持修改处理当前工作目录 * 创建禁止支持 stdin 重定向输入 * 修复一些 mingw 上的编译错误 ## v1.6.5 ### 新特性 * [#112](https://github.com/tboox/tbox/issues/112): 新增unix socket支持,感谢[@Codehz](https://github.com/codehz)的贡献 * 在协程和poller中支持同时等待和调度socket,pipe io和process ### 改进 * 改进uuid生成,实现uuid v4 * 支持msys/mingw和cygwin/gcc上编译 ## v1.6.4 ### 新特性 * [#70](https://github.com/tboox/tbox/issues/70): 添加`tb_stream_init_from_sock_ref()`接口去直接打开一个socket作为stream去读取数据。 * 添加stdfile接口去读写stdin, stdout和stderr。 * [#81](https://github.com/tboox/tbox/issues/81): 添加对进程和线程的cpu亲缘性设置和获取 * 添加filelock文件锁跨平台api接口 * 添加匿名管道,命名管道支持 ### 改进 * 优化queue_buffer模块 * 改进stream接口实现 * 改进字符集编码转换,以及增加对ANSI编码的支持 * 改进原子操作,并增加c11风格原子接口 * 改进spinlock实现 * 新增进程输出重定向到管道 * 针对协程栈使用虚拟内存 * 改进基于openssl/mbedtls的https访问 ## v1.6.3 ### 新特性 * [#24](https://github.com/tboox/tbox/issues/24): 针对windows平台下的协程处理,增加IOCP支持 ### 改进 * 移除docs目录,放置到独立tbox-docs仓库,减少tbox.zip包大小 * 支持tinyc编译器 * 移除被废弃的模块(asio模块,先用coroutine代替) * 精简优化容器库内存资源使用 * 帮助valgrind更好的理解coroutine ### Bugs修复 * 修复windows环境变量的中文编码问题 * 修复后台进程退出问题 * 修复设置环境变量值为空时的崩溃问题 * 修复协程sleep超时覆写数据的bug * 修复windows根路径问题 * 修复tls线程存储内存泄露问题 * 修复context切换问题 * 修复`tb_vsnprintf`栈溢出问题 * [#43](https://github.com/tboox/tbox/issues/43): 修复读取dns服务器以及stream读取bug ## v1.6.2 ### 新特性 * 增加ping测试程序 ### 改进 * 修改license,使用更加宽松的Apache License 2.0 * 重命名`--smallest=y|n`选项到`--small=y|n` * 使用`stat64`支持大文件信息获取 * 改进`tb_file_copy`,更加快速的文件copy,并且修复copy后文件权限丢失问题 * 改进posix平台下的路径操作 * 改进socket初始化接口,支持icmp协议 ### Bugs修复 * 修复创建文件权限不对问题 * 修复文件和目录路径问题 * 修复无法移除带有无效软链的目录问题 * 修复无法移除只读文件问题 * [#34](https://github.com/tboox/tbox/issues/34): 修复缓存时间和协程sleep不准问题 * [#35](https://github.com/tboox/tbox/issues/35): 修复epoll边缘触发模式下,centos上检测连接关闭失效问题 ## v1.6.1 ### 新特性 * 针对协程上下文切换,支持mips架构 * 添加`__tb_thread_local__`关键字宏 * 添加 `--micro=y|n` 选项,实现极小编译,针对嵌入式平台,编译tbox微内核(~64K) * 添加 `tb_addrinfo_addr` and `tb_addrinfo_name` 接口 * 添加stackless协程,更加轻量的协程支持,每个协程只占用几十个bytes,同时支持io调度 * 针对stackless协程,增加lock和semaphone支持 ### 改进 * 为协程优化io调度器,缓存poller轮询等待,减少频繁重复调用epoll_ctl, kevent等系统接口 * 添加对c11关键字`_Static_assert`的支持 * 针对hash和platform模块,移除一些废弃的接口 ## v1.6.0 ### 新特性 * 支持make进行直接编译(会去自动下载xmake进行构建) * 在平台库中,添加切换context上下文接口(参考boost.context实现原理进行重写,并对部分架构进行优化) * 新增跨平台协程模块(支持i386, x86_64, arm, arm64, mips),提供更加易用的高性能并发编程模式 * 新增基于协程的各种服务器开发实例(包括:简单轻量的http服务器,爬虫。。) * 新增poller轮询器接口,实现对epoll, poll, kqueue, select的封装,逐步取代老的aiop接口 * 新增mbedtls ssl库接口支持,目前已支持:openssl, polarssl, mbedtls * tbox所有stream, socket, http, dns, ssl 等io相关操作,原生支持协程模式,并且可以在线程和协程间随意切换 * 为协程提供lock, semaphone, channel模块 ### 改进 * 优化和重构线程局部存储TLS模块 * 修改部分线程接口 * asio模块被标记为废弃接口,下个版本将会被移除,逐步使用协程模式来实现异步io开发 * 优化异常捕获接口 ### Bugs修复 * 修复一些编译警告和错误 * 修复一些线相关bug * 修复bplist中解析uid类型失败问题 ## v1.5.3 ### 新特性 * 增加同时等待多个进程接口 * 增加uuid生成器 * 增加hash库模块 * 添加`__tb_deprecated__`关键字以及配置选项 ### 改进 * 移动部分utils接口到hash模块 * 重写random生成器 ### Bugs修复 * 修复stdout在vs2015以上版本的兼容性问题 * 修复进程参数长度限制 ## v1.5.2 ### 新特性 * 增加smallest参数配置选项,实现一键配置最小化编译,禁用所有扩展模块和依赖库 * 增加进程创建和控制接口 ### 改进 * 增强环境变量设置接口 * 修改xmake.lua支持最新版xmake v2.x, 简化编译配置 ### Bugs修复 * 修复ltimer定时器不准问题 * 修复asio部分内存泄露问题 * 修复asio/httpd在linux下keepalive模式,响应很慢问题 * 修复windows下路径处理的一些bug ## v1.5.1 ### 新特性 * 自动检测所有系统libc接口,优先使用系统版本 * 支持自定义内存分配器,并且能够在debug模式下,获取每次分配的代码位置信息,用于自定义追踪 * 增加轻量级`static_pool`来维护整块buffer的内存分配,适合局部管理部分内存,pool虽然也能维护,但是底层基于`large_pool`,比较重量级,适合全局管理内存 * 增加stream快速读取全部数据到string的接口 * 增加adler32 hash算法 * 增加`tb_memmem`接口 * 采用pcre/pcre2/posix regex实现正则表达式库 ### 改进 * 优化stream,支持对字符设备文件的读写 * 修改`tb_init`接口,增加allocator自定义内存分配器参数,实现用户的侵入式内存管理 * 重构内存管理,完全采用分配器allocator模式,可以灵活切换内存管理,支持原生系统内存、静态buffer内存、内存池等各种分配方式 * 重定义assert,debug模式遇到assert直接abort执行 ### Bugs修复 * 修复android下的一些bug * 修复stream的seek问题 ## v1.5.0 ### 新特性 * 增加跨平台环境变量操作接口 ### 改进 * 重建整个编译架构,采用xmake跨平台自动构建工具进行构建。。 * 优化.pkg的依赖包机制,支持依赖库和接口的自动检测,针对libc、libm优先使用自动检测到的系统库接口实现,如果当前平台没有实现则使用tbox的自己实现版本,使得最大化性能和跨平台性。。 * 完善和优化路径操作,增加相对路径、绝对路径的相互转换 ### Bugs修复 * 修复strlcpy等一些libc接口的实现bug ## v1.4.8 ### 新特性 * 新增路径操作接口,支持相对路径、绝对路径相互转换 ### 改进 * 重建整个makefile架构,采用`*.pkg`依赖包模式模块化对第三方库的依赖,降低耦合 * 默认编译配置可以自动探测当前平台支持的依赖包,注:所有依赖包都是可选的,如果要最小化编译,可以完全禁用 * 编译生成的所有库和头文件,也都安装成独立`*.pkg`格式,方便集成到其他开发平台,也方便copy * 增强object路径解析接口,支持json, xml宏路径解析,并增加实用json解析工具:jcat * 实现通用ipaddr结构,统一接口,全面支持ipv6/ipv4,stream/http的url也完全支持ipv6格式解析 * 重命名hash为`hash_map`,并新增`hash_set`容器 ## v1.4.7 ### 改进 * 增强fixed16定点类型的接口,优化部分接口性能,调试模式下增加更多的溢出检测 * 优化整数平方根的实现,增加对64位整数平方根的快速计算 ### Bugs修复 * 修复string空字符串bug * 修复windows下asio的一些bug * 修复一些编译问题 ## v1.4.7_rc1 ### 新特性 * 增加asio模块,支持各种异步socket/file操作,支持异步dns、ssl(依赖polarssl/openssl)、http * 增加http cookie支持,完善http客户端协议 * 增加sql数据库模块,依赖sqlite3/mysql * 增加object模块 * 新增min/max heap容器,新增`list_entry`、`single_list_entry`等外置轻量链表实现,和`list`、`single_list`不同的是,不需要维护内部内存,而且更加灵活,新增bloom_filter * 新增remove、walk、count、for等常用算法支持 * 新增线程池、定时器、信号量、自旋锁、atomic64等常用系统操作 * 新增http服务器、http爬虫、http下载器等实用性demo ### 改进 * 重构stream模块,并新增`async_stream`、`async_transfer`、`transfer_pool`等新特性。 * 优化和完善libc、libm的接口 * 重构整个内存管理架构,完善内存检测的支持,优化内存使用和效率 ### Bugs修复 * 修复和优化xml解析模块 tbox-1.6.7/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000013457 14142237372 0015317 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [waruqi@gmail.com]. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org # Contributor Covenant行为准则 # 参与者公约 ## 我们的保证 为了促进一个开放透明且友好的环境,我们作为贡献者和维护者保证:无论年龄、种族、民族、性别认同和表达(方式)、体型、身体健全与否、经验水平、国籍、个人表现、宗教或性别取向,参与者在我们项目和社区中都免于骚扰。 ## 我们的标准 有助于创造正面环境的行为包括但不限于: * 使用友好和包容性语言 * 尊重不同的观点和经历 * 耐心地接受建设性批评 * 关注对社区最有利的事情 * 友善对待其他社区成员 身为参与者不能接受的行为包括但不限于: * 使用与性有关的言语或是图像,以及不受欢迎的性骚扰 * 捣乱/煽动/造谣的行为或进行侮辱/贬损的评论,人身攻击及政治攻击 * 公开或私下的骚扰 * 未经许可地发布他人的个人资料,例如住址或是电子地址 * 其他可以被合理地认定为不恰当或者违反职业操守的行为 ## 我们的责任 项目维护者有责任为「可接受的行为」标准做出诠释,以及对已发生的不被接受的行为采取恰当且公平的纠正措施。 项目维护者有权利及责任去删除、编辑、拒绝与本行为标准有所违背的评论 (comments)、提交 (commits)、代码、wiki 编辑、问题 (issues) 和其他贡献,以及项目维护者可暂时或永久性的禁止任何他们认为有不适当、威胁、冒犯、有害行为的贡献者。 ## 使用范围 当一个人代表该项目或是其社区时,本行为标准适用于其项目平台和公共平台。 代表项目或是社区的情况,举例来说包括使用官方项目的电子邮件地址、通过官方的社区媒体账号发布或线上或线下事件中担任指定代表。 该项目的呈现方式可由其项目维护者进行进一步的定义及解释。 ## 强制执行 可以通过[waruqi@gmail.com],来联系项目团队来举报滥用、骚扰或其他不被接受的行为。 任何维护团队认为有必要且适合的所有投诉都将进行审查及调查,并做出相对应的回应。项目小组有对事件回报者有保密的义务。具体执行的方针近一步细节可能会单独公布。 没有切实地遵守或是执行本行为标准的项目维护人员,可能会因项目领导人或是其他成员的决定,暂时或是永久地取消其参与资格。 ## 来源 本行为标准改编自[贡献者公约][主页],版本 1.4 可在此观看https://www.contributor-covenant.org/zh-cn/version/1/4/code-of-conduct.html [主页]: https://www.contributor-covenant.org tbox-1.6.7/CONTRIBUTING.md 0000664 0000000 0000000 00000006444 14142237372 0014747 0 ustar 00root root 0000000 0000000 # Contributing If you discover issues, have ideas for improvements or new features, or want to contribute a new module, please report them to the [issue tracker][1] of the repository or submit a pull request. Please, try to follow these guidelines when you do so. ## Issue reporting * Check that the issue has not already been reported. * Check that the issue has not already been fixed in the latest code (a.k.a. `master`). * Be clear, concise and precise in your description of the problem. * Open an issue with a descriptive title and a summary in grammatically correct, complete sentences. * Include any relevant code to the issue summary. ## Pull requests * Use a topic branch to easily amend a pull request later, if necessary. * Write good commit messages. * Use the same coding conventions as the rest of the project. * Ensure your edited codes with four spaces instead of TAB. * Please commit code to `dev` branch and we will merge into `master` branch in feature * Before adding new features and new modules, please go to issues to submit the relevant feature description first # 贡献代码 如果你发现一些问题,或者想新增或者改进某些新特性,或者想贡献一个新的模块 那么你可以在[issues][1]上提交反馈,或者发起一个提交代码的请求(pull request). ## 问题反馈 * 确认这个问题没有被反馈过 * 确认这个问题最近还没有被修复,请先检查下 `master` 的最新提交 * 请清晰详细地描述你的问题 * 如果发现某些代码存在问题,请在issue上引用相关代码 ## 提交代码 * 请先更新你的本地分支到最新,再进行提交代码请求,确保没有合并冲突 * 编写友好可读的提交信息 * 请使用与工程代码相同的代码规范 * 请提交代码到`dev`分支,如果通过,我们会在特定时间合并到`master`分支上 * 为了规范化提交日志的格式,commit消息,不要用中文,请用英文描述 * 增加新特性和新模块之前,请先到issues提交相关特性说明,经过讨论评估确认后,再进行相应的代码提交,避免做无用工作 ## 编码规范 代码需要符合tbox的编码风格,保证整体风格一致,这样可读性会更好,也更容易维护,下面列举一些风格描述。 * 空格缩进、填充,4字符宽度,不允许出现任意tab字符 * 换行符'\n',不要用'\r\n' * 文件utf8编码,不允许其他编码格式,例如:gbk * 全英文注释,public接口注释采用doxygen风格 * 类unix命名规范:小写 + 下划线,例如:`aaa_bb_cc`,不允许任何大写字符 * 接口名、宏定义等必须带:`tb_`, `TB_`前缀 * 需要使用tbox提供的基础类型,例如:`tb_size_t` * if, while, for等关键字之后,带一个空格,例如:`if ()`, `for (; ;)` * 如果if, for的body只有一行代码,不需要写大括号 * {}块,换行对称 * 局部变量定义不需要遵循c89风格,定义位置尽量靠近实际使用的地方 * 函数取参,返回值处理,需要有assert检测 * 宏定义大写,其他都小写 * 除非必要,尽量使用`tb_size_t`, `tb_long_t`类型,而不是`tb_int_t` * 接口定义、接口实现、宏定义、全局变量、include等布局风格必须一致,风格可参考实际代码 [1]: https://github.com/tboox/tbox/issues tbox-1.6.7/LICENSE.md 0000775 0000000 0000000 00000034230 14142237372 0014117 0 ustar 00root root 0000000 0000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2009-present TBOOX Open Source Group Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ------------------------------------------------------------------------------- ## SUBCOMPONENTS The TBOX project contains subcomponents with separate copyright notices and license terms. Your use of the source code for the these subcomponents is subject to the terms and conditions of the following licenses. #### Boost Software License Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For src/tbox/platform/arch/{arm,arm64,mips,x86,x64}/context.{S,asm}: ``` /* Copyright Oliver Kowalke 2009. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ ``` #### ZLib License Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler For src/tbox/hash/adler32.c: ``` /* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ ``` tbox-1.6.7/NOTICE.md 0000775 0000000 0000000 00000004207 14142237372 0014017 0 ustar 00root root 0000000 0000000 The Treasure Box Library Copyright 2009-present The TBOOX Open Source Group This product includes software developed by The TBOOX Open Source Group (https://tboox.org/). ------------------------------------------------------------------------------- This product contains a modified portion of 'boost.context', a coroutine context implementation for assembler code, which can be obtained at: * LICENSE: * http://www.boost.org/LICENSE_1_0.txt (Boost Software License 1.0) * HOMEPAGE: * http://www.boost.org This product contains a modified portion of 'zlib.adler32', compute the Adler-32 checksum of a data stream, which can be obtained at: * LICENSE: * pkg/zlib.pkg/LICENSE.md (Zlib License) * HOMEPAGE: * http://zlib.net/ This product optionally depends on 'pcre', a library of functions to support regular expressions, which can be obtained at: * LICENSE: * pkg/pcre.pkg/LICENSE.md (BSD License) * HOMEPAGE: * http://www.pcre.org/ This product optionally depends on 'pcre2', a library of functions to support regular expressions, which can be obtained at: * LICENSE: * pkg/pcre2.pkg/LICENSE.md (BSD License) * HOMEPAGE: * http://www.pcre.org/ This product optionally depends on 'mbedtls', an open source, portable, easy to use, readable and flexible SSL library, which can be obtained at: * LICENSE: * pkg/mbedtls.pkg/LICENSE.md (Apache License 2.0) * HOMEPAGE: * https://tls.mbed.org/ This product optionally depends on 'polarssl', an open source, portable, easy to use, readable and flexible SSL library, which can be obtained at: * LICENSE: * pkg/polarssl.pkg/LICENSE.md (GPL 2.0) * HOMEPAGE: * https://tls.mbed.org/ This product optionally depends on 'openssl', a TLS/SSL and crypto library, which can be obtained at: * LICENSE: * pkg/openssl.pkg/LICENSE.md (OpenSSL License and SSLeay license) * HOMEPAGE: * https://www.openssl.org/ This product optionally depends on 'sqlite3', a self-contained, high-reliability, embedded, full-featured, public-domain, SQL database engine, which can be obtained at: * LICENSE: * Public Domain * HOMEPAGE: * http://sqlite.org/ tbox-1.6.7/README.md 0000775 0000000 0000000 00000024223 14142237372 0013773 0 ustar 00root root 0000000 0000000 ## Supporting the project Support this project by becoming a sponsor. Your logo will show up here with a link to your website. 🙏 [[Become a sponsor](https://tboox.io/#/about/sponsor)]
Or you can also consider sponsoring us to get technical support services, [[Become a sponsor](https://tboox.io/#/about/sponsor)]
## Contacts
* Email:[waruqi@gmail.com](mailto:waruqi@gmail.com)
* Homepage:[tboox.org](https://tboox.org)
* Community:[/r/tboox on reddit](https://www.reddit.com/r/tboox/)
* ChatRoom:[Chat on telegram](https://t.me/tbooxorg), [Chat on gitter](https://gitter.im/tboox/tboox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
* QQ Group: 343118190(full), 662147501
* Wechat Public: tboox-os
tbox-1.6.7/README_zh.md 0000775 0000000 0000000 00000032577 14142237372 0014507 0 ustar 00root root 0000000 0000000
## 项目支持
通过成为赞助者来支持该项目。您的logo将显示在此处,并带有指向您网站的链接。🙏 [[成为赞助商](https://tboox.io/#/zh-cn/about/sponsor)]
或者你也可以考虑赞助我们也获取技术支持服务,[[成为赞助商](https://tboox.io/#/zh-cn/about/sponsor)]
## 联系方式
* 邮箱:[waruqi@gmail.com](mailto:waruqi@gmail.com)
* 主页:[TBOOX开源工程](https://tboox.org/cn)
* 社区:[Reddit论坛](https://www.reddit.com/r/tboox/)
* 聊天:[Telegram群组](https://t.me/tbooxorg), [Gitter聊天室](https://gitter.im/tboox/tboox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
* QQ群:343118190(满), 662147501
* 微信公众号:tboox-os
tbox-1.6.7/src/ 0000775 0000000 0000000 00000000000 14142237372 0013275 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/demo/ 0000775 0000000 0000000 00000000000 14142237372 0014221 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/demo/algorithm/ 0000775 0000000 0000000 00000000000 14142237372 0016207 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/demo/algorithm/find.c 0000664 0000000 0000000 00000010721 14142237372 0017274 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_find_int_test()
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = i;
// find
tb_size_t itor = tb_iterator_tail(iterator);
tb_hong_t time = tb_mclock();
for (i = 0; i < n; i++) itor = tb_find_all(iterator, (tb_pointer_t)data[800]);
time = tb_mclock() - time;
// item
tb_long_t item = itor != tb_iterator_tail(iterator)? (tb_long_t)tb_iterator_item(iterator, itor) : 0;
// time
tb_trace_i("tb_find_int_all[%ld ?= %ld]: %lld ms", item, data[800], time);
// free
tb_free(data);
}
static tb_void_t tb_find_int_test_binary()
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = i;
// find
tb_size_t itor = tb_iterator_tail(iterator);
tb_hong_t time = tb_mclock();
for (i = 0; i < n; i++) itor = tb_binary_find_all(iterator, (tb_pointer_t)data[800]);
time = tb_mclock() - time;
// item
tb_long_t item = itor != tb_iterator_tail(iterator)? (tb_long_t)tb_iterator_item(iterator, itor) : 0;
// time
tb_trace_i("tb_binary_find_int_all[%ld ?= %ld]: %lld ms", item, data[800], time);
// free
tb_free(data);
}
static tb_void_t tb_find_str_test()
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%04lu", i);
s[r] = '\0';
data[i] = tb_strdup(s);
}
// find
tb_size_t itor = tb_iterator_tail(iterator);
tb_hong_t time = tb_mclock();
for (i = 0; i < n; i++) itor = tb_find_all(iterator, (tb_pointer_t)data[800]);
time = tb_mclock() - time;
// item
tb_char_t* item = itor != tb_iterator_tail(iterator)? (tb_char_t*)tb_iterator_item(iterator, itor) : 0;
// time
tb_trace_i("tb_find_str_all[%s ?= %s]: %lld ms", item, data[800], time);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
static tb_void_t tb_find_str_test_binary()
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%04lu", i);
s[r] = '\0';
data[i] = tb_strdup(s);
}
// find
tb_size_t itor = tb_iterator_tail(iterator);
tb_hong_t time = tb_mclock();
for (i = 0; i < n; i++) itor = tb_binary_find_all(iterator, (tb_pointer_t)data[800]);
time = tb_mclock() - time;
// item
tb_char_t* item = itor != tb_iterator_tail(iterator)? (tb_char_t*)tb_iterator_item(iterator, itor) : 0;
// time
tb_trace_i("tb_binary_find_str_all[%s ?= %s]: %lld ms", item, data[800], time);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_algorithm_find_main(tb_int_t argc, tb_char_t** argv)
{
// test
tb_find_int_test();
tb_find_int_test_binary();
tb_find_str_test();
tb_find_str_test_binary();
return 0;
}
tbox-1.6.7/src/demo/algorithm/sort.c 0000664 0000000 0000000 00000031052 14142237372 0017343 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_sort_int_test_perf(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
// sort
tb_hong_t time = tb_mclock();
tb_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_sort_int_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(data[i - 1] <= data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_perf_bubble(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
// sort
tb_hong_t time = tb_mclock();
tb_bubble_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_bubble_sort_int_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(data[i - 1] <= data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_func_bubble()
{
// init
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 20;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// trace
tb_trace_i("");
// put
for (i = 0; i < n; i++)
{
data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
tb_trace_i("bubble_put: %ld", data[i]);
}
// sort
tb_heap_sort_all(iterator, tb_null);
// trace
tb_trace_i("");
// pop
for (i = 0; i < n; i++) tb_trace_i("bubble_pop: %ld", data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_perf_insert(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
// sort
tb_hong_t time = tb_mclock();
tb_insert_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_insert_sort_int_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(data[i - 1] <= data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_func_insert()
{
// init
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 20;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// trace
tb_trace_i("");
// put
for (i = 0; i < n; i++)
{
data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
tb_trace_i("insert_put: %ld", data[i]);
}
// sort
tb_heap_sort_all(iterator, tb_null);
// trace
tb_trace_i("");
// pop
for (i = 0; i < n; i++) tb_trace_i("insert_pop: %ld", data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_perf_quick(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
// sort
tb_hong_t time = tb_mclock();
tb_quick_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_quick_sort_int_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(data[i - 1] <= data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_func_quick()
{
// init
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 20;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// trace
tb_trace_i("");
// put
for (i = 0; i < n; i++)
{
data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
tb_trace_i("quick_put: %ld", data[i]);
}
// sort
tb_heap_sort_all(iterator, tb_null);
// trace
tb_trace_i("");
// pop
for (i = 0; i < n; i++) tb_trace_i("quick_pop: %ld", data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_perf_heap(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// make
for (i = 0; i < n; i++) data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
// sort
tb_hong_t time = tb_mclock();
tb_heap_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_heap_sort_int_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(data[i - 1] <= data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_int_test_func_heap()
{
// init
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 20;
// init data
tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n);
// trace
tb_trace_i("");
// put
for (i = 0; i < n; i++)
{
data[i] = tb_random_range(TB_MINS16, TB_MAXS16);
tb_trace_i("heap_put: %ld", data[i]);
}
// sort
tb_heap_sort_all(iterator, tb_null);
// trace
tb_trace_i("");
// pop
for (i = 0; i < n; i++) tb_trace_i("heap_pop: %ld", data[i]);
// free
tb_free(data);
}
static tb_void_t tb_sort_str_test_perf(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%ld", tb_random_value());
s[r] = '\0';
data[i] = tb_strdup(s);
}
// sort
tb_hong_t time = tb_mclock();
tb_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_sort_str_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(tb_strcmp(data[i - 1], data[i]) <= 0);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
static tb_void_t tb_sort_str_test_perf_bubble(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%ld", tb_random_value());
s[r] = '\0';
data[i] = tb_strdup(s);
}
// sort
tb_hong_t time = tb_mclock();
tb_bubble_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_bubble_sort_str_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(tb_strcmp(data[i - 1], data[i]) <= 0);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
static tb_void_t tb_sort_str_test_perf_insert(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%ld", tb_random_value());
s[r] = '\0';
data[i] = tb_strdup(s);
}
// sort
tb_hong_t time = tb_mclock();
tb_insert_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_insert_sort_str_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(tb_strcmp(data[i - 1], data[i]) <= 0);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
static tb_void_t tb_sort_str_test_perf_quick(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%ld", tb_random_value());
s[r] = '\0';
data[i] = tb_strdup(s);
}
// sort
tb_hong_t time = tb_mclock();
tb_quick_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_quick_sort_str_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(tb_strcmp(data[i - 1], data[i]) <= 0);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
static tb_void_t tb_sort_str_test_perf_heap(tb_size_t n)
{
__tb_volatile__ tb_size_t i = 0;
// init data
tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*));
tb_assert_and_check_return(data);
// init iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n);
// make
tb_char_t s[256] = {0};
for (i = 0; i < n; i++)
{
tb_long_t r = tb_snprintf(s, 256, "%ld", tb_random_value());
s[r] = '\0';
data[i] = tb_strdup(s);
}
// sort
tb_hong_t time = tb_mclock();
tb_heap_sort_all(iterator, tb_null);
time = tb_mclock() - time;
// time
tb_trace_i("tb_heap_sort_str_all: %lld ms", time);
// check
for (i = 1; i < n; i++) tb_assert_and_check_break(tb_strcmp(data[i - 1], data[i]) <= 0);
// free data
for (i = 0; i < n; i++) tb_free(data[i]);
tb_free(data);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_algorithm_sort_main(tb_int_t argc, tb_char_t** argv)
{
// func
tb_sort_int_test_func_heap();
tb_sort_int_test_func_quick();
tb_sort_int_test_func_bubble();
tb_sort_int_test_func_insert();
// perf
tb_sort_int_test_perf(1000);
tb_sort_int_test_perf_heap(1000);
tb_sort_int_test_perf_quick(1000);
tb_sort_int_test_perf_bubble(1000);
tb_sort_int_test_perf_insert(1000);
tb_sort_str_test_perf(1000);
tb_sort_str_test_perf_heap(1000);
tb_sort_str_test_perf_quick(1000);
tb_sort_str_test_perf_bubble(1000);
tb_sort_str_test_perf_insert(1000);
return 0;
}
tbox-1.6.7/src/demo/container/ 0000775 0000000 0000000 00000000000 14142237372 0016203 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/demo/container/bloom_filter.c 0000664 0000000 0000000 00000025433 14142237372 0021033 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_size_t g_func_indx = 0;
static tb_element_t g_func_prev;
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_size_t tb_demo_test_hash_func(tb_element_ref_t element, tb_cpointer_t priv, tb_size_t mask, tb_size_t index)
{
return g_func_prev.hash(element, priv, mask, g_func_indx);
}
static tb_void_t tb_demo_test_cstr_h(tb_size_t index)
{
// the count
tb_size_t count = 1000000;
// save element
g_func_indx = index;
g_func_prev = tb_element_str(tb_true);
// the element
tb_element_t element = g_func_prev;
element.hash = tb_demo_test_hash_func;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 1, count, element);
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
tb_char_t s[256] = {0};
tb_hong_t t = tb_mclock();
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random();
// format it
tb_snprintf(s, sizeof(s) - 1, "%ld", value);
// set value to filter
if (!tb_bloom_filter_set(filter, s))
{
// repeat++
r++;
}
}
t = tb_mclock() - t;
// trace
tb_trace_i("cstr: index: %lu, repeat: %lu, time: %lld ms", index, r, t);
// exit filter
tb_bloom_filter_exit(filter);
}
}
static tb_void_t tb_demo_test_cstr_p()
{
// the count
tb_size_t count = 10000000;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_01, 3, count, tb_element_str(tb_true));
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
tb_char_t s[256] = {0};
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random();
// format it
tb_snprintf(s, sizeof(s) - 1, "%ld", value);
// set value to filter
if (!tb_bloom_filter_set(filter, s))
{
// repeat++
r++;
}
}
// trace
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_trace_i("cstr: count: %lu, repeat: %lu, repeat_p ~= p: %lf", count, r, (tb_double_t)r / count);
#else
tb_trace_i("cstr: count: %lu, repeat: %lu", count, r);
#endif
// exit filter
tb_bloom_filter_exit(filter);
}
}
static tb_void_t tb_demo_test_uint8_h(tb_size_t index)
{
// the count
tb_size_t count = TB_MAXU8;
// save element
g_func_indx = index;
g_func_prev = tb_element_uint8();
// the element
tb_element_t element = g_func_prev;
element.hash = tb_demo_test_hash_func;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 1, count, element);
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
tb_hong_t t = tb_mclock();
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random_range(0, TB_MAXU8);
// set value to filter
if (!tb_bloom_filter_set(filter, (tb_cpointer_t)value))
{
// repeat++
r++;
}
}
t = tb_mclock() - t;
// trace
tb_trace_i("uint8: index: %lu, repeat: %lu, time: %lld ms", index, r, t);
// exit filter
tb_bloom_filter_exit(filter);
}
}
static tb_void_t tb_demo_test_uint16_h(tb_size_t index)
{
// the count
tb_size_t count = TB_MAXU16;
// save element
g_func_indx = index;
g_func_prev = tb_element_uint16();
// the element
tb_element_t element = g_func_prev;
element.hash = tb_demo_test_hash_func;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 1, count, element);
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
tb_hong_t t = tb_mclock();
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random_range(0, TB_MAXU16);
// set value to filter
if (!tb_bloom_filter_set(filter, (tb_cpointer_t)value))
{
// repeat++
r++;
}
}
t = tb_mclock() - t;
// trace
tb_trace_i("uint16: index: %lu, repeat: %lu, time: %lld ms", index, r, t);
// exit filter
tb_bloom_filter_exit(filter);
}
}
static tb_void_t tb_demo_test_uint32_h(tb_size_t index)
{
// the count
tb_size_t count = 1000000;
// save element
g_func_indx = index;
g_func_prev = tb_element_uint32();
// the element
tb_element_t element = g_func_prev;
element.hash = tb_demo_test_hash_func;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 1, count, element);
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
tb_hong_t t = tb_mclock();
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random_value();
// set value to filter
if (!tb_bloom_filter_set(filter, (tb_cpointer_t)value))
{
// repeat++
r++;
}
}
t = tb_mclock() - t;
// trace
tb_trace_i("uint32: index: %lu, repeat: %lu, time: %lld ms", index, r, t);
// exit filter
tb_bloom_filter_exit(filter);
}
}
static tb_void_t tb_demo_test_long_h(tb_size_t index)
{
// the count
tb_size_t count = 1000000;
// save element
g_func_indx = index;
g_func_prev = tb_element_long();
// the element
tb_element_t element = g_func_prev;
element.hash = tb_demo_test_hash_func;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 1, count, element);
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
tb_hong_t t = tb_mclock();
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random();
// set value to filter
if (!tb_bloom_filter_set(filter, (tb_cpointer_t)value))
{
// repeat++
r++;
}
}
t = tb_mclock() - t;
// trace
tb_trace_i("long: index: %lu, repeat: %lu, time: %lld ms", index, r, t);
// exit filter
tb_bloom_filter_exit(filter);
}
}
static tb_void_t tb_demo_test_long_p()
{
// the count
tb_size_t count = 10000000;
// init filter
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_01, 3, count, tb_element_long());
if (filter)
{
// done
tb_size_t i = 0;
tb_size_t r = 0;
for (i = 0; i < count; i++)
{
// the value
tb_long_t value = tb_random();
// set value to filter
if (!tb_bloom_filter_set(filter, (tb_cpointer_t)value))
{
// repeat++
r++;
}
}
// trace
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_trace_i("long: count: %lu, repeat: %lu, repeat_p ~= p: %lf", count, r, (tb_double_t)r / count);
#else
tb_trace_i("long: count: %lu, repeat: %lu", count, r);
#endif
// exit filter
tb_bloom_filter_exit(filter);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_bloom_filter_main(tb_int_t argc, tb_char_t** argv)
{
tb_trace_i("===========================================================");
tb_demo_test_uint8_h(0);
tb_demo_test_uint8_h(1);
tb_demo_test_uint8_h(2);
tb_demo_test_uint8_h(3);
tb_demo_test_uint8_h(4);
tb_demo_test_uint8_h(5);
tb_demo_test_uint8_h(6);
tb_demo_test_uint8_h(7);
tb_demo_test_uint8_h(8);
tb_demo_test_uint8_h(9);
tb_demo_test_uint8_h(10);
tb_demo_test_uint8_h(11);
tb_demo_test_uint8_h(12);
tb_demo_test_uint8_h(13);
tb_demo_test_uint8_h(14);
tb_demo_test_uint8_h(15);
tb_trace_i("===========================================================");
tb_demo_test_uint16_h(0);
tb_demo_test_uint16_h(1);
tb_demo_test_uint16_h(2);
tb_demo_test_uint16_h(3);
tb_demo_test_uint16_h(4);
tb_demo_test_uint16_h(5);
tb_demo_test_uint16_h(6);
tb_demo_test_uint16_h(7);
tb_demo_test_uint16_h(8);
tb_demo_test_uint16_h(9);
tb_demo_test_uint16_h(10);
tb_demo_test_uint16_h(11);
tb_demo_test_uint16_h(12);
tb_demo_test_uint16_h(13);
tb_demo_test_uint16_h(14);
tb_demo_test_uint16_h(15);
tb_trace_i("===========================================================");
tb_demo_test_uint32_h(0);
tb_demo_test_uint32_h(1);
tb_demo_test_uint32_h(2);
tb_demo_test_uint32_h(3);
tb_demo_test_uint32_h(4);
tb_demo_test_uint32_h(5);
tb_demo_test_uint32_h(6);
tb_demo_test_uint32_h(7);
tb_demo_test_uint32_h(8);
tb_demo_test_uint32_h(9);
tb_demo_test_uint32_h(10);
tb_demo_test_uint32_h(11);
tb_demo_test_uint32_h(12);
tb_demo_test_uint32_h(13);
tb_demo_test_uint32_h(14);
tb_demo_test_uint32_h(15);
tb_trace_i("===========================================================");
tb_demo_test_long_h(0);
tb_demo_test_long_h(1);
tb_demo_test_long_h(2);
tb_demo_test_long_h(3);
tb_demo_test_long_h(4);
tb_demo_test_long_h(5);
tb_demo_test_long_h(6);
tb_demo_test_long_h(7);
tb_demo_test_long_h(8);
tb_demo_test_long_h(9);
tb_demo_test_long_h(10);
tb_demo_test_long_h(11);
tb_demo_test_long_h(12);
tb_demo_test_long_h(13);
tb_demo_test_long_h(14);
tb_demo_test_long_h(15);
tb_trace_i("===========================================================");
tb_demo_test_cstr_h(0);
tb_demo_test_cstr_h(1);
tb_demo_test_cstr_h(2);
tb_demo_test_cstr_h(3);
tb_demo_test_cstr_h(4);
tb_demo_test_cstr_h(5);
tb_demo_test_cstr_h(6);
tb_demo_test_cstr_h(7);
tb_demo_test_cstr_h(8);
tb_demo_test_cstr_h(9);
tb_demo_test_cstr_h(10);
tb_demo_test_cstr_h(11);
tb_demo_test_cstr_h(12);
// tb_demo_test_cstr_h(13);
// tb_demo_test_cstr_h(14);
// tb_demo_test_cstr_h(15);
tb_trace_i("===========================================================");
tb_demo_test_long_p();
tb_demo_test_cstr_p();
return 0;
}
tbox-1.6.7/src/demo/container/circle_queue.c 0000664 0000000 0000000 00000021266 14142237372 0021023 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_circle_queue_put_and_pop_test()
{
// init
tb_circle_queue_ref_t queue = tb_circle_queue_init(10, tb_element_long());
tb_assert_and_check_return(queue);
// make queue
tb_circle_queue_put(queue, (tb_pointer_t)0);
tb_circle_queue_put(queue, (tb_pointer_t)1);
tb_circle_queue_put(queue, (tb_pointer_t)2);
tb_circle_queue_put(queue, (tb_pointer_t)3);
tb_circle_queue_put(queue, (tb_pointer_t)4);
tb_circle_queue_put(queue, (tb_pointer_t)5);
tb_circle_queue_put(queue, (tb_pointer_t)6);
tb_circle_queue_put(queue, (tb_pointer_t)7);
tb_circle_queue_put(queue, (tb_pointer_t)8);
tb_circle_queue_put(queue, (tb_pointer_t)9);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++)
{
tb_circle_queue_pop(queue);
tb_circle_queue_put(queue, (tb_pointer_t)0xf);
}
t = tb_mclock() - t;
// trace
tb_trace_i("tb_circle_queue_put_and_pop(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_circle_queue_size(queue), tb_circle_queue_maxn(queue));
// check
tb_assert(tb_circle_queue_size(queue) == 10);
tb_assert(tb_circle_queue_head(queue) == (tb_pointer_t)0xf);
tb_assert(tb_circle_queue_last(queue) == (tb_pointer_t)0xf);
// clear it
tb_circle_queue_clear(queue);
tb_assert(!tb_circle_queue_size(queue));
// exit
tb_circle_queue_exit(queue);
}
static tb_void_t tb_circle_queue_iterator_next_test()
{
// init
tb_size_t n = 1000000;
tb_circle_queue_ref_t queue = tb_circle_queue_init(n, tb_element_long());
tb_assert_and_check_return(queue);
// make queue
while (n--) tb_circle_queue_put(queue, (tb_pointer_t)0xf);
// done
tb_hong_t t = tb_mclock();
tb_for_all (tb_char_t*, item, queue) tb_used(item);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_circle_queue_iterator_next(%lu): %lld ms, size: %lu, maxn: %lu", 1000000, t, tb_circle_queue_size(queue), tb_circle_queue_maxn(queue));
// exit
tb_circle_queue_exit(queue);
}
static tb_void_t tb_circle_queue_int_dump(tb_circle_queue_ref_t queue)
{
tb_trace_i("tb_int_t size: %lu, maxn: %lu", tb_circle_queue_size(queue), tb_circle_queue_maxn(queue));
tb_for_all (tb_char_t*, item, queue)
{
tb_trace_i("tb_int_t at[%lu]: %u", item_itor, item);
}
}
static tb_void_t tb_circle_queue_int_test()
{
tb_circle_queue_ref_t queue = tb_circle_queue_init(10, tb_element_long());
tb_assert_and_check_return(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_circle_queue_put(queue, (tb_pointer_t)0);
tb_circle_queue_put(queue, (tb_pointer_t)1);
tb_circle_queue_put(queue, (tb_pointer_t)2);
tb_circle_queue_put(queue, (tb_pointer_t)3);
tb_circle_queue_put(queue, (tb_pointer_t)4);
tb_circle_queue_put(queue, (tb_pointer_t)5);
tb_circle_queue_put(queue, (tb_pointer_t)6);
tb_circle_queue_put(queue, (tb_pointer_t)7);
tb_circle_queue_put(queue, (tb_pointer_t)8);
tb_circle_queue_put(queue, (tb_pointer_t)9);
tb_circle_queue_int_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("pop:");
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_int_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_circle_queue_put(queue, (tb_pointer_t)0);
tb_circle_queue_put(queue, (tb_pointer_t)1);
tb_circle_queue_put(queue, (tb_pointer_t)2);
tb_circle_queue_put(queue, (tb_pointer_t)3);
tb_circle_queue_put(queue, (tb_pointer_t)4);
tb_circle_queue_int_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_circle_queue_clear(queue);
tb_circle_queue_int_dump(queue);
tb_circle_queue_exit(queue);
}
static tb_void_t tb_circle_queue_str_dump(tb_circle_queue_ref_t queue)
{
tb_trace_i("str size: %lu, maxn: %lu", tb_circle_queue_size(queue), tb_circle_queue_maxn(queue));
tb_for_all (tb_char_t*, item, queue)
{
tb_trace_i("str at[%lu]: %s", item_itor, item);
}
}
static tb_void_t tb_circle_queue_str_test()
{
tb_circle_queue_ref_t queue = tb_circle_queue_init(10, tb_element_str(tb_true));
tb_assert_and_check_return(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_circle_queue_put(queue, "0000000000");
tb_circle_queue_put(queue, "1111111111");
tb_circle_queue_put(queue, "2222222222");
tb_circle_queue_put(queue, "3333333333");
tb_circle_queue_put(queue, "4444444444");
tb_circle_queue_put(queue, "5555555555");
tb_circle_queue_put(queue, "6666666666");
tb_circle_queue_put(queue, "7777777777");
tb_circle_queue_put(queue, "8888888888");
tb_circle_queue_put(queue, "9999999999");
tb_circle_queue_str_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("pop:");
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_str_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_circle_queue_put(queue, "0000000000");
tb_circle_queue_put(queue, "1111111111");
tb_circle_queue_put(queue, "2222222222");
tb_circle_queue_put(queue, "3333333333");
tb_circle_queue_put(queue, "4444444444");
tb_circle_queue_str_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_circle_queue_clear(queue);
tb_circle_queue_str_dump(queue);
tb_circle_queue_exit(queue);
}
static tb_void_t tb_circle_queue_mem_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_trace_i("ifm free: %s, priv: %s", buff, element->priv);
}
static tb_void_t tb_circle_queue_mem_dump(tb_circle_queue_ref_t queue)
{
tb_trace_i("ifm size: %lu, maxn: %lu", tb_circle_queue_size(queue), tb_circle_queue_maxn(queue));
tb_for_all (tb_char_t*, item, queue)
{
tb_trace_i("ifm at[%lu]: %s", item_itor, item);
}
}
static tb_void_t tb_circle_queue_mem_test()
{
tb_circle_queue_ref_t queue = tb_circle_queue_init(10, tb_element_mem(11, tb_circle_queue_mem_free, "ifm"));
tb_assert_and_check_return(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_circle_queue_put(queue, "0000000000");
tb_circle_queue_put(queue, "1111111111");
tb_circle_queue_put(queue, "2222222222");
tb_circle_queue_put(queue, "3333333333");
tb_circle_queue_put(queue, "4444444444");
tb_circle_queue_put(queue, "5555555555");
tb_circle_queue_put(queue, "6666666666");
tb_circle_queue_put(queue, "7777777777");
tb_circle_queue_put(queue, "8888888888");
tb_circle_queue_put(queue, "9999999999");
tb_circle_queue_mem_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("pop:");
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_pop(queue);
tb_circle_queue_mem_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_circle_queue_put(queue, "0000000000");
tb_circle_queue_put(queue, "1111111111");
tb_circle_queue_put(queue, "2222222222");
tb_circle_queue_put(queue, "3333333333");
tb_circle_queue_put(queue, "4444444444");
tb_circle_queue_mem_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_circle_queue_clear(queue);
tb_circle_queue_mem_dump(queue);
tb_circle_queue_exit(queue);
}
static tb_void_t tb_circle_queue_perf_test()
{
tb_circle_queue_put_and_pop_test();
tb_circle_queue_iterator_next_test();
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_circle_queue_main(tb_int_t argc, tb_char_t** argv)
{
tb_circle_queue_int_test();
tb_circle_queue_str_test();
tb_circle_queue_mem_test();
tb_circle_queue_perf_test();
return 0;
}
tbox-1.6.7/src/demo/container/hash_map.c 0000664 0000000 0000000 00000054113 14142237372 0020133 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __tb_debug__
# define tb_hash_map_test_dump(h) tb_hash_map_dump(h)
#else
# define tb_hash_map_test_dump(h)
#endif
#define tb_hash_map_test_get_s2i(h, s) do {tb_assert(tb_strlen((tb_char_t*)s) == (tb_size_t)tb_hash_map_get(h, (tb_char_t*)(s))); } while (0);
#define tb_hash_map_test_insert_s2i(h, s) do {tb_size_t n = tb_strlen((tb_char_t*)(s)); tb_hash_map_insert(h, (tb_char_t*)(s), (tb_pointer_t)n); } while (0);
#define tb_hash_map_test_remove_s2i(h, s) do {tb_hash_map_remove(h, s); tb_assert(!tb_hash_map_get(h, s)); } while (0);
#define tb_hash_map_test_get_i2s(h, i) do {tb_char_t s[256] = {0}; tb_snprintf(s, 256, "%u", i); tb_assert(!tb_strcmp(s, (tb_char_t const*)tb_hash_map_get(h, (tb_pointer_t)i))); } while (0);
#define tb_hash_map_test_insert_i2s(h, i) do {tb_char_t s[256] = {0}; tb_snprintf(s, 256, "%u", i); tb_hash_map_insert(h, (tb_pointer_t)i, s); } while (0);
#define tb_hash_map_test_remove_i2s(h, i) do {tb_hash_map_remove(h, (tb_pointer_t)i); tb_assert(!tb_hash_map_get(h, (tb_pointer_t)i)); } while (0);
#define tb_hash_map_test_get_m2m(h, i) do {tb_memset_u32(item, i, step >> 2); tb_assert(!tb_memcmp(item, tb_hash_map_get(h, item), step)); } while (0);
#define tb_hash_map_test_insert_m2m(h, i) do {tb_memset_u32(item, i, step >> 2); tb_hash_map_insert(h, item, item); } while (0);
#define tb_hash_map_test_remove_m2m(h, i) do {tb_memset_u32(item, i, step >> 2); tb_hash_map_remove(h, item); tb_assert(!tb_hash_map_get(h, item)); } while (0);
#define tb_hash_map_test_get_i2i(h, i) do {tb_assert(i == (tb_size_t)tb_hash_map_get(h, (tb_pointer_t)i)); } while (0);
#define tb_hash_map_test_insert_i2i(h, i) do {tb_hash_map_insert(h, (tb_pointer_t)i, (tb_pointer_t)i); } while (0);
#define tb_hash_map_test_remove_i2i(h, i) do {tb_hash_map_remove(h, (tb_pointer_t)i); tb_assert(!tb_hash_map_get(h, (tb_pointer_t)i)); } while (0);
#define tb_hash_map_test_get_i2t(h, i) do {tb_assert(tb_hash_map_get(h, (tb_pointer_t)i)); } while (0);
#define tb_hash_map_test_insert_i2t(h, i) do {tb_hash_map_insert(h, (tb_pointer_t)i, (tb_pointer_t)(tb_size_t)tb_true); } while (0);
#define tb_hash_map_test_remove_i2t(h, i) do {tb_hash_map_remove(h, (tb_pointer_t)i); tb_assert(!tb_hash_map_get(h, (tb_pointer_t)i)); } while (0);
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_hash_map_test_s2i_func()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(8, tb_element_str(tb_true), tb_element_long());
tb_assert_and_check_return(hash);
// set
tb_hash_map_test_insert_s2i(hash, "");
tb_hash_map_test_insert_s2i(hash, "0");
tb_hash_map_test_insert_s2i(hash, "01");
tb_hash_map_test_insert_s2i(hash, "012");
tb_hash_map_test_insert_s2i(hash, "0123");
tb_hash_map_test_insert_s2i(hash, "01234");
tb_hash_map_test_insert_s2i(hash, "012345");
tb_hash_map_test_insert_s2i(hash, "0123456");
tb_hash_map_test_insert_s2i(hash, "01234567");
tb_hash_map_test_insert_s2i(hash, "012345678");
tb_hash_map_test_insert_s2i(hash, "0123456789");
tb_hash_map_test_insert_s2i(hash, "9876543210");
tb_hash_map_test_insert_s2i(hash, "876543210");
tb_hash_map_test_insert_s2i(hash, "76543210");
tb_hash_map_test_insert_s2i(hash, "6543210");
tb_hash_map_test_insert_s2i(hash, "543210");
tb_hash_map_test_insert_s2i(hash, "43210");
tb_hash_map_test_insert_s2i(hash, "3210");
tb_hash_map_test_insert_s2i(hash, "210");
tb_hash_map_test_insert_s2i(hash, "10");
tb_hash_map_test_insert_s2i(hash, "0");
tb_hash_map_test_insert_s2i(hash, "");
tb_hash_map_test_dump(hash);
// get
tb_hash_map_test_get_s2i(hash, "");
tb_hash_map_test_get_s2i(hash, "01");
tb_hash_map_test_get_s2i(hash, "012");
tb_hash_map_test_get_s2i(hash, "0123");
tb_hash_map_test_get_s2i(hash, "01234");
tb_hash_map_test_get_s2i(hash, "012345");
tb_hash_map_test_get_s2i(hash, "0123456");
tb_hash_map_test_get_s2i(hash, "01234567");
tb_hash_map_test_get_s2i(hash, "012345678");
tb_hash_map_test_get_s2i(hash, "0123456789");
tb_hash_map_test_get_s2i(hash, "9876543210");
tb_hash_map_test_get_s2i(hash, "876543210");
tb_hash_map_test_get_s2i(hash, "76543210");
tb_hash_map_test_get_s2i(hash, "6543210");
tb_hash_map_test_get_s2i(hash, "543210");
tb_hash_map_test_get_s2i(hash, "43210");
tb_hash_map_test_get_s2i(hash, "3210");
tb_hash_map_test_get_s2i(hash, "210");
tb_hash_map_test_get_s2i(hash, "10");
tb_hash_map_test_get_s2i(hash, "0");
tb_hash_map_test_get_s2i(hash, "");
// del
tb_hash_map_test_remove_s2i(hash, "");
tb_hash_map_test_remove_s2i(hash, "01");
tb_hash_map_test_remove_s2i(hash, "012");
tb_hash_map_test_remove_s2i(hash, "0123");
tb_hash_map_test_remove_s2i(hash, "01234");
tb_hash_map_test_remove_s2i(hash, "012345");
tb_hash_map_test_remove_s2i(hash, "0123456");
tb_hash_map_test_remove_s2i(hash, "01234567");
tb_hash_map_test_remove_s2i(hash, "012345678");
tb_hash_map_test_remove_s2i(hash, "0123456789");
tb_hash_map_test_remove_s2i(hash, "0123456789");
tb_hash_map_test_dump(hash);
// clear
tb_hash_map_clear(hash);
tb_hash_map_test_dump(hash);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_s2i_perf()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(0, tb_element_str(tb_true), tb_element_long());
tb_assert_and_check_return(hash);
// performance
tb_char_t s[256] = {0};
__tb_volatile__ tb_size_t n = 100000;
tb_hong_t t = tb_mclock();
while (n--)
{
tb_long_t r = tb_snprintf(s, sizeof(s) - 1, "%ld", tb_random_value());
s[r] = '\0';
tb_hash_map_test_insert_s2i(hash, s);
tb_hash_map_test_get_s2i(hash, s);
}
t = tb_mclock() - t;
tb_trace_i("s2i: time: %lld", t);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_i2s_func()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(8, tb_element_long(), tb_element_str(tb_true));
tb_assert_and_check_return(hash);
// set
tb_hash_map_test_insert_i2s(hash, 0);
tb_hash_map_test_insert_i2s(hash, 1);
tb_hash_map_test_insert_i2s(hash, 12);
tb_hash_map_test_insert_i2s(hash, 123);
tb_hash_map_test_insert_i2s(hash, 1234);
tb_hash_map_test_insert_i2s(hash, 12345);
tb_hash_map_test_insert_i2s(hash, 123456);
tb_hash_map_test_insert_i2s(hash, 1234567);
tb_hash_map_test_insert_i2s(hash, 12345678);
tb_hash_map_test_insert_i2s(hash, 123456789);
tb_hash_map_test_insert_i2s(hash, 876543210);
tb_hash_map_test_insert_i2s(hash, 76543210);
tb_hash_map_test_insert_i2s(hash, 6543210);
tb_hash_map_test_insert_i2s(hash, 543210);
tb_hash_map_test_insert_i2s(hash, 43210);
tb_hash_map_test_insert_i2s(hash, 3210);
tb_hash_map_test_insert_i2s(hash, 210);
tb_hash_map_test_insert_i2s(hash, 10);
tb_hash_map_test_insert_i2s(hash, 0);
tb_hash_map_test_dump(hash);
// get
tb_hash_map_test_get_i2s(hash, 0);
tb_hash_map_test_get_i2s(hash, 1);
tb_hash_map_test_get_i2s(hash, 12);
tb_hash_map_test_get_i2s(hash, 123);
tb_hash_map_test_get_i2s(hash, 1234);
tb_hash_map_test_get_i2s(hash, 12345);
tb_hash_map_test_get_i2s(hash, 123456);
tb_hash_map_test_get_i2s(hash, 1234567);
tb_hash_map_test_get_i2s(hash, 12345678);
tb_hash_map_test_get_i2s(hash, 123456789);
tb_hash_map_test_get_i2s(hash, 876543210);
tb_hash_map_test_get_i2s(hash, 76543210);
tb_hash_map_test_get_i2s(hash, 6543210);
tb_hash_map_test_get_i2s(hash, 543210);
tb_hash_map_test_get_i2s(hash, 43210);
tb_hash_map_test_get_i2s(hash, 3210);
tb_hash_map_test_get_i2s(hash, 210);
tb_hash_map_test_get_i2s(hash, 10);
tb_hash_map_test_get_i2s(hash, 0);
// del
tb_hash_map_test_remove_i2s(hash, 0);
tb_hash_map_test_remove_i2s(hash, 1);
tb_hash_map_test_remove_i2s(hash, 12);
tb_hash_map_test_remove_i2s(hash, 123);
tb_hash_map_test_remove_i2s(hash, 1234);
tb_hash_map_test_remove_i2s(hash, 12345);
tb_hash_map_test_remove_i2s(hash, 123456);
tb_hash_map_test_remove_i2s(hash, 1234567);
tb_hash_map_test_remove_i2s(hash, 12345678);
tb_hash_map_test_remove_i2s(hash, 123456789);
tb_hash_map_test_remove_i2s(hash, 123456789);
tb_hash_map_test_dump(hash);
// clear
tb_hash_map_clear(hash);
tb_hash_map_test_dump(hash);
// exit
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_i2s_perf()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(0, tb_element_long(), tb_element_str(tb_true));
tb_assert_and_check_return(hash);
// performance
__tb_volatile__ tb_size_t n = 100000;
tb_hong_t t = tb_mclock();
while (n--)
{
tb_size_t i = tb_random_value();
tb_hash_map_test_insert_i2s(hash, i);
tb_hash_map_test_get_i2s(hash, i);
}
t = tb_mclock() - t;
tb_trace_i("i2s: time: %lld", t);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_m2m_func()
{
// init hash
tb_size_t const step = 256;
tb_byte_t item[step];
tb_hash_map_ref_t hash = tb_hash_map_init(8, tb_element_mem(step, tb_null, tb_null), tb_element_mem(step, tb_null, tb_null));
tb_assert_and_check_return(hash);
// set
tb_hash_map_test_insert_m2m(hash, 0);
tb_hash_map_test_insert_m2m(hash, 1);
tb_hash_map_test_insert_m2m(hash, 2);
tb_hash_map_test_insert_m2m(hash, 3);
tb_hash_map_test_insert_m2m(hash, 4);
tb_hash_map_test_insert_m2m(hash, 5);
tb_hash_map_test_insert_m2m(hash, 6);
tb_hash_map_test_insert_m2m(hash, 7);
tb_hash_map_test_insert_m2m(hash, 8);
tb_hash_map_test_insert_m2m(hash, 9);
tb_hash_map_test_insert_m2m(hash, 10);
tb_hash_map_test_insert_m2m(hash, 11);
tb_hash_map_test_insert_m2m(hash, 12);
tb_hash_map_test_insert_m2m(hash, 13);
tb_hash_map_test_insert_m2m(hash, 14);
tb_hash_map_test_insert_m2m(hash, 15);
tb_hash_map_test_insert_m2m(hash, 16);
tb_hash_map_test_insert_m2m(hash, 17);
tb_hash_map_test_insert_m2m(hash, 18);
tb_hash_map_test_insert_m2m(hash, 19);
tb_hash_map_test_insert_m2m(hash, 20);
tb_hash_map_test_insert_m2m(hash, 21);
tb_hash_map_test_insert_m2m(hash, 22);
tb_hash_map_test_insert_m2m(hash, 23);
tb_hash_map_test_insert_m2m(hash, 24);
tb_hash_map_test_insert_m2m(hash, 25);
tb_hash_map_test_insert_m2m(hash, 26);
tb_hash_map_test_insert_m2m(hash, 27);
tb_hash_map_test_insert_m2m(hash, 28);
tb_hash_map_test_insert_m2m(hash, 29);
tb_hash_map_test_insert_m2m(hash, 30);
tb_hash_map_test_insert_m2m(hash, 31);
tb_hash_map_test_insert_m2m(hash, 32);
tb_hash_map_test_dump(hash);
// get
tb_hash_map_test_get_m2m(hash, 0);
tb_hash_map_test_get_m2m(hash, 1);
tb_hash_map_test_get_m2m(hash, 2);
tb_hash_map_test_get_m2m(hash, 3);
tb_hash_map_test_get_m2m(hash, 4);
tb_hash_map_test_get_m2m(hash, 5);
tb_hash_map_test_get_m2m(hash, 6);
tb_hash_map_test_get_m2m(hash, 7);
tb_hash_map_test_get_m2m(hash, 8);
tb_hash_map_test_get_m2m(hash, 9);
tb_hash_map_test_get_m2m(hash, 10);
tb_hash_map_test_get_m2m(hash, 11);
tb_hash_map_test_get_m2m(hash, 12);
tb_hash_map_test_get_m2m(hash, 13);
tb_hash_map_test_get_m2m(hash, 14);
tb_hash_map_test_get_m2m(hash, 15);
tb_hash_map_test_get_m2m(hash, 16);
tb_hash_map_test_get_m2m(hash, 17);
tb_hash_map_test_get_m2m(hash, 18);
tb_hash_map_test_get_m2m(hash, 19);
tb_hash_map_test_get_m2m(hash, 20);
tb_hash_map_test_get_m2m(hash, 21);
tb_hash_map_test_get_m2m(hash, 22);
tb_hash_map_test_get_m2m(hash, 23);
tb_hash_map_test_get_m2m(hash, 24);
tb_hash_map_test_get_m2m(hash, 25);
tb_hash_map_test_get_m2m(hash, 26);
tb_hash_map_test_get_m2m(hash, 27);
tb_hash_map_test_get_m2m(hash, 28);
tb_hash_map_test_get_m2m(hash, 29);
tb_hash_map_test_get_m2m(hash, 30);
tb_hash_map_test_get_m2m(hash, 31);
tb_hash_map_test_get_m2m(hash, 32);
// del
tb_hash_map_test_remove_m2m(hash, 10);
tb_hash_map_test_remove_m2m(hash, 11);
tb_hash_map_test_remove_m2m(hash, 12);
tb_hash_map_test_remove_m2m(hash, 13);
tb_hash_map_test_remove_m2m(hash, 14);
tb_hash_map_test_remove_m2m(hash, 15);
tb_hash_map_test_remove_m2m(hash, 16);
tb_hash_map_test_remove_m2m(hash, 17);
tb_hash_map_test_remove_m2m(hash, 18);
tb_hash_map_test_remove_m2m(hash, 19);
tb_hash_map_test_remove_m2m(hash, 20);
tb_hash_map_test_remove_m2m(hash, 21);
tb_hash_map_test_remove_m2m(hash, 22);
tb_hash_map_test_remove_m2m(hash, 23);
tb_hash_map_test_remove_m2m(hash, 24);
tb_hash_map_test_remove_m2m(hash, 25);
tb_hash_map_test_remove_m2m(hash, 26);
tb_hash_map_test_remove_m2m(hash, 27);
tb_hash_map_test_remove_m2m(hash, 28);
tb_hash_map_test_remove_m2m(hash, 29);
tb_hash_map_test_remove_m2m(hash, 30);
tb_hash_map_test_remove_m2m(hash, 31);
tb_hash_map_test_remove_m2m(hash, 32);
tb_hash_map_test_dump(hash);
// clear
tb_hash_map_clear(hash);
tb_hash_map_test_dump(hash);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_m2m_perf()
{
// init hash: mem => mem
tb_size_t const step = 12;
tb_byte_t item[step];
tb_hash_map_ref_t hash = tb_hash_map_init(0, tb_element_mem(step, tb_null, tb_null), tb_element_mem(step, tb_null, tb_null));
tb_assert_and_check_return(hash);
// performance
__tb_volatile__ tb_size_t n = 100000;
tb_hong_t t = tb_mclock();
while (n--)
{
tb_uint32_t i = (tb_uint32_t)tb_random_value();
tb_hash_map_test_insert_m2m(hash, i);
tb_hash_map_test_get_m2m(hash, i);
}
t = tb_mclock() - t;
tb_trace_i("m2m: time: %lld", t);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_i2i_func()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(8, tb_element_long(), tb_element_long());
tb_assert_and_check_return(hash);
// set
tb_hash_map_test_insert_i2i(hash, 0);
tb_hash_map_test_insert_i2i(hash, 1);
tb_hash_map_test_insert_i2i(hash, 12);
tb_hash_map_test_insert_i2i(hash, 123);
tb_hash_map_test_insert_i2i(hash, 1234);
tb_hash_map_test_insert_i2i(hash, 12345);
tb_hash_map_test_insert_i2i(hash, 123456);
tb_hash_map_test_insert_i2i(hash, 1234567);
tb_hash_map_test_insert_i2i(hash, 12345678);
tb_hash_map_test_insert_i2i(hash, 123456789);
tb_hash_map_test_insert_i2i(hash, 876543210);
tb_hash_map_test_insert_i2i(hash, 76543210);
tb_hash_map_test_insert_i2i(hash, 6543210);
tb_hash_map_test_insert_i2i(hash, 543210);
tb_hash_map_test_insert_i2i(hash, 43210);
tb_hash_map_test_insert_i2i(hash, 3210);
tb_hash_map_test_insert_i2i(hash, 210);
tb_hash_map_test_insert_i2i(hash, 10);
tb_hash_map_test_insert_i2i(hash, 0);
tb_hash_map_test_dump(hash);
// get
tb_hash_map_test_get_i2i(hash, 0);
tb_hash_map_test_get_i2i(hash, 1);
tb_hash_map_test_get_i2i(hash, 12);
tb_hash_map_test_get_i2i(hash, 123);
tb_hash_map_test_get_i2i(hash, 1234);
tb_hash_map_test_get_i2i(hash, 12345);
tb_hash_map_test_get_i2i(hash, 123456);
tb_hash_map_test_get_i2i(hash, 1234567);
tb_hash_map_test_get_i2i(hash, 12345678);
tb_hash_map_test_get_i2i(hash, 123456789);
tb_hash_map_test_get_i2i(hash, 876543210);
tb_hash_map_test_get_i2i(hash, 76543210);
tb_hash_map_test_get_i2i(hash, 6543210);
tb_hash_map_test_get_i2i(hash, 543210);
tb_hash_map_test_get_i2i(hash, 43210);
tb_hash_map_test_get_i2i(hash, 3210);
tb_hash_map_test_get_i2i(hash, 210);
tb_hash_map_test_get_i2i(hash, 10);
tb_hash_map_test_get_i2i(hash, 0);
// del
tb_hash_map_test_remove_i2i(hash, 0);
tb_hash_map_test_remove_i2i(hash, 1);
tb_hash_map_test_remove_i2i(hash, 12);
tb_hash_map_test_remove_i2i(hash, 123);
tb_hash_map_test_remove_i2i(hash, 1234);
tb_hash_map_test_remove_i2i(hash, 12345);
tb_hash_map_test_remove_i2i(hash, 123456);
tb_hash_map_test_remove_i2i(hash, 1234567);
tb_hash_map_test_remove_i2i(hash, 12345678);
tb_hash_map_test_remove_i2i(hash, 123456789);
tb_hash_map_test_remove_i2i(hash, 123456789);
tb_hash_map_test_dump(hash);
// clear
tb_hash_map_clear(hash);
tb_hash_map_test_dump(hash);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_i2i_perf()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(0, tb_element_long(), tb_element_long());
tb_assert_and_check_return(hash);
// performance
__tb_volatile__ tb_size_t n = 100000;
tb_hong_t t = tb_mclock();
while (n--)
{
tb_size_t i = tb_random_value();
tb_hash_map_test_insert_i2i(hash, i);
tb_hash_map_test_get_i2i(hash, i);
}
t = tb_mclock() - t;
tb_trace_i("i2i: time: %lld", t);
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_i2t_func()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(8, tb_element_long(), tb_element_true());
tb_assert_and_check_return(hash);
// set
tb_hash_map_test_insert_i2t(hash, 0);
tb_hash_map_test_insert_i2t(hash, 1);
tb_hash_map_test_insert_i2t(hash, 12);
tb_hash_map_test_insert_i2t(hash, 123);
tb_hash_map_test_insert_i2t(hash, 1234);
tb_hash_map_test_insert_i2t(hash, 12345);
tb_hash_map_test_insert_i2t(hash, 123456);
tb_hash_map_test_insert_i2t(hash, 1234567);
tb_hash_map_test_insert_i2t(hash, 12345678);
tb_hash_map_test_insert_i2t(hash, 123456789);
tb_hash_map_test_insert_i2t(hash, 876543210);
tb_hash_map_test_insert_i2t(hash, 76543210);
tb_hash_map_test_insert_i2t(hash, 6543210);
tb_hash_map_test_insert_i2t(hash, 543210);
tb_hash_map_test_insert_i2t(hash, 43210);
tb_hash_map_test_insert_i2t(hash, 3210);
tb_hash_map_test_insert_i2t(hash, 210);
tb_hash_map_test_insert_i2t(hash, 10);
tb_hash_map_test_insert_i2t(hash, 0);
tb_hash_map_test_dump(hash);
// get
tb_hash_map_test_get_i2t(hash, 0);
tb_hash_map_test_get_i2t(hash, 1);
tb_hash_map_test_get_i2t(hash, 12);
tb_hash_map_test_get_i2t(hash, 123);
tb_hash_map_test_get_i2t(hash, 1234);
tb_hash_map_test_get_i2t(hash, 12345);
tb_hash_map_test_get_i2t(hash, 123456);
tb_hash_map_test_get_i2t(hash, 1234567);
tb_hash_map_test_get_i2t(hash, 12345678);
tb_hash_map_test_get_i2t(hash, 123456789);
tb_hash_map_test_get_i2t(hash, 876543210);
tb_hash_map_test_get_i2t(hash, 76543210);
tb_hash_map_test_get_i2t(hash, 6543210);
tb_hash_map_test_get_i2t(hash, 543210);
tb_hash_map_test_get_i2t(hash, 43210);
tb_hash_map_test_get_i2t(hash, 3210);
tb_hash_map_test_get_i2t(hash, 210);
tb_hash_map_test_get_i2t(hash, 10);
tb_hash_map_test_get_i2t(hash, 0);
// del
tb_hash_map_test_remove_i2t(hash, 0);
tb_hash_map_test_remove_i2t(hash, 1);
tb_hash_map_test_remove_i2t(hash, 12);
tb_hash_map_test_remove_i2t(hash, 123);
tb_hash_map_test_remove_i2t(hash, 1234);
tb_hash_map_test_remove_i2t(hash, 12345);
tb_hash_map_test_remove_i2t(hash, 123456);
tb_hash_map_test_remove_i2t(hash, 1234567);
tb_hash_map_test_remove_i2t(hash, 12345678);
tb_hash_map_test_remove_i2t(hash, 123456789);
tb_hash_map_test_remove_i2t(hash, 123456789);
tb_hash_map_test_dump(hash);
// clear
tb_hash_map_clear(hash);
tb_hash_map_test_dump(hash);
// exit
tb_hash_map_exit(hash);
}
static tb_void_t tb_hash_map_test_i2t_perf()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(0, tb_element_long(), tb_element_true());
tb_assert_and_check_return(hash);
// done
__tb_volatile__ tb_size_t n = 100000;
tb_hong_t t = tb_mclock();
while (n--)
{
tb_size_t i = tb_random_value();
tb_hash_map_test_insert_i2t(hash, i);
tb_hash_map_test_get_i2t(hash, i);
}
t = tb_mclock() - t;
tb_trace_i("i2t: time: %lld", t);
// exit hash
tb_hash_map_exit(hash);
}
static tb_bool_t tb_hash_map_test_walk_item(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// done
tb_bool_t ok = tb_false;
tb_hize_t* test = (tb_hize_t*)value;
tb_hash_map_item_ref_t hash_item = (tb_hash_map_item_ref_t)item;
if (hash_item)
{
if (!(((tb_size_t)hash_item->data >> 25) & 0x1)) ok = tb_true;
else
{
test[0] += (tb_size_t)hash_item->name;
test[1] += (tb_size_t)hash_item->data;
test[2]++;
}
}
// ok?
return ok;
}
static tb_void_t tb_hash_map_test_walk_perf()
{
// init hash
tb_hash_map_ref_t hash = tb_hash_map_init(0, tb_element_long(), tb_element_long());
tb_assert_and_check_return(hash);
// reset random
tb_random_reset(tb_true);
// add items
__tb_volatile__ tb_size_t n = 100000;
while (n--)
{
tb_size_t i = tb_random_value();
tb_hash_map_test_insert_i2i(hash, i);
tb_hash_map_test_get_i2i(hash, i);
}
// done
tb_hong_t t = tb_mclock();
__tb_volatile__ tb_hize_t test[3] = {0};
tb_remove_if(hash, tb_hash_map_test_walk_item, (tb_cpointer_t)test);
t = tb_mclock() - t;
tb_trace_i("name: %llx, data: %llx, size: %llu ?= %u, time: %lld", test[0], test[1], test[2], tb_hash_map_size(hash), t);
// exit
tb_hash_map_exit(hash);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_hash_map_main(tb_int_t argc, tb_char_t** argv)
{
#if 1
tb_hash_map_test_s2i_func();
tb_hash_map_test_i2s_func();
tb_hash_map_test_m2m_func();
tb_hash_map_test_i2i_func();
tb_hash_map_test_i2t_func();
#endif
#if 1
tb_hash_map_test_s2i_perf();
tb_hash_map_test_i2s_perf();
tb_hash_map_test_m2m_perf();
tb_hash_map_test_i2i_perf();
tb_hash_map_test_i2t_perf();
#endif
#if 1
tb_hash_map_test_walk_perf();
#endif
return 0;
}
tbox-1.6.7/src/demo/container/hash_set.c 0000664 0000000 0000000 00000001641 14142237372 0020147 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_hash_set_main(tb_int_t argc, tb_char_t** argv)
{
// init hash
tb_hash_set_ref_t hash = tb_hash_set_init(8, tb_element_str(tb_true));
if (hash)
{
tb_hash_set_insert(hash, "1");
tb_hash_set_insert(hash, "9");
tb_hash_set_insert(hash, "4");
tb_hash_set_insert(hash, "6");
tb_hash_set_insert(hash, "8");
tb_hash_set_insert(hash, "2");
tb_hash_set_insert(hash, "3");
tb_hash_set_insert(hash, "5");
tb_hash_set_insert(hash, "7");
tb_for_all_if (tb_char_t const*, s, hash, s)
{
tb_trace_i("%s", s);
}
tb_hash_set_exit(hash);
}
return 0;
}
tbox-1.6.7/src/demo/container/heap.c 0000664 0000000 0000000 00000013002 14142237372 0017260 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_long_t tb_test_heap_max_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
return ((tb_p2u32(ldata) > tb_p2u32(rdata))? -1 : (tb_p2u32(ldata) < tb_p2u32(rdata)));
}
static tb_void_t tb_test_heap_min_func()
{
// init heap
tb_heap_ref_t heap = tb_heap_init(16, tb_element_uint32());
tb_assert_and_check_return(heap);
// reset rand
tb_random_reset(tb_true);
// make heap
tb_size_t i = 0;
for (i = 0; i < 100; i++)
{
// the value
tb_uint32_t val = (tb_uint32_t)tb_random_range(0, 50);
// trace
// tb_trace_i("heap_min: put: %u", val);
// put it
tb_heap_put(heap, tb_u2p(val));
}
// reset rand
tb_random_reset(tb_true);
// remove some values
for (i = 0; i < 100; i++)
{
// the value
tb_uint32_t val = (tb_uint32_t)tb_random_range(0, 50);
// remove it?
if (!(i & 3))
{
tb_size_t itor = tb_find_all(heap, tb_u2p(val));
if (itor != tb_iterator_tail(heap)) tb_heap_remove(heap, itor);
}
}
// append heap
for (i = 0; i < 30; i++)
{
// the value
tb_uint32_t val = (tb_uint32_t)tb_random_range(0, 50);
// put it
tb_heap_put(heap, tb_u2p(val));
}
// trace
tb_trace_i("");
// dump heap
while (tb_heap_size(heap))
{
// put it
tb_uint32_t val = (tb_uint32_t)(tb_size_t)tb_heap_top(heap);
// trace
tb_trace_i("heap_min: pop: %u", val);
// pop it
tb_heap_pop(heap);
}
// exit heap
tb_heap_exit(heap);
}
static tb_void_t tb_test_heap_min_perf()
{
// init heap
tb_heap_ref_t heap = tb_heap_init(4096, tb_element_uint32());
tb_assert_and_check_return(heap);
// reset rand
tb_random_reset(tb_true);
// init time
tb_hong_t time = tb_mclock();
// profile
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_size_t p; tb_used(&p);
for (i = 0; i < n; i++) tb_heap_put(heap, (tb_pointer_t)(tb_size_t)tb_random_range(0, 50));
for (i = 0; tb_heap_size(heap); i++)
{
// get the top value
tb_size_t v = (tb_size_t)tb_heap_top(heap);
// check order
tb_assert(!i || p <= v);
// save the previous value
p = v;
// pop it
tb_heap_pop(heap);
}
// exit time
time = tb_mclock() - time;
// trace
tb_trace_i("heap_min: %lld ms", time);
// exit heap
tb_heap_exit(heap);
}
static tb_void_t tb_test_heap_max_func()
{
// init element
tb_element_t element = tb_element_uint32(); element.comp = tb_test_heap_max_comp;
// init heap
tb_heap_ref_t heap = tb_heap_init(16, element);
tb_assert_and_check_return(heap);
// reset rand
tb_random_reset(tb_true);
// make heap
tb_size_t i = 0;
for (i = 0; i < 100; i++)
{
// the value
tb_uint32_t val = (tb_uint32_t)tb_random_range(0, 50);
// trace
// tb_trace_i("heap_max: put: %u", val);
// put it
tb_heap_put(heap, tb_u2p(val));
}
// remove some values
for (i = 0; i < 100; i++)
{
// the value
tb_uint32_t val = (tb_uint32_t)tb_random_range(0, 50);
// remove it?
if (!(i & 3))
{
tb_size_t itor = tb_find_all(heap, tb_u2p(val));
if (itor != tb_iterator_tail(heap)) tb_heap_remove(heap, itor);
}
}
// append heap
for (i = 0; i < 30; i++)
{
// the value
tb_uint32_t val = (tb_uint32_t)tb_random_range(0, 50);
// put it
tb_heap_put(heap, tb_u2p(val));
}
// trace
tb_trace_i("");
// dump heap
while (tb_heap_size(heap))
{
// put it
tb_uint32_t val = (tb_uint32_t)(tb_size_t)tb_heap_top(heap);
// trace
tb_trace_i("heap_max: pop: %u", val);
// pop it
tb_heap_pop(heap);
}
// exit heap
tb_heap_exit(heap);
}
static tb_void_t tb_test_heap_max_perf()
{
// init element
tb_element_t element = tb_element_uint32(); element.comp = tb_test_heap_max_comp;
// init heap
tb_heap_ref_t heap = tb_heap_init(4096, element);
tb_assert_and_check_return(heap);
// init time
tb_hong_t time = tb_mclock();
// profile
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_size_t p; tb_used(&p);
for (i = 0; i < n; i++) tb_heap_put(heap, (tb_pointer_t)(tb_size_t)tb_random_range(0, 50));
for (i = 0; tb_heap_size(heap); i++)
{
// get the top value
tb_size_t v = (tb_size_t)tb_heap_top(heap);
// check order
tb_assert(!i || p >= v);
// save the previous value
p = v;
// pop it
tb_heap_pop(heap);
}
// exit time
time = tb_mclock() - time;
// trace
tb_trace_i("heap_max: %lld ms", time);
// exit heap
tb_heap_exit(heap);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_heap_main(tb_int_t argc, tb_char_t** argv)
{
// element
tb_test_heap_min_func();
tb_test_heap_max_func();
// performance
tb_test_heap_min_perf();
tb_test_heap_max_perf();
return 0;
}
tbox-1.6.7/src/demo/container/list.c 0000664 0000000 0000000 00000062376 14142237372 0017340 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_list_insert_prev_test()
{
// init list
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
tb_size_t itor = tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_insert_prev(list, itor, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_insert_prev(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n + 1);
tb_assert(tb_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_list_clear(list);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_insert_next_test()
{
// init list
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
tb_size_t itor = tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_insert_next(list, itor, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_insert_next(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n + 1);
tb_assert(tb_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_list_clear(list);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_insert_head_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_insert_head(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n);
tb_assert(tb_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_list_clear(list);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_insert_tail_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_insert_tail(list, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_insert_tail(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n);
tb_assert(tb_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_list_clear(list);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_remove_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_size_t itor = tb_iterator_head(list);
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) itor = tb_list_remove(list, itor);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_remove(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(!tb_list_size(list));
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_remove_head_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_remove_head(list);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_remove_head(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(!tb_list_size(list));
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_remove_last_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_remove_last(list);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_remove_last(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(!tb_list_size(list));
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_replace_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_size_t itor = tb_iterator_head(list);
tb_size_t tail = tb_iterator_tail(list);
tb_hong_t t = tb_mclock();
for (; itor != tail; itor = tb_iterator_next(list, itor)) tb_list_replace(list, itor, (tb_pointer_t)0xe);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_replace(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n);
tb_assert(tb_list_head(list) == (tb_pointer_t)0xe);
tb_assert(tb_list_last(list) == (tb_pointer_t)0xe);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_replace_head_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_replace_head(list, (tb_pointer_t)0xe);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_replace_head(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n);
tb_assert(tb_list_head(list) == (tb_pointer_t)0xe);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_replace_last_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_list_replace_last(list, (tb_pointer_t)0xe);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_replace_last(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// check
tb_assert(tb_list_size(list) == n);
tb_assert(tb_list_last(list) == (tb_pointer_t)0xe);
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_iterator_next_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_size());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
tb_for_all(tb_size_t, item, list) tb_used(item);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_iterator_next(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_iterator_prev_test()
{
// init
tb_list_ref_t list = tb_list_init(0, tb_element_size());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
tb_rfor_all(tb_size_t, item, list) tb_used(item);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_list_iterator_prev(%d): %lld ms, size: %d, maxn: %d", n, t, tb_list_size(list), tb_list_maxn(list));
// exit
tb_list_exit(list);
}
static tb_void_t tb_list_int_dump(tb_list_ref_t list)
{
// trace
tb_trace_i("tb_int_t size: %d, maxn: %d", tb_list_size(list), tb_list_maxn(list));
// done
tb_for_all(tb_char_t*, item, list)
{
// trace
tb_trace_i("tb_int_t at[%lx]: %x", item_itor, item);
}
}
static tb_void_t tb_list_int_test()
{
// done
tb_list_ref_t list = tb_null;
tb_size_t i;
tb_size_t j;
do
{
// init list
list = tb_list_init(0, tb_element_long());
tb_assert_and_check_break(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("insert:");
// insert head
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
tb_list_insert_head(list, (tb_pointer_t)0xa);
// insert tail
i = tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
tb_list_insert_tail(list, (tb_pointer_t)0xf);
// insert prev
j = tb_list_insert_prev(list, i, (tb_pointer_t)0);
tb_list_insert_prev(list, i, (tb_pointer_t)1);
tb_list_insert_prev(list, i, (tb_pointer_t)2);
tb_list_insert_prev(list, i, (tb_pointer_t)3);
tb_list_insert_prev(list, i, (tb_pointer_t)4);
tb_list_insert_prev(list, i, (tb_pointer_t)5);
tb_list_insert_prev(list, i, (tb_pointer_t)6);
tb_list_insert_prev(list, i, (tb_pointer_t)7);
tb_list_insert_prev(list, i, (tb_pointer_t)8);
tb_list_insert_prev(list, i, (tb_pointer_t)9);
// insert head
tb_list_insert_head(list, (tb_pointer_t)4);
tb_list_insert_head(list, (tb_pointer_t)3);
tb_list_insert_head(list, (tb_pointer_t)2);
tb_list_insert_head(list, (tb_pointer_t)1);
tb_list_insert_head(list, (tb_pointer_t)0);
// insert tail
tb_list_insert_tail(list, (tb_pointer_t)5);
tb_list_insert_tail(list, (tb_pointer_t)6);
tb_list_insert_tail(list, (tb_pointer_t)7);
tb_list_insert_tail(list, (tb_pointer_t)8);
tb_list_insert_tail(list, (tb_pointer_t)9);
// dump
tb_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("remove:");
// remove head
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
// remove last
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
// remove
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
// dump
tb_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("replace:");
// replace head
tb_list_replace_head(list, (tb_pointer_t)0);
// replace last
tb_list_replace_last(list, (tb_pointer_t)1);
// dump
tb_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("moveto:");
// move to head and tail
tb_list_moveto_head(list, tb_iterator_last(list));
tb_list_moveto_tail(list, tb_iterator_next(list, tb_iterator_head(list)));
// dump
tb_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("clear:");
// clear
tb_list_clear(list);
// dump
tb_list_int_dump(list);
} while (0);
// exit list
if (list) tb_list_exit(list);
}
static tb_void_t tb_list_str_dump(tb_list_ref_t list)
{
// trace
tb_trace_i("str size: %d, maxn: %d", tb_list_size(list), tb_list_maxn(list));
// done
tb_for_all (tb_char_t*, item, list)
{
// trace
tb_trace_i("str at[%lx]: %s", item_itor, item);
}
}
static tb_void_t tb_list_str_test()
{
// done
tb_list_ref_t list = tb_null;
tb_size_t i;
tb_size_t j;
do
{
// init list
list = tb_list_init(0, tb_element_str(tb_true));
tb_assert_and_check_break(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("insert:");
// insert head
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
// insert tail
i = tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
// insert prev
j = tb_list_insert_prev(list, i, "0000000000");
tb_list_insert_prev(list, i, "1111111111");
tb_list_insert_prev(list, i, "2222222222");
tb_list_insert_prev(list, i, "3333333333");
tb_list_insert_prev(list, i, "4444444444");
tb_list_insert_prev(list, i, "5555555555");
tb_list_insert_prev(list, i, "6666666666");
tb_list_insert_prev(list, i, "7777777777");
tb_list_insert_prev(list, i, "8888888888");
tb_list_insert_prev(list, i, "9999999999");
// insert head
tb_list_insert_head(list, "4444444444");
tb_list_insert_head(list, "3333333333");
tb_list_insert_head(list, "2222222222");
tb_list_insert_head(list, "1111111111");
tb_list_insert_head(list, "0000000000");
// insert tail
tb_list_insert_tail(list, "5555555555");
tb_list_insert_tail(list, "6666666666");
tb_list_insert_tail(list, "7777777777");
tb_list_insert_tail(list, "8888888888");
tb_list_insert_tail(list, "9999999999");
// dump
tb_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("remove:");
// remove head
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
// remove last
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
// remove
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
// dump
tb_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("replace:");
// replace head
tb_list_replace_head(list, "0000000000");
// replace last
tb_list_replace_last(list, "1111111111");
// dump
tb_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("moveto:");
// move to head and tail
tb_list_moveto_head(list, tb_iterator_last(list));
tb_list_moveto_tail(list, tb_iterator_next(list, tb_iterator_head(list)));
// dump
tb_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("clear:");
// clear
tb_list_clear(list);
// dump
tb_list_str_dump(list);
} while (0);
// exit list
if (list) tb_list_exit(list);
}
static tb_void_t tb_list_mem_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_trace_i("ifm free: %s, priv: %s", buff, element->priv);
}
static tb_void_t tb_list_mem_dump(tb_list_ref_t list)
{
// trace
tb_trace_i("ifm size: %d, maxn: %d", tb_list_size(list), tb_list_maxn(list));
// done
tb_for_all (tb_char_t*, item, list)
{
// trace
tb_trace_i("ifm at[%lx]: %s", item_itor, item);
}
}
static tb_void_t tb_list_mem_test()
{
// done
tb_list_ref_t list = tb_null;
tb_size_t i;
tb_size_t j;
do
{
// init list
list = tb_list_init(0, tb_element_mem(11, tb_list_mem_free, "mem"));
tb_assert_and_check_break(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("insert:");
// insert head
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
tb_list_insert_head(list, "AAAAAAAAAA");
// insert tail
i = tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
tb_list_insert_tail(list, "FFFFFFFFFF");
// insert prev
j = tb_list_insert_prev(list, i, "0000000000");
tb_list_insert_prev(list, i, "1111111111");
tb_list_insert_prev(list, i, "2222222222");
tb_list_insert_prev(list, i, "3333333333");
tb_list_insert_prev(list, i, "4444444444");
tb_list_insert_prev(list, i, "5555555555");
tb_list_insert_prev(list, i, "6666666666");
tb_list_insert_prev(list, i, "7777777777");
tb_list_insert_prev(list, i, "8888888888");
tb_list_insert_prev(list, i, "9999999999");
// insert head
tb_list_insert_head(list, "4444444444");
tb_list_insert_head(list, "3333333333");
tb_list_insert_head(list, "2222222222");
tb_list_insert_head(list, "1111111111");
tb_list_insert_head(list, "0000000000");
// insert tail
tb_list_insert_tail(list, "5555555555");
tb_list_insert_tail(list, "6666666666");
tb_list_insert_tail(list, "7777777777");
tb_list_insert_tail(list, "8888888888");
tb_list_insert_tail(list, "9999999999");
// dump
tb_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("remove:");
// remove head
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
tb_list_remove_head(list);
// remove last
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
tb_list_remove_last(list);
// remove
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
j = tb_list_remove(list, j);
// dump
tb_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("replace:");
// replace head
tb_list_replace_head(list, "0000000000");
// replace last
tb_list_replace_last(list, "1111111111");
// dump
tb_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("moveto:");
// move to head and tail
tb_list_moveto_head(list, tb_iterator_last(list));
tb_list_moveto_tail(list, tb_iterator_next(list, tb_iterator_head(list)));
// dump
tb_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("clear:");
// clear
tb_list_clear(list);
// dump
tb_list_mem_dump(list);
} while (0);
// exit list
if (list) tb_list_exit(list);
}
static tb_void_t tb_list_perf_test()
{
// insert
tb_list_insert_prev_test();
tb_list_insert_next_test();
tb_list_insert_head_test();
tb_list_insert_tail_test();
// remove
tb_list_remove_test();
tb_list_remove_head_test();
tb_list_remove_last_test();
// replace
tb_list_replace_test();
tb_list_replace_head_test();
tb_list_replace_last_test();
// iterator
tb_list_iterator_next_test();
tb_list_iterator_prev_test();
}
static tb_bool_t tb_list_test_walk_item(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// done
tb_hize_t* test = (tb_hize_t*)value;
tb_size_t i = (tb_size_t)item;
tb_bool_t ok = tb_false;
if (!((i >> 25) & 0x1)) ok = tb_true;
else
{
test[0] += i;
test[1]++;
}
// ok?
return ok;
}
static tb_void_t tb_list_walk_perf()
{
// init list
tb_list_ref_t list = tb_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t n = 100000;
while (n--) tb_list_insert_tail(list, (tb_pointer_t)(tb_size_t)tb_random_value());
// done
tb_hong_t t = tb_mclock();
__tb_volatile__ tb_hize_t test[2] = {0};
tb_remove_if(list, tb_list_test_walk_item, (tb_pointer_t)test);
t = tb_mclock() - t;
// trace
tb_trace_i("item: %llx, size: %llu ?= %u, time: %lld", test[0], test[1], tb_list_size(list), t);
// exit list
tb_list_exit(list);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_list_main(tb_int_t argc, tb_char_t** argv)
{
tb_list_int_test();
tb_list_str_test();
tb_list_mem_test();
#if 1
tb_list_perf_test();
#endif
#if 1
tb_list_walk_perf();
#endif
return 0;
}
tbox-1.6.7/src/demo/container/list_entry.c 0000664 0000000 0000000 00000007346 14142237372 0020555 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the demo entry type
typedef struct __tb_demo_entry_t
{
// the list entry
tb_list_entry_t entry;
// the data
tb_size_t data;
}tb_demo_entry_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* comparer
*/
static tb_void_t tb_demo_entry_copy(tb_pointer_t litem, tb_pointer_t ritem)
{
// check
tb_assert(litem && ritem);
// copy it
((tb_demo_entry_t*)litem)->data = ((tb_demo_entry_t*)ritem)->data;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_list_entry_main(tb_int_t argc, tb_char_t** argv)
{
// init the entries
tb_demo_entry_t entries[12] =
{
{{0}, 0}
, {{0}, 1}
, {{0}, 2}
, {{0}, 3}
, {{0}, 4}
, {{0}, 5}
, {{0}, 6}
, {{0}, 7}
, {{0}, 8}
, {{0}, 9}
, {{0}, 10}
, {{0}, 11}
};
// init the list
tb_list_entry_head_t list;
tb_list_entry_init(&list, tb_demo_entry_t, entry, tb_demo_entry_copy);
// insert entries
tb_list_entry_insert_tail(&list, &entries[5].entry);
tb_list_entry_insert_tail(&list, &entries[6].entry);
tb_list_entry_insert_tail(&list, &entries[7].entry);
tb_list_entry_insert_tail(&list, &entries[8].entry);
tb_list_entry_insert_tail(&list, &entries[9].entry);
tb_list_entry_insert_head(&list, &entries[4].entry);
tb_list_entry_insert_head(&list, &entries[3].entry);
tb_list_entry_insert_head(&list, &entries[2].entry);
tb_list_entry_insert_head(&list, &entries[1].entry);
tb_list_entry_insert_head(&list, &entries[0].entry);
// the entry
tb_demo_entry_t* entry = (tb_demo_entry_t*)tb_list_entry(&list, &entries[5].entry);
tb_trace_i("entry: %lu", entry->data);
tb_trace_i("");
// walk it
tb_trace_i("insert: %lu", tb_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item0, tb_list_entry_itor(&list), item0)
{
tb_trace_i("%lu", item0->data);
}
// trace
tb_trace_i("");
// replace entries
tb_list_entry_replace_head(&list, &entries[10].entry);
tb_list_entry_replace_last(&list, &entries[11].entry);
// walk it
tb_trace_i("replace: %lu", tb_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item1, tb_list_entry_itor(&list), item1)
{
tb_trace_i("%lu", item1->data);
}
// trace
tb_trace_i("");
// remove entries
tb_list_entry_remove_head(&list);
tb_list_entry_remove_last(&list);
// walk it
tb_trace_i("remove: %lu", tb_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item2, tb_list_entry_itor(&list), item2)
{
tb_trace_i("%lu", item2->data);
}
// trace
tb_trace_i("");
// moveto entries
tb_list_entry_ref_t head = tb_list_entry_head(&list);
tb_list_entry_moveto_head(&list, tb_list_entry_last(&list));
tb_list_entry_moveto_tail(&list, head);
// walk it
tb_trace_i("moveto: %lu", tb_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item3, tb_list_entry_itor(&list), item3)
{
tb_trace_i("%lu", item3->data);
}
// trace
tb_trace_i("");
// clear entries
tb_list_entry_clear(&list);
// walk it
tb_trace_i("clear: %lu", tb_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item5, tb_list_entry_itor(&list), item5)
{
tb_trace_i("%lu", item5->data);
}
// exit the list
tb_list_entry_exit(&list);
// trace
tb_trace_i("");
return 0;
}
tbox-1.6.7/src/demo/container/queue.c 0000664 0000000 0000000 00000017331 14142237372 0017500 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_queue_put_and_pop_test()
{
// init
tb_queue_ref_t queue = tb_queue_init(10, tb_element_long());
tb_assert_and_check_return(queue);
// make queue
tb_queue_put(queue, (tb_pointer_t)0);
tb_queue_put(queue, (tb_pointer_t)1);
tb_queue_put(queue, (tb_pointer_t)2);
tb_queue_put(queue, (tb_pointer_t)3);
tb_queue_put(queue, (tb_pointer_t)4);
tb_queue_put(queue, (tb_pointer_t)5);
tb_queue_put(queue, (tb_pointer_t)6);
tb_queue_put(queue, (tb_pointer_t)7);
tb_queue_put(queue, (tb_pointer_t)8);
tb_queue_put(queue, (tb_pointer_t)9);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++)
{
tb_queue_pop(queue);
tb_queue_put(queue, (tb_pointer_t)0xf);
}
t = tb_mclock() - t;
// trace
tb_trace_i("tb_queue_put_and_pop(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_queue_size(queue), tb_queue_maxn(queue));
// check
tb_assert(tb_queue_size(queue) == 10);
tb_assert(tb_queue_head(queue) == (tb_pointer_t)0xf);
tb_assert(tb_queue_last(queue) == (tb_pointer_t)0xf);
// clear it
tb_queue_clear(queue);
tb_assert(!tb_queue_size(queue));
// exit
tb_queue_exit(queue);
}
static tb_void_t tb_queue_iterator_next_test()
{
// init
tb_queue_ref_t queue = tb_queue_init(0, tb_element_long());
tb_assert_and_check_return(queue);
// make queue
tb_size_t n = 1000000;
while (n--) tb_queue_put(queue, (tb_pointer_t)0xf);
// done
tb_hong_t t = tb_mclock();
tb_for_all (tb_char_t*, item, queue) tb_used(item);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_queue_iterator_next(%lu): %lld ms, size: %lu, maxn: %lu", 1000000, t, tb_queue_size(queue), tb_queue_maxn(queue));
// exit
tb_queue_exit(queue);
}
static tb_void_t tb_queue_int_dump(tb_queue_ref_t queue)
{
tb_trace_i("tb_int_t size: %lu, maxn: %lu", tb_queue_size(queue), tb_queue_maxn(queue));
tb_for_all (tb_char_t*, item, queue)
{
tb_trace_i("tb_int_t at[%lu]: %u", item_itor, item);
}
}
static tb_void_t tb_queue_int_test()
{
tb_queue_ref_t queue = tb_queue_init(10, tb_element_long());
tb_assert_and_check_return(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_queue_put(queue, (tb_pointer_t)0);
tb_queue_put(queue, (tb_pointer_t)1);
tb_queue_put(queue, (tb_pointer_t)2);
tb_queue_put(queue, (tb_pointer_t)3);
tb_queue_put(queue, (tb_pointer_t)4);
tb_queue_put(queue, (tb_pointer_t)5);
tb_queue_put(queue, (tb_pointer_t)6);
tb_queue_put(queue, (tb_pointer_t)7);
tb_queue_put(queue, (tb_pointer_t)8);
tb_queue_put(queue, (tb_pointer_t)9);
tb_queue_int_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("pop:");
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_int_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_queue_put(queue, (tb_pointer_t)0);
tb_queue_put(queue, (tb_pointer_t)1);
tb_queue_put(queue, (tb_pointer_t)2);
tb_queue_put(queue, (tb_pointer_t)3);
tb_queue_put(queue, (tb_pointer_t)4);
tb_queue_int_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_queue_clear(queue);
tb_queue_int_dump(queue);
tb_queue_exit(queue);
}
static tb_void_t tb_queue_str_dump(tb_queue_ref_t queue)
{
tb_trace_i("str size: %lu, maxn: %lu", tb_queue_size(queue), tb_queue_maxn(queue));
tb_for_all (tb_char_t*, item, queue)
{
tb_trace_i("str at[%lu]: %s", item_itor, item);
}
}
static tb_void_t tb_queue_str_test()
{
tb_queue_ref_t queue = tb_queue_init(10, tb_element_str(tb_true));
tb_assert_and_check_return(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_queue_put(queue, "0000000000");
tb_queue_put(queue, "1111111111");
tb_queue_put(queue, "2222222222");
tb_queue_put(queue, "3333333333");
tb_queue_put(queue, "4444444444");
tb_queue_put(queue, "5555555555");
tb_queue_put(queue, "6666666666");
tb_queue_put(queue, "7777777777");
tb_queue_put(queue, "8888888888");
tb_queue_put(queue, "9999999999");
tb_queue_str_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("pop:");
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_str_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_queue_put(queue, "0000000000");
tb_queue_put(queue, "1111111111");
tb_queue_put(queue, "2222222222");
tb_queue_put(queue, "3333333333");
tb_queue_put(queue, "4444444444");
tb_queue_str_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_queue_clear(queue);
tb_queue_str_dump(queue);
tb_queue_exit(queue);
}
static tb_void_t tb_queue_mem_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_trace_i("ifm free: %s, priv: %s", buff, element->priv);
}
static tb_void_t tb_queue_mem_dump(tb_queue_ref_t queue)
{
tb_trace_i("ifm size: %lu, maxn: %lu", tb_queue_size(queue), tb_queue_maxn(queue));
tb_for_all (tb_char_t*, item, queue)
{
tb_trace_i("ifm at[%lu]: %s", item_itor, item);
}
}
static tb_void_t tb_queue_mem_test()
{
tb_queue_ref_t queue = tb_queue_init(10, tb_element_mem(11, tb_queue_mem_free, "ifm"));
tb_assert_and_check_return(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_queue_put(queue, "0000000000");
tb_queue_put(queue, "1111111111");
tb_queue_put(queue, "2222222222");
tb_queue_put(queue, "3333333333");
tb_queue_put(queue, "4444444444");
tb_queue_put(queue, "5555555555");
tb_queue_put(queue, "6666666666");
tb_queue_put(queue, "7777777777");
tb_queue_put(queue, "8888888888");
tb_queue_put(queue, "9999999999");
tb_queue_mem_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("pop:");
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_pop(queue);
tb_queue_mem_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("put:");
tb_queue_put(queue, "0000000000");
tb_queue_put(queue, "1111111111");
tb_queue_put(queue, "2222222222");
tb_queue_put(queue, "3333333333");
tb_queue_put(queue, "4444444444");
tb_queue_mem_dump(queue);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_queue_clear(queue);
tb_queue_mem_dump(queue);
tb_queue_exit(queue);
}
static tb_void_t tb_queue_perf_test()
{
tb_queue_put_and_pop_test();
tb_queue_iterator_next_test();
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_queue_main(tb_int_t argc, tb_char_t** argv)
{
tb_queue_int_test();
tb_queue_str_test();
tb_queue_mem_test();
tb_queue_perf_test();
return 0;
}
tbox-1.6.7/src/demo/container/single_list.c 0000664 0000000 0000000 00000055444 14142237372 0020677 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_single_list_insert_next_test()
{
// init list
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
tb_size_t itor = tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_single_list_insert_next(list, itor, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_insert_next(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(tb_single_list_size(list) == n + 1);
tb_assert(tb_single_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_single_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_single_list_clear(list);
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_insert_head_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_insert_head(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(tb_single_list_size(list) == n);
tb_assert(tb_single_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_single_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_single_list_clear(list);
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_insert_tail_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// done
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_single_list_insert_tail(list, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_insert_tail(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(tb_single_list_size(list) == n);
tb_assert(tb_single_list_head(list) == (tb_pointer_t)0xd);
tb_assert(tb_single_list_last(list) == (tb_pointer_t)0xd);
// clear it
tb_single_list_clear(list);
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_remove_next_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_size_t itor = tb_iterator_head(list);
tb_hong_t t = tb_mclock();
for (i = 0, n--; i < n; i++) tb_single_list_remove_next(list, itor);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_remove(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(1 == tb_single_list_size(list));
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_remove_head_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_single_list_remove_head(list);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_remove_head(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(!tb_single_list_size(list));
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_replace_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_size_t itor = tb_iterator_head(list);
tb_size_t tail = tb_iterator_tail(list);
tb_hong_t t = tb_mclock();
for (; itor != tail; itor = tb_iterator_next(list, itor)) tb_single_list_replace(list, itor, (tb_pointer_t)0xe);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_replace(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(tb_single_list_size(list) == n);
tb_assert(tb_single_list_head(list) == (tb_pointer_t)0xe);
tb_assert(tb_single_list_last(list) == (tb_pointer_t)0xe);
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_replace_head_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_single_list_replace_head(list, (tb_pointer_t)0xe);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_replace_head(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(tb_single_list_size(list) == n);
tb_assert(tb_single_list_head(list) == (tb_pointer_t)0xe);
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_replace_last_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_single_list_replace_last(list, (tb_pointer_t)0xe);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_replace_last(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// check
tb_assert(tb_single_list_size(list) == n);
tb_assert(tb_single_list_last(list) == (tb_pointer_t)0xe);
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_iterator_next_test()
{
// init
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_size());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 1000000;
for (i = 0; i < n; i++) tb_single_list_insert_head(list, (tb_pointer_t)0xd);
// done
tb_hong_t t = tb_mclock();
tb_for_all(tb_size_t, item, list) tb_used(item);
t = tb_mclock() - t;
// trace
tb_trace_i("tb_single_list_iterator_next(%d): %lld ms, size: %d, maxn: %d", n, t, tb_single_list_size(list), tb_single_list_maxn(list));
// exit
tb_single_list_exit(list);
}
static tb_void_t tb_single_list_int_dump(tb_single_list_ref_t list)
{
// trace
tb_trace_i("tb_int_t size: %d, maxn: %d", tb_single_list_size(list), tb_single_list_maxn(list));
// done
tb_for_all(tb_char_t*, item, list)
{
// trace
tb_trace_i("tb_int_t at[%lx]: %x", item_itor, item);
}
}
static tb_void_t tb_single_list_int_test()
{
// done
tb_single_list_ref_t list = tb_null;
tb_size_t i;
do
{
// init list
list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_break(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("insert:");
// insert head
i = tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
tb_single_list_insert_head(list, (tb_pointer_t)0xa);
// insert tail
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
tb_single_list_insert_tail(list, (tb_pointer_t)0xf);
// insert next
tb_single_list_insert_next(list, i, (tb_pointer_t)0);
tb_single_list_insert_next(list, i, (tb_pointer_t)1);
tb_single_list_insert_next(list, i, (tb_pointer_t)2);
tb_single_list_insert_next(list, i, (tb_pointer_t)3);
tb_single_list_insert_next(list, i, (tb_pointer_t)4);
tb_single_list_insert_next(list, i, (tb_pointer_t)5);
tb_single_list_insert_next(list, i, (tb_pointer_t)6);
tb_single_list_insert_next(list, i, (tb_pointer_t)7);
tb_single_list_insert_next(list, i, (tb_pointer_t)8);
tb_single_list_insert_next(list, i, (tb_pointer_t)9);
// insert head
tb_single_list_insert_head(list, (tb_pointer_t)4);
tb_single_list_insert_head(list, (tb_pointer_t)3);
tb_single_list_insert_head(list, (tb_pointer_t)2);
tb_single_list_insert_head(list, (tb_pointer_t)1);
tb_single_list_insert_head(list, (tb_pointer_t)0);
// dump
tb_single_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("remove:");
// remove head
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
// remove
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
// dump
tb_single_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("replace:");
// replace head
tb_single_list_replace_head(list, (tb_pointer_t)0);
// replace last
tb_single_list_replace_last(list, (tb_pointer_t)1);
// dump
tb_single_list_int_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("clear:");
// clear
tb_single_list_clear(list);
// dump
tb_single_list_int_dump(list);
} while (0);
// exit list
if (list) tb_single_list_exit(list);
}
static tb_void_t tb_single_list_str_dump(tb_single_list_ref_t list)
{
// trace
tb_trace_i("str size: %d, maxn: %d", tb_single_list_size(list), tb_single_list_maxn(list));
// done
tb_for_all (tb_char_t*, item, list)
{
// trace
tb_trace_i("str at[%lx]: %s", item_itor, item);
}
}
static tb_void_t tb_single_list_str_test()
{
// done
tb_single_list_ref_t list = tb_null;
tb_size_t i;
do
{
// init list
list = tb_single_list_init(0, tb_element_str(tb_true));
tb_assert_and_check_break(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("insert:");
// insert head
i = tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
// insert tail
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
// insert next
tb_single_list_insert_next(list, i, "0000000000");
tb_single_list_insert_next(list, i, "1111111111");
tb_single_list_insert_next(list, i, "2222222222");
tb_single_list_insert_next(list, i, "3333333333");
tb_single_list_insert_next(list, i, "4444444444");
tb_single_list_insert_next(list, i, "5555555555");
tb_single_list_insert_next(list, i, "6666666666");
tb_single_list_insert_next(list, i, "7777777777");
tb_single_list_insert_next(list, i, "8888888888");
tb_single_list_insert_next(list, i, "9999999999");
// insert head
tb_single_list_insert_head(list, "4444444444");
tb_single_list_insert_head(list, "3333333333");
tb_single_list_insert_head(list, "2222222222");
tb_single_list_insert_head(list, "1111111111");
tb_single_list_insert_head(list, "0000000000");
// dump
tb_single_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("remove:");
// remove head
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
// remove
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
// dump
tb_single_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("replace:");
// replace head
tb_single_list_replace_head(list, "0000000000");
// replace last
tb_single_list_replace_last(list, "1111111111");
// dump
tb_single_list_str_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("clear:");
// clear
tb_single_list_clear(list);
// dump
tb_single_list_str_dump(list);
} while (0);
// exit list
if (list) tb_single_list_exit(list);
}
static tb_void_t tb_single_list_mem_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_trace_i("ifm free: %s, priv: %s", buff, element->priv);
}
static tb_void_t tb_single_list_mem_dump(tb_single_list_ref_t list)
{
// trace
tb_trace_i("ifm size: %d, maxn: %d", tb_single_list_size(list), tb_single_list_maxn(list));
// done
tb_for_all (tb_char_t*, item, list)
{
// trace
tb_trace_i("ifm at[%lx]: %s", item_itor, item);
}
}
static tb_void_t tb_single_list_mem_test()
{
// done
tb_single_list_ref_t list = tb_null;
tb_size_t i;
do
{
// init list
list = tb_single_list_init(0, tb_element_mem(11, tb_single_list_mem_free, "mem"));
tb_assert_and_check_break(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("insert:");
// insert head
i = tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
tb_single_list_insert_head(list, "AAAAAAAAAA");
// insert tail
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
tb_single_list_insert_tail(list, "FFFFFFFFFF");
// insert next
tb_single_list_insert_next(list, i, "0000000000");
tb_single_list_insert_next(list, i, "1111111111");
tb_single_list_insert_next(list, i, "2222222222");
tb_single_list_insert_next(list, i, "3333333333");
tb_single_list_insert_next(list, i, "4444444444");
tb_single_list_insert_next(list, i, "5555555555");
tb_single_list_insert_next(list, i, "6666666666");
tb_single_list_insert_next(list, i, "7777777777");
tb_single_list_insert_next(list, i, "8888888888");
tb_single_list_insert_next(list, i, "9999999999");
// insert head
tb_single_list_insert_head(list, "4444444444");
tb_single_list_insert_head(list, "3333333333");
tb_single_list_insert_head(list, "2222222222");
tb_single_list_insert_head(list, "1111111111");
tb_single_list_insert_head(list, "0000000000");
// dump
tb_single_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("remove:");
// remove head
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
tb_single_list_remove_head(list);
// remove
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
tb_single_list_remove_next(list, i);
// dump
tb_single_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("replace:");
// replace head
tb_single_list_replace_head(list, "0000000000");
// replace last
tb_single_list_replace_last(list, "1111111111");
// dump
tb_single_list_mem_dump(list);
// trace
tb_trace_i("=============================================================");
tb_trace_i("clear:");
// clear
tb_single_list_clear(list);
// dump
tb_single_list_mem_dump(list);
} while (0);
// exit list
if (list) tb_single_list_exit(list);
}
static tb_void_t tb_single_list_perf_test()
{
// insert
tb_single_list_insert_next_test();
tb_single_list_insert_head_test();
tb_single_list_insert_tail_test();
// remove
tb_single_list_remove_next_test();
tb_single_list_remove_head_test();
// replace
tb_single_list_replace_test();
tb_single_list_replace_head_test();
tb_single_list_replace_last_test();
// iterator
tb_single_list_iterator_next_test();
}
static tb_bool_t tb_single_list_test_walk_item(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// done
tb_hize_t* test = (tb_hize_t*)value;
tb_size_t i = (tb_size_t)item;
tb_bool_t ok = tb_false;
if (!((i >> 25) & 0x1)) ok = tb_true;
else
{
test[0] += i;
test[1]++;
}
// ok?
return ok;
}
static tb_void_t tb_single_list_walk_perf()
{
// init list
tb_single_list_ref_t list = tb_single_list_init(0, tb_element_long());
tb_assert_and_check_return(list);
// make list
__tb_volatile__ tb_size_t n = 100000;
while (n--) tb_single_list_insert_tail(list, (tb_pointer_t)(tb_size_t)tb_random_value());
// done
tb_hong_t t = tb_mclock();
__tb_volatile__ tb_hize_t test[2] = {0};
tb_remove_if(list, tb_single_list_test_walk_item, (tb_pointer_t)test);
t = tb_mclock() - t;
// trace
tb_trace_i("item: %llx, size: %llu ?= %u, time: %lld", test[0], test[1], tb_single_list_size(list), t);
// exit list
tb_single_list_exit(list);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_single_list_main(tb_int_t argc, tb_char_t** argv)
{
tb_single_list_int_test();
tb_single_list_str_test();
tb_single_list_mem_test();
#if 1
tb_single_list_perf_test();
#endif
#if 1
tb_single_list_walk_perf();
#endif
return 0;
}
tbox-1.6.7/src/demo/container/single_list_entry.c 0000664 0000000 0000000 00000006637 14142237372 0022120 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the demo entry type
typedef struct __tb_demo_entry_t
{
// the list entry
tb_single_list_entry_t entry;
// the data
tb_size_t data;
}tb_demo_entry_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* comparer
*/
static tb_void_t tb_demo_entry_copy(tb_pointer_t litem, tb_pointer_t ritem)
{
// check
tb_assert(litem && ritem);
// copy it
((tb_demo_entry_t*)litem)->data = ((tb_demo_entry_t*)ritem)->data;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_single_list_entry_main(tb_int_t argc, tb_char_t** argv)
{
// init the entries
tb_demo_entry_t entries[12] =
{
{{0}, 0}
, {{0}, 1}
, {{0}, 2}
, {{0}, 3}
, {{0}, 4}
, {{0}, 5}
, {{0}, 6}
, {{0}, 7}
, {{0}, 8}
, {{0}, 9}
, {{0}, 10}
, {{0}, 11}
};
// init the list
tb_single_list_entry_head_t list;
tb_single_list_entry_init(&list, tb_demo_entry_t, entry, tb_demo_entry_copy);
// insert entries
tb_single_list_entry_insert_tail(&list, &entries[5].entry);
tb_single_list_entry_insert_tail(&list, &entries[6].entry);
tb_single_list_entry_insert_tail(&list, &entries[7].entry);
tb_single_list_entry_insert_tail(&list, &entries[8].entry);
tb_single_list_entry_insert_tail(&list, &entries[9].entry);
tb_single_list_entry_insert_head(&list, &entries[4].entry);
tb_single_list_entry_insert_head(&list, &entries[3].entry);
tb_single_list_entry_insert_head(&list, &entries[2].entry);
tb_single_list_entry_insert_head(&list, &entries[1].entry);
tb_single_list_entry_insert_head(&list, &entries[0].entry);
// the entry
tb_demo_entry_t* entry = (tb_demo_entry_t*)tb_single_list_entry(&list, &entries[5].entry);
tb_trace_i("entry: %lu", entry->data);
tb_trace_i("");
// walk it
tb_trace_i("insert: %lu", tb_single_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item0, tb_single_list_entry_itor(&list), item0)
{
tb_trace_i("%lu", item0->data);
}
// trace
tb_trace_i("");
// replace entries
tb_single_list_entry_replace_head(&list, &entries[10].entry);
// walk it
tb_trace_i("replace: %lu", tb_single_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item1, tb_single_list_entry_itor(&list), item1)
{
tb_trace_i("%lu", item1->data);
}
// trace
tb_trace_i("");
// remove entries
tb_single_list_entry_remove_head(&list);
// walk it
tb_trace_i("remove: %lu", tb_single_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item2, tb_single_list_entry_itor(&list), item2)
{
tb_trace_i("%lu", item2->data);
}
// trace
tb_trace_i("");
// clear entries
tb_single_list_entry_clear(&list);
// walk it
tb_trace_i("clear: %lu", tb_single_list_entry_size(&list));
tb_for_all_if(tb_demo_entry_t*, item5, tb_single_list_entry_itor(&list), item5)
{
tb_trace_i("%lu", item5->data);
}
// exit the list
tb_single_list_entry_exit(&list);
// trace
tb_trace_i("");
return 0;
}
tbox-1.6.7/src/demo/container/stack.c 0000664 0000000 0000000 00000007013 14142237372 0017455 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_stack_put_and_pop_test()
{
// init
tb_stack_ref_t stack = tb_stack_init(10, tb_element_long());
tb_assert_and_check_return_val(stack, 0);
tb_stack_put(stack, (tb_pointer_t)0);
tb_stack_put(stack, (tb_pointer_t)1);
tb_stack_put(stack, (tb_pointer_t)2);
tb_stack_put(stack, (tb_pointer_t)3);
tb_stack_put(stack, (tb_pointer_t)4);
tb_stack_put(stack, (tb_pointer_t)5);
tb_stack_put(stack, (tb_pointer_t)6);
tb_stack_put(stack, (tb_pointer_t)7);
tb_stack_put(stack, (tb_pointer_t)8);
tb_stack_put(stack, (tb_pointer_t)9);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++)
{
tb_stack_pop(stack);
tb_stack_put(stack, (tb_pointer_t)0xf);
}
t = tb_mclock() - t;
// time
tb_trace_i("tb_stack_put_and_pop(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_stack_size(stack), tb_stack_maxn(stack));
// check
tb_assert(tb_stack_size(stack) == 10);
tb_assert(tb_stack_head(stack) == (tb_pointer_t)0x0);
tb_assert(tb_stack_last(stack) == (tb_pointer_t)0xf);
// clear it
tb_stack_clear(stack);
tb_assert(!tb_stack_size(stack));
// exit
tb_stack_exit(stack);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_stack_iterator_next_test()
{
// init
tb_size_t n = 1000000;
tb_stack_ref_t stack = tb_stack_init(n, tb_element_long());
tb_assert_and_check_return_val(stack, 0);
tb_size_t i;
for (i = 0; i < n; i++) tb_stack_put(stack, (tb_pointer_t)0xf);
tb_hong_t t = tb_mclock();
tb_for_all (tb_char_t*, item, stack) tb_used(item);
t = tb_mclock() - t;
// time
tb_trace_i("tb_stack_iterator_next(%lu): %lld ms, size: %lu, maxn: %lu", 1000000, t, tb_stack_size(stack), tb_stack_maxn(stack));
// exit
tb_stack_exit(stack);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_stack_iterator_prev_test()
{
// init
tb_size_t n = 1000000;
tb_stack_ref_t stack = tb_stack_init(n, tb_element_long());
tb_assert_and_check_return_val(stack, 0);
tb_size_t i;
for (i = 0; i < n; i++) tb_stack_put(stack, (tb_pointer_t)0xf);
tb_hong_t t = tb_mclock();
tb_rfor_all (tb_char_t*, item, stack) tb_used(item);
t = tb_mclock() - t;
// time
tb_trace_i("tb_stack_iterator_prev(%lu): %lld ms, size: %lu, maxn: %lu", 1000000, t, tb_stack_size(stack), tb_stack_maxn(stack));
// exit
tb_stack_exit(stack);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_void_t tb_stack_perf_test()
{
tb_size_t score = 0;
tb_trace_i("=============================================================");
tb_trace_i("put & pop performance:");
score += tb_stack_put_and_pop_test();
tb_trace_i("=============================================================");
tb_trace_i("iterator performance:");
score += tb_stack_iterator_next_test();
score += tb_stack_iterator_prev_test();
tb_trace_i("=============================================================");
tb_trace_i("score: %lu", score / 100);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_stack_main(tb_int_t argc, tb_char_t** argv)
{
tb_stack_perf_test();
return 0;
}
tbox-1.6.7/src/demo/container/vector.c 0000664 0000000 0000000 00000066532 14142237372 0017665 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_VECTOR_GROW_SIZE (256)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_vector_insert_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_insert_prev(vector, tb_vector_size(vector) >> 1, (tb_pointer_t)0xf);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_insert_prev(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);
// clear it
tb_vector_clear(vector);
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_insert_head_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_insert_head(vector, (tb_pointer_t)0xf);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_insert_head(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);
// clear it
tb_vector_clear(vector);
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_insert_tail_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_insert_tail(vector, (tb_pointer_t)0xf);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_insert_tail(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);
// clear it
tb_vector_clear(vector);
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_ninsert_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
// insert one first
tb_vector_insert_head(vector, (tb_pointer_t)0xf);
tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
tb_vector_ninsert_prev(vector, 1, (tb_pointer_t)0xf, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_ninsert_prev(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n + 1);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);
// clear it
tb_vector_clear(vector);
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_ninsert_head_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_ninsert_head(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);
// clear it
tb_vector_clear(vector);
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_ninsert_tail_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_hong_t t = tb_mclock();
tb_vector_ninsert_tail(vector, (tb_pointer_t)0xf, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_ninsert_tail(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);
// clear it
tb_vector_clear(vector);
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_remove_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_remove(vector, tb_vector_size(vector) >> 1);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_remove(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_remove_head_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_remove_head(vector);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_remove_head(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_remove_last_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_remove_last(vector);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_remove_last(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_nremove_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_vector_nremove(vector, tb_iterator_head(vector), n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_nremove(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_nremove_head_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_vector_nremove_head(vector, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_nremove_head(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_nremove_last_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_vector_nremove_last(vector, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_nremove_last(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(!tb_vector_size(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_replace_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
__tb_volatile__ tb_size_t itor = tb_iterator_head(vector);
__tb_volatile__ tb_size_t tail = tb_iterator_tail(vector);
tb_hong_t t = tb_mclock();
for (; itor != tail; itor = tb_iterator_next(vector, itor)) tb_vector_replace(vector, itor, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_replace(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd);
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_replace_head_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_replace_head(vector, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_replace_head(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd);
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_replace_last_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
for (i = 0; i < n; i++) tb_vector_replace_last(vector, (tb_pointer_t)0xd);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_replace_last(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd);
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_nreplace_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_vector_nreplace(vector, tb_iterator_head(vector), (tb_pointer_t)0xd, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_nreplace(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd);
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_nreplace_head_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_vector_nreplace_head(vector, (tb_pointer_t)0xd, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_nreplace_head(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd);
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_nreplace_last_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_vector_nreplace_last(vector, (tb_pointer_t)0xd, n);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_nreplace_last(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// check
tb_assert(tb_vector_size(vector) == n);
tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd);
tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd);
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_iterator_next_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_for_all (tb_char_t*, item, vector) tb_used(item);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_iterator_next(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_size_t tb_vector_iterator_prev_test()
{
// init
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return_val(vector, 0);
tb_size_t n = 10000;
tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
tb_hong_t t = tb_mclock();
tb_rfor_all (tb_char_t*, item, vector) tb_used(item);
t = tb_mclock() - t;
// time
tb_trace_i("tb_vector_iterator_prev(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));
// exit
tb_vector_exit(vector);
return n / ((tb_uint32_t)(t) + 1);
}
static tb_void_t tb_vector_int_dump(tb_vector_ref_t vector)
{
tb_trace_i("tb_int_t size: %lu, maxn: %lu", tb_vector_size(vector), tb_vector_maxn(vector));
tb_for_all (tb_char_t*, item, vector)
{
tb_trace_i("tb_int_t at[%lu]: %x", item_itor, item);
}
}
static tb_void_t tb_vector_int_test()
{
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return(vector);
tb_trace_i("=============================================================");
tb_trace_i("insert:");
tb_vector_ninsert_head(vector, (tb_pointer_t)0xa, 10);
tb_vector_ninsert_tail(vector, (tb_pointer_t)0xf, 10);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)0);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)1);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)2);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)3);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)4);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)5);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)6);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)7);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)8);
tb_vector_insert_prev(vector, 10, (tb_pointer_t)9);
tb_vector_insert_head(vector, (tb_pointer_t)4);
tb_vector_insert_head(vector, (tb_pointer_t)3);
tb_vector_insert_head(vector, (tb_pointer_t)2);
tb_vector_insert_head(vector, (tb_pointer_t)1);
tb_vector_insert_head(vector, (tb_pointer_t)0);
tb_vector_insert_tail(vector, (tb_pointer_t)5);
tb_vector_insert_tail(vector, (tb_pointer_t)6);
tb_vector_insert_tail(vector, (tb_pointer_t)7);
tb_vector_insert_tail(vector, (tb_pointer_t)8);
tb_vector_insert_tail(vector, (tb_pointer_t)9);
tb_vector_int_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("remove:");
tb_vector_nremove_head(vector, 5);
tb_vector_nremove_last(vector, 5);
tb_vector_int_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("replace:");
tb_vector_nreplace_head(vector, (tb_pointer_t)0xf, 10);
tb_vector_nreplace_last(vector, (tb_pointer_t)0xa, 10);
tb_vector_replace_head(vector, 0);
tb_vector_replace_last(vector, 0);
tb_vector_int_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_vector_clear(vector);
tb_vector_int_dump(vector);
tb_vector_exit(vector);
}
static tb_void_t tb_vector_str_dump(tb_vector_ref_t vector)
{
tb_trace_i("str size: %lu, maxn: %lu", tb_vector_size(vector), tb_vector_maxn(vector));
tb_for_all (tb_char_t*, item, vector)
tb_trace_i("str at[%lu]: %s", item_itor, item);
}
static tb_void_t tb_vector_str_test()
{
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_str(tb_true));
tb_assert_and_check_return(vector);
tb_trace_i("=============================================================");
tb_trace_i("insert:");
tb_vector_ninsert_head(vector, "HHHHHHHHHH", 10);
tb_vector_ninsert_tail(vector, "TTTTTTTTTT", 10);
tb_vector_insert_prev(vector, 10, "0000000000");
tb_vector_insert_prev(vector, 10, "1111111111");
tb_vector_insert_prev(vector, 10, "2222222222");
tb_vector_insert_prev(vector, 10, "3333333333");
tb_vector_insert_prev(vector, 10, "4444444444");
tb_vector_insert_prev(vector, 10, "5555555555");
tb_vector_insert_prev(vector, 10, "6666666666");
tb_vector_insert_prev(vector, 10, "7777777777");
tb_vector_insert_prev(vector, 10, "8888888888");
tb_vector_insert_prev(vector, 10, "9999999999");
tb_vector_insert_head(vector, "4444444444");
tb_vector_insert_head(vector, "3333333333");
tb_vector_insert_head(vector, "2222222222");
tb_vector_insert_head(vector, "1111111111");
tb_vector_insert_head(vector, "0000000000");
tb_vector_insert_tail(vector, "5555555555");
tb_vector_insert_tail(vector, "6666666666");
tb_vector_insert_tail(vector, "7777777777");
tb_vector_insert_tail(vector, "8888888888");
tb_vector_insert_tail(vector, "9999999999");
tb_vector_str_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("remove:");
tb_vector_nremove_head(vector, 5);
tb_vector_nremove_last(vector, 5);
tb_vector_str_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("replace:");
tb_vector_nreplace_head(vector, "TTTTTTTTTT", 10);
tb_vector_nreplace_last(vector, "HHHHHHHHHH", 10);
tb_vector_replace_head(vector, "OOOOOOOOOO");
tb_vector_replace_last(vector, "OOOOOOOOOO");
tb_vector_str_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_vector_clear(vector);
tb_vector_str_dump(vector);
tb_vector_exit(vector);
}
static tb_void_t tb_vector_mem_dump(tb_vector_ref_t vector)
{
tb_trace_i("ifm size: %lu, maxn: %lu", tb_vector_size(vector), tb_vector_maxn(vector));
tb_for_all (tb_char_t*, item, vector)
{
tb_trace_i("ifm at[%lu]: %s", item_itor, item);
}
}
static tb_void_t tb_vector_mem_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_trace_i("ifm free: %s, priv: %s", buff, element->priv);
}
static tb_void_t tb_vector_mem_test()
{
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_mem(11, tb_vector_mem_free, "ifm"));
tb_assert_and_check_return(vector);
tb_trace_i("=============================================================");
tb_trace_i("insert:");
tb_vector_ninsert_head(vector, "HHHHHHHHHH", 10);
tb_vector_ninsert_tail(vector, "TTTTTTTTTT", 10);
tb_vector_insert_prev(vector, 10, "0000000000");
tb_vector_insert_prev(vector, 10, "1111111111");
tb_vector_insert_prev(vector, 10, "2222222222");
tb_vector_insert_prev(vector, 10, "3333333333");
tb_vector_insert_prev(vector, 10, "4444444444");
tb_vector_insert_prev(vector, 10, "5555555555");
tb_vector_insert_prev(vector, 10, "6666666666");
tb_vector_insert_prev(vector, 10, "7777777777");
tb_vector_insert_prev(vector, 10, "8888888888");
tb_vector_insert_prev(vector, 10, "9999999999");
tb_vector_insert_head(vector, "4444444444");
tb_vector_insert_head(vector, "3333333333");
tb_vector_insert_head(vector, "2222222222");
tb_vector_insert_head(vector, "1111111111");
tb_vector_insert_head(vector, "0000000000");
tb_vector_insert_tail(vector, "5555555555");
tb_vector_insert_tail(vector, "6666666666");
tb_vector_insert_tail(vector, "7777777777");
tb_vector_insert_tail(vector, "8888888888");
tb_vector_insert_tail(vector, "9999999999");
tb_vector_mem_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("remove:");
tb_vector_nremove_head(vector, 5);
tb_vector_nremove_last(vector, 5);
tb_vector_mem_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("replace:");
tb_vector_nreplace_head(vector, "TTTTTTTTTT", 10);
tb_vector_nreplace_last(vector, "HHHHHHHHHH", 10);
tb_vector_replace_head(vector, "OOOOOOOOOO");
tb_vector_replace_last(vector, "OOOOOOOOOO");
tb_vector_mem_dump(vector);
tb_trace_i("=============================================================");
tb_trace_i("clear:");
tb_vector_clear(vector);
tb_vector_mem_dump(vector);
tb_vector_exit(vector);
}
static tb_void_t tb_vector_perf_test()
{
tb_size_t score = 0;
tb_trace_i("=============================================================");
tb_trace_i("insert performance:");
score += tb_vector_insert_test();
score += tb_vector_insert_head_test();
score += tb_vector_insert_tail_test();
score += tb_vector_ninsert_test();
score += tb_vector_ninsert_head_test();
score += tb_vector_ninsert_tail_test();
tb_trace_i("=============================================================");
tb_trace_i("remove performance:");
score += tb_vector_remove_test();
score += tb_vector_remove_head_test();
score += tb_vector_remove_last_test();
score += tb_vector_nremove_test();
score += tb_vector_nremove_head_test();
score += tb_vector_nremove_last_test();
tb_trace_i("=============================================================");
tb_trace_i("replace performance:");
score += tb_vector_replace_test();
score += tb_vector_replace_head_test();
score += tb_vector_replace_last_test();
score += tb_vector_nreplace_test();
score += tb_vector_nreplace_head_test();
score += tb_vector_nreplace_last_test();
tb_trace_i("=============================================================");
tb_trace_i("iterator performance:");
score += tb_vector_iterator_next_test();
score += tb_vector_iterator_prev_test();
tb_trace_i("=============================================================");
tb_trace_i("score: %lu", score / 100);
}
static tb_void_t tb_vector_test_itor_perf()
{
// init vector
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_size());
tb_assert_and_check_return(vector);
// reset random
tb_random_reset(tb_true);
// add items
__tb_volatile__ tb_size_t n = 10000;
while (n--) tb_vector_insert_tail(vector, (tb_pointer_t)(tb_size_t)tb_random_value());
// done
tb_hong_t t = tb_mclock();
__tb_volatile__ tb_hize_t test[2] = {0};
__tb_volatile__ tb_size_t itor = tb_iterator_head(vector);
for (; itor != tb_iterator_tail(vector); )
{
__tb_volatile__ tb_size_t item = (tb_size_t)tb_iterator_item(vector, itor);
if (!(((tb_size_t)item >> 25) & 0x1))
{
// remove, hack: the itor of the same item is mutable
tb_vector_remove(vector, itor);
// continue
continue ;
}
else
{
test[0] += (tb_size_t)item;
test[1]++;
}
itor = tb_iterator_next(vector, itor);
}
t = tb_mclock() - t;
tb_trace_i("item: %llx, size: %llu ?= %u, time: %lld", test[0], test[1], tb_vector_size(vector), t);
// exit
tb_vector_exit(vector);
}
static tb_bool_t tb_vector_test_walk_item(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// done
tb_hize_t* test = (tb_hize_t*)value;
tb_size_t i = (tb_size_t)item;
tb_bool_t ok = tb_false;
if (!((i >> 25) & 0x1)) ok = tb_true;
else
{
test[0] += i;
test[1]++;
}
// ok?
return ok;
}
static tb_void_t tb_vector_test_walk_perf()
{
// init vector
tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long());
tb_assert_and_check_return(vector);
// reset random
tb_random_reset(tb_true);
// add items
__tb_volatile__ tb_size_t n = 10000;
while (n--) tb_vector_insert_tail(vector, (tb_pointer_t)(tb_size_t)tb_random_value());
// done
tb_hong_t t = tb_mclock();
__tb_volatile__ tb_hize_t test[2] = {0};
tb_remove_if(vector, tb_vector_test_walk_item, (tb_pointer_t)test);
t = tb_mclock() - t;
// trace
tb_trace_i("item: %llx, size: %llu ?= %u, time: %lld", test[0], test[1], tb_vector_size(vector), t);
// exit
tb_vector_exit(vector);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_container_vector_main(tb_int_t argc, tb_char_t** argv)
{
#if 1
tb_vector_int_test();
tb_vector_str_test();
tb_vector_mem_test();
#endif
#if 1
tb_vector_perf_test();
#endif
#if 1
tb_vector_test_itor_perf();
tb_vector_test_walk_perf();
#endif
return 0;
}
tbox-1.6.7/src/demo/coroutine/ 0000775 0000000 0000000 00000000000 14142237372 0016230 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/demo/coroutine/channel.c 0000664 0000000 0000000 00000010636 14142237372 0020012 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the switch count
#define COUNT (10000000)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_channel_test_send(tb_cpointer_t priv)
{
// check
tb_co_channel_ref_t channel = (tb_co_channel_ref_t)priv;
// loop
tb_size_t count = 10;
while (count--)
{
// trace
tb_trace_i("[coroutine: %p]: send: %lu", tb_coroutine_self(), count);
// send data
tb_co_channel_send(channel, (tb_cpointer_t)count);
// trace
tb_trace_i("[coroutine: %p]: send: %lu ok", tb_coroutine_self(), count);
}
}
static tb_void_t tb_demo_coroutine_channel_test_recv(tb_cpointer_t priv)
{
// check
tb_co_channel_ref_t channel = (tb_co_channel_ref_t)priv;
// loop
tb_size_t count = 10;
while (count--)
{
// trace
tb_trace_i("[coroutine: %p]: recv: ..", tb_coroutine_self());
// recv
tb_size_t data = (tb_size_t)tb_co_channel_recv(channel);
// trace
tb_trace_i("[coroutine: %p]: recv: %lu ok", tb_coroutine_self(), data);
}
}
static tb_void_t tb_demo_coroutine_channel_test(tb_size_t size)
{
// trace
tb_trace_i("test: %lu", size);
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// init channel
tb_co_channel_ref_t channel = tb_co_channel_init(size, tb_null, 0);
tb_assert(channel);
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_test_send, channel, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_test_send, channel, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_test_send, channel, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_test_recv, channel, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_test_recv, channel, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_test_recv, channel, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit channel
tb_co_channel_exit(channel);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
}
static tb_void_t tb_demo_coroutine_channel_perf_send(tb_cpointer_t priv)
{
// check
tb_co_channel_ref_t channel = (tb_co_channel_ref_t)priv;
// loop
tb_size_t count = COUNT;
while (count--) tb_co_channel_send(channel, (tb_cpointer_t)count);
}
static tb_void_t tb_demo_coroutine_channel_perf_recv(tb_cpointer_t priv)
{
// check
tb_co_channel_ref_t channel = (tb_co_channel_ref_t)priv;
// loop
tb_size_t count = COUNT;
while (count--) tb_co_channel_recv(channel);
}
static tb_void_t tb_demo_coroutine_channel_perf(tb_size_t size)
{
// trace
tb_trace_i("perf: %lu", size);
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// init channel
tb_co_channel_ref_t channel = tb_co_channel_init(size, tb_null, 0);
tb_assert(channel);
// start coroutine
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_perf_send, channel, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_channel_perf_recv, channel, 0);
// init the start time
tb_hong_t startime = tb_mclock();
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// computing time
tb_hong_t duration = tb_mclock() - startime;
// exit channel
tb_co_channel_exit(channel);
// trace
tb_trace_i("%d passes in %lld ms, %lld passes per second", COUNT, duration, (((tb_hong_t)1000 * COUNT) / duration));
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_channel_main(tb_int_t argc, tb_char_t** argv)
{
tb_demo_coroutine_channel_test(0);
tb_demo_coroutine_channel_test(1);
tb_demo_coroutine_channel_test(5);
tb_demo_coroutine_channel_perf(0);
tb_demo_coroutine_channel_perf(1);
tb_demo_coroutine_channel_perf(10);
return 0;
}
tbox-1.6.7/src/demo/coroutine/dns.c 0000664 0000000 0000000 00000002567 14142237372 0017172 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_dns(tb_cpointer_t priv)
{
tb_ipaddr_t addr;
tb_hong_t time = tb_mclock();
tb_char_t const* name = (tb_char_t const*)priv;
if (tb_dns_looker_done(name, &addr))
{
time = tb_mclock() - time;
tb_trace_i("lookup: %s => %{ipaddr}, %lld ms", name, &addr, time);
}
else tb_trace_i("lookup: %s failed", name);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_dns_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc >= 2 && argv[1], -1);
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start dns
tb_size_t n = argv[2]? (tb_size_t)tb_atoi(argv[2]) : 10;
while (n--)
{
// start it
tb_coroutine_start(scheduler, tb_demo_coroutine_dns, argv[1], 0);
}
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
// end
return 0;
}
tbox-1.6.7/src/demo/coroutine/echo_client.c 0000664 0000000 0000000 00000005772 14142237372 0020663 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// port
#define TB_DEMO_PORT (9001)
// timeout
#define TB_DEMO_TIMEOUT (-1)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_echo(tb_cpointer_t priv)
{
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// init address
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, "127.0.0.1", TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
// trace
tb_trace_i("connecting(%p): %{ipaddr} ..", sock, &addr);
// connect socket
tb_long_t ok;
while (!(ok = tb_socket_connect(sock, &addr)))
{
// wait it
if (tb_socket_wait(sock, TB_SOCKET_EVENT_CONN, TB_DEMO_TIMEOUT) <= 0) break;
}
// connect ok?
tb_check_break(ok > 0);
// loop
tb_byte_t data[8192] = {0};
tb_long_t count = (tb_long_t)priv;
while (count--)
{
// send data
if (tb_socket_bsend(sock, (tb_byte_t const*)"hello world..", 13))
{
// recv data
if (!tb_socket_brecv(sock, data, 13))
{
// error
tb_trace_e("send error!");
break;
}
}
else break;
}
// trace
tb_trace_d("send(%p): %s %s", sock, data, count <= 0? "ok" : "failed");
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_echo_client_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc >= 1, -1);
// the coroutines count
tb_size_t count = argc > 1? tb_atoi(argv[1]) : 100;
// the request count
tb_size_t reqt_count = argc > 2? tb_atoi(argv[2]) : 10000;
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start echo
tb_size_t i = 0;
for (i = 0; i < count; i++)
tb_coroutine_start(scheduler, tb_demo_coroutine_echo, (tb_cpointer_t)reqt_count, 0);
// start time
tb_hong_t startime = tb_mclock();
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// compute the spent time
tb_hong_t spent = tb_mclock() - startime;
// trace
tb_trace_i("echo: clients: %lu, request: %lu, spent: %lld ms", count, reqt_count, spent);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
// end
return 0;
}
tbox-1.6.7/src/demo/coroutine/echo_server.c 0000664 0000000 0000000 00000005307 14142237372 0020705 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// port
#define TB_DEMO_PORT (9001)
// timeout
#define TB_DEMO_TIMEOUT (-1)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_client(tb_cpointer_t priv)
{
// check
tb_socket_ref_t sock = (tb_socket_ref_t)priv;
tb_assert_and_check_return(sock);
// loop
tb_byte_t data[8192] = {0};
tb_size_t size = 13;
while (1)
{
// recv data
if (tb_socket_brecv(sock, data, size))
{
// send data
if (!tb_socket_bsend(sock, data, size))
{
// error
tb_trace_e("send error!");
break;
}
}
else break;
}
// trace
tb_trace_d("echo: %s", data);
// exit socket
tb_socket_exit(sock);
}
static tb_void_t tb_demo_coroutine_listen(tb_cpointer_t priv)
{
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// bind socket
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, tb_null, TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
if (!tb_socket_bind(sock, &addr)) break;
// listen socket
if (!tb_socket_listen(sock, 1000)) break;
// trace
tb_trace_i("listening ..");
// accept client sockets
tb_socket_ref_t client = tb_null;
while (1)
{
// accept and start client connection
if ((client = tb_socket_accept(sock, tb_null)))
{
if (!tb_coroutine_start(tb_null, tb_demo_coroutine_client, client, 0)) break;
}
else if (tb_socket_wait(sock, TB_SOCKET_EVENT_ACPT, TB_DEMO_TIMEOUT) < 0) break;
}
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_echo_server_main(tb_int_t argc, tb_char_t** argv)
{
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start listening
tb_coroutine_start(scheduler, tb_demo_coroutine_listen, tb_null, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/file_client.c 0000664 0000000 0000000 00000012701 14142237372 0020652 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "file_client"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// port
#define TB_DEMO_PORT (9090)
// timeout
#define TB_DEMO_TIMEOUT (-1)
// eanble conn/recv coroutine
#define TB_DEMO_CONN_RECV (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if TB_DEMO_CONN_RECV
static tb_void_t tb_demo_coroutine_recv(tb_cpointer_t priv)
{
// check
tb_socket_ref_t sock = (tb_socket_ref_t)priv;
tb_assert_and_check_return(sock);
// trace
tb_trace_d("[%p]: recving ..", sock);
// recv data
tb_byte_t data[8192];
tb_hize_t recv = 0;
tb_long_t wait = 0;
tb_hong_t time = tb_mclock();
while (1)
{
// read it
tb_long_t real = tb_socket_recv(sock, data, sizeof(data));
// trace
tb_trace_d("[%p]: recv: %ld, total: %lu", sock, real, recv + (real > 0? real : 0));
// has data?
if (real > 0)
{
recv += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, TB_DEMO_TIMEOUT);
tb_assert_and_check_break(wait >= 0);
}
// failed or end?
else break;
}
// trace
tb_trace_i("[%p]: recv %llu bytes %lld ms", sock, recv, tb_mclock() - time);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
}
static tb_void_t tb_demo_coroutine_pull(tb_cpointer_t priv)
{
tb_long_t ok = -1;
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// init address
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, "127.0.0.1", TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
// trace
tb_trace_d("[%p]: connecting %{ipaddr} ..", sock, &addr);
// connect socket
while (!(ok = tb_socket_connect(sock, &addr)))
{
// wait it
if (tb_socket_wait(sock, TB_SOCKET_EVENT_CONN, TB_DEMO_TIMEOUT) <= 0) break;
}
// connect ok?
tb_check_break(ok > 0);
// start recv coroutine
tb_coroutine_start(tb_co_scheduler_self(), tb_demo_coroutine_recv, sock, 0);
} while (0);
// failed?
if (ok <= 0)
{
if (sock) tb_socket_exit(sock);
sock = tb_null;
}
}
#else
static tb_void_t tb_demo_coroutine_pull(tb_cpointer_t priv)
{
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// init address
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, "127.0.0.1", TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
// trace
tb_trace_d("[%p]: connecting %{ipaddr} ..", sock, &addr);
// connect socket
tb_long_t ok;
while (!(ok = tb_socket_connect(sock, &addr)))
{
// wait it
if (tb_socket_wait(sock, TB_SOCKET_EVENT_CONN, TB_DEMO_TIMEOUT) <= 0) break;
}
// connect ok?
tb_check_break(ok > 0);
// trace
tb_trace_d("[%p]: recving ..", sock);
// recv data
tb_byte_t data[8192];
tb_hize_t recv = 0;
tb_long_t wait = 0;
tb_hong_t time = tb_mclock();
while (1)
{
// read it
tb_long_t real = tb_socket_recv(sock, data, sizeof(data));
// trace
tb_trace_d("[%p]: recv: %ld, total: %lu", sock, real, recv + (real > 0? real : 0));
// has data?
if (real > 0)
{
recv += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, TB_DEMO_TIMEOUT);
tb_assert_and_check_break(wait >= 0);
}
// failed or end?
else break;
}
// trace
tb_trace_i("[%p]: recv %llu bytes %lld ms", sock, recv, tb_mclock() - time);
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_file_client_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2 && argv[1], -1);
// the coroutines count
tb_size_t count = tb_atoi(argv[1]);
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start file
tb_size_t i = 0;
for (i = 0; i < count; i++)
{
// start it
tb_coroutine_start(scheduler, tb_demo_coroutine_pull, tb_null, 0);
}
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
// end
return 0;
}
tbox-1.6.7/src/demo/coroutine/file_server.c 0000664 0000000 0000000 00000010105 14142237372 0020676 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "file_server"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// port
#define TB_DEMO_PORT (9090)
// timeout
#define TB_DEMO_TIMEOUT (-1)
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the file path
static tb_char_t g_filepath[TB_PATH_MAXN];
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_client(tb_cpointer_t priv)
{
// check
tb_socket_ref_t sock = (tb_socket_ref_t)priv;
tb_assert_and_check_return(sock);
// trace
tb_trace_d("[%p]: sending %s ..", sock, g_filepath);
// init file
tb_file_ref_t file = tb_file_init(g_filepath, TB_FILE_MODE_RO);
tb_assert_and_check_return(file);
// send data
tb_hize_t send = 0;
tb_hize_t size = tb_file_size(file);
tb_long_t wait = 0;
tb_hong_t time = tb_mclock();
while (send < size)
{
// send it
tb_hong_t real = tb_socket_sendf(sock, file, send, size - send);
// trace
tb_trace_d("[%p]: send: %lld, total: %llu", sock, real, send + (real > 0? real : 0));
// has data?
if (real > 0)
{
send += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, TB_DEMO_TIMEOUT);
tb_assert_and_check_break(wait >= 0);
}
// failed or end?
else break;
}
// trace
tb_trace_i("[%p]: send: %lld bytes %lld ms", sock, send, tb_mclock() - time);
// exit file
tb_file_exit(file);
// exit socket
tb_socket_exit(sock);
}
static tb_void_t tb_demo_coroutine_listen(tb_cpointer_t priv)
{
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// bind socket
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, tb_null, TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
if (!tb_socket_bind(sock, &addr)) break;
// listen socket
if (!tb_socket_listen(sock, 1000)) break;
// trace
tb_trace_i("listening ..");
// accept client sockets
tb_size_t count = 0;
tb_socket_ref_t client = tb_null;
while (1)
{
// accept and start client connection
if ((client = tb_socket_accept(sock, tb_null)))
{
if (!tb_coroutine_start(tb_null, tb_demo_coroutine_client, client, 0)) break;
count++;
}
else if (tb_socket_wait(sock, TB_SOCKET_EVENT_ACPT, -1) <= 0) break;
}
// trace
tb_trace_i("listened %lu", count);
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_file_server_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2 && argv[1], -1);
// the file path
tb_char_t const* filepath = argv[1];
tb_assert_and_check_return_val(filepath, -1);
// save the file path
tb_strlcpy(g_filepath, filepath, sizeof(g_filepath));
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start listening
tb_coroutine_start(scheduler, tb_demo_coroutine_listen, tb_null, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/http_server.c 0000664 0000000 0000000 00000035061 14142237372 0020746 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the port
#define TB_DEMO_PORT (8080)
// the timeout
#define TB_DEMO_TIMEOUT (-1)
// the cpu-core count
#define TB_DEMO_CPU (1)
// the stack size
#define TB_DEMO_STACKSIZE (8192 << 2)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the http session type
typedef struct __tb_demo_http_session_t
{
// the socket
tb_socket_ref_t sock;
// the http code
tb_size_t code;
// the http method
tb_size_t method;
// the content size
tb_hize_t content_size;
// is keep-alive?
tb_bool_t keep_alive;
// the file
tb_file_ref_t file;
// the data buffer
tb_byte_t data[8192];
// the resource path
tb_char_t path[1024];
// the line buffer
tb_char_t line[1024];
// the line size
tb_size_t line_size;
// the line index
tb_size_t line_index;
}tb_demo_http_session_t, *tb_demo_http_session_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the root directory
static tb_char_t g_rootdir[TB_PATH_MAXN];
// only send data for testing?
static tb_bool_t g_onlydata = tb_false;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_demo_http_session_init(tb_demo_http_session_ref_t session, tb_socket_ref_t sock)
{
// check
tb_assert(session && sock);
// init
session->sock = sock;
session->file = tb_null;
session->line_size = 0;
session->line_index = 0;
session->keep_alive = tb_false;
session->code = TB_HTTP_CODE_OK;
session->method = TB_HTTP_METHOD_GET;
session->content_size = 0;
// ok
return tb_true;
}
static tb_void_t tb_demo_http_session_exit(tb_demo_http_session_ref_t session)
{
// check
tb_assert(session);
// exit socket
if (session->sock) tb_socket_exit(session->sock);
session->sock = tb_null;
// exit file
if (session->file) tb_file_exit(session->file);
session->file = tb_null;
}
static tb_bool_t tb_demo_http_session_data_send(tb_socket_ref_t sock, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(sock && data && size, tb_false);
// send data
tb_size_t send = 0;
tb_long_t wait = 0;
while (send < size)
{
// send it
tb_long_t real = tb_socket_send(sock, data + send, size - send);
// has data?
if (real > 0)
{
send += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, TB_DEMO_TIMEOUT);
tb_assert_and_check_break(wait >= 0);
}
// failed or end?
else break;
}
// ok?
return send == size;
}
static tb_bool_t tb_demo_http_session_file_send(tb_socket_ref_t sock, tb_file_ref_t file)
{
// check
tb_assert_and_check_return_val(sock && file, tb_false);
// send data
tb_hize_t send = 0;
tb_hize_t size = tb_file_size(file);
tb_long_t wait = 0;
while (send < size)
{
// send it
tb_hong_t real = tb_socket_sendf(sock, file, send, size - send);
// has data?
if (real > 0)
{
send += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, TB_DEMO_TIMEOUT);
tb_assert_and_check_break(wait >= 0);
}
// failed or end?
else break;
}
// ok?
return send == size;
}
static tb_char_t const* tb_demo_http_session_code_cstr(tb_size_t code)
{
// done
tb_char_t const* cstr = tb_null;
switch (code)
{
case TB_HTTP_CODE_OK: cstr = "OK"; break;
case TB_HTTP_CODE_BAD_REQUEST: cstr = "Bad Request"; break;
case TB_HTTP_CODE_NOT_FOUND: cstr = "Not Found"; break;
case TB_HTTP_CODE_NOT_IMPLEMENTED: cstr = "Not Implemented"; break;
case TB_HTTP_CODE_NOT_MODIFIED: cstr = "Not Modified"; break;
case TB_HTTP_CODE_INTERNAL_SERVER_ERROR: cstr = "Internal Server Error"; break;
default: break;
}
// check
tb_assert(cstr);
// ok?
return cstr;
}
static tb_bool_t tb_demo_http_session_resp_send(tb_demo_http_session_ref_t session, tb_char_t const* cstr)
{
// check
tb_assert_and_check_return_val(session && session->sock, tb_false);
// make the response header
tb_long_t size = tb_snprintf( (tb_char_t*)session->data
, sizeof(session->data)
, "HTTP/1.1 %lu %s\r\n"
"Server: %s\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %llu\r\n"
"Connection: %s\r\n"
"\r\n"
"%s"
, session->code
, tb_demo_http_session_code_cstr(session->code)
, TB_VERSION_SHORT_STRING
, session->file? tb_file_size(session->file) : (cstr? tb_strlen(cstr) : 0)
, session->keep_alive? "keep-alive" : "close"
, cstr? cstr : "");
tb_assert_and_check_return_val(size > 0, tb_false);
// end
session->data[size] = 0;
// send the response header
if (!tb_demo_http_session_data_send(session->sock, session->data, size)) return tb_false;
// send the response file if exists
if (session->file && !tb_demo_http_session_file_send(session->sock, session->file)) return tb_false;
// ok
return tb_true;
}
static tb_void_t tb_demo_http_session_head_parse(tb_demo_http_session_ref_t session)
{
// check
tb_assert_and_check_return(session);
// the first line?
tb_char_t const* p = session->line;
if (!session->line_index)
{
// parse get
if (!tb_strnicmp(p, "GET", 3))
{
session->code = TB_HTTP_CODE_OK;
session->method = TB_HTTP_METHOD_GET;
p += 3;
}
// parse post
else if (!tb_strnicmp(p, "POST", 4))
{
session->code = TB_HTTP_CODE_NOT_IMPLEMENTED;
session->method = TB_HTTP_METHOD_POST;
p += 4;
}
// other method is not implemented
else session->code = TB_HTTP_CODE_NOT_IMPLEMENTED;
// get or post? parse the path
if ( session->method == TB_HTTP_METHOD_GET
|| session->method == TB_HTTP_METHOD_POST)
{
// skip space
while (*p && tb_isspace(*p)) p++;
// append path
tb_size_t i = 0;
while (*p && !tb_isspace(*p) && i < sizeof(session->path) - 1) session->path[i++] = *p++;
session->path[i] = '\0';
}
}
// key: value?
else
{
// seek to value
while (*p && *p != ':') p++;
tb_assert_and_check_return(*p);
p++; while (*p && tb_isspace(*p)) p++;
// no value
tb_check_return(*p);
// parse content-length
if (!tb_strnicmp(session->line, "Content-Length", 14))
session->content_size = tb_stou64(p);
// parse connection
else if (!tb_strnicmp(session->line, "Connection", 10))
session->keep_alive = !tb_stricmp(p, "keep-alive");
// parse range
else if (!tb_strnicmp(session->line, "Range", 5))
session->code = TB_HTTP_CODE_NOT_IMPLEMENTED;
}
}
static tb_long_t tb_demo_http_session_head_line(tb_demo_http_session_ref_t session, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(session && data && size, -1);
// done
tb_long_t ok = 0;
do
{
// done
tb_char_t ch = '\0';
tb_char_t const* p = (tb_char_t const*)data;
tb_char_t const* e = p + size;
while (p < e)
{
// the char
ch = *p++;
// error end?
if (!ch)
{
ok = -1;
break;
}
// append char to line
if (ch != '\n') session->line[session->line_size++] = ch;
// is line end?
else
{
// line end? strip '\r\n'
if (session->line_size && session->line[session->line_size - 1] == '\r')
{
session->line_size--;
session->line[session->line_size] = '\0';
}
// trace
tb_trace_d("head: %s", session->line);
// end?
if (!session->line_size)
{
// ok
ok = 1;
break;
}
// parse the header line
tb_demo_http_session_head_parse(session);
// clear line
session->line_size = 0;
// update line index
session->line_index++;
}
}
} while (0);
// ok?
return ok;
}
static tb_bool_t tb_demo_http_session_head_recv(tb_demo_http_session_ref_t session)
{
// check
tb_assert_and_check_return_val(session && session->sock, tb_false);
// read data
tb_long_t wait = 0;
tb_long_t ok = 0;
while (!ok)
{
// read it
tb_long_t real = tb_socket_recv(session->sock, session->data, sizeof(session->data));
// has data?
if (real > 0)
{
// get the header line
ok = tb_demo_http_session_head_line(session, session->data, real);
// clear wait events
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_socket_wait(session->sock, TB_SOCKET_EVENT_RECV, TB_DEMO_TIMEOUT);
tb_assert_and_check_break(wait >= 0);
}
// failed or end?
else break;
}
// ok?
return ok > 0;
}
static tb_void_t tb_demo_coroutine_client(tb_cpointer_t priv)
{
// check
tb_socket_ref_t sock = (tb_socket_ref_t)priv;
tb_assert_and_check_return(sock);
// done
tb_demo_http_session_t session;
do
{
// init session
if (!tb_demo_http_session_init(&session, sock)) break;
// read the request header
if (!tb_demo_http_session_head_recv(&session)) break;
// trace
tb_trace_d("path: %s", session.path);
// get file or data?
tb_char_t const* data = tb_null;
if (session.method == TB_HTTP_METHOD_GET)
{
// only send data?
if (g_onlydata) data = g_rootdir;
else
{
// make full path
tb_long_t size = tb_snprintf((tb_char_t*)session.data, sizeof(session.data), "%s%s%s", g_rootdir, session.path[0] != '/'? "/" : "", session.path);
if (size > 0) session.data[size] = 0;
// init file
session.file = tb_file_init((tb_char_t*)session.data, TB_FILE_MODE_RO);
// not found?
if (!session.file) session.code = TB_HTTP_CODE_NOT_FOUND;
}
}
// send the response
if (!tb_demo_http_session_resp_send(&session, data)) break;
// exit file
if (session.file) tb_file_exit(session.file);
session.file = tb_null;
// trace
tb_trace_d("ok!");
} while (session.keep_alive);
// exit session
tb_demo_http_session_exit(&session);
}
static tb_void_t tb_demo_coroutine_listen(tb_cpointer_t priv)
{
// TODO: fix thundering herd issues
tb_size_t count = 0;
tb_socket_ref_t client = tb_null;
tb_socket_ref_t sock = (tb_socket_ref_t)priv;
while (1)
{
// accept and start client connection
if ((client = tb_socket_accept(sock, tb_null)))
{
if (!tb_coroutine_start(tb_null, tb_demo_coroutine_client, client, TB_DEMO_STACKSIZE)) break;
count++;
}
else if (tb_socket_wait(sock, TB_SOCKET_EVENT_ACPT, -1) <= 0) break;
}
// trace
tb_trace_d("[%#x]: listened %lu", tb_thread_self(), count);
}
static tb_int_t tb_demo_coroutine_worker(tb_cpointer_t priv)
{
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_listen, priv, 0);
// run scheduler, enable exclusive mode if be only one cpu
tb_co_scheduler_loop(scheduler, TB_DEMO_CPU == 1);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_http_server_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// bind socket
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, tb_null, TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
if (!tb_socket_bind(sock, &addr)) break;
// listen socket
if (!tb_socket_listen(sock, 1000)) break;
// init the root directory
if (argv[1]) tb_strlcpy(g_rootdir, argv[1], sizeof(g_rootdir));
else tb_directory_current(g_rootdir, sizeof(g_rootdir));
// only data?
if (!tb_file_info(g_rootdir, tb_null)) g_onlydata = tb_true;
// trace
tb_trace_i("%s: %s", g_onlydata? "data" : "rootdir", g_rootdir);
#if TB_DEMO_CPU > 1
// start workers for multi-threads
tb_size_t count = TB_DEMO_CPU - 1;
while (count--) tb_thread_init(tb_null, tb_demo_coroutine_worker, sock, 0);
#endif
// start worker
tb_demo_coroutine_worker(sock);
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
// ok
return 0;
}
tbox-1.6.7/src/demo/coroutine/lock.c 0000664 0000000 0000000 00000003502 14142237372 0017324 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_lock_test_func(tb_cpointer_t priv)
{
// check
tb_co_lock_ref_t lock = (tb_co_lock_ref_t)priv;
tb_assert_and_check_return(lock);
// loop
tb_size_t count = 10;
while (count--)
{
// enter lock
tb_co_lock_enter(lock);
// trace
tb_trace_i("[coroutine: %p]: enter", tb_coroutine_self());
// wait some time
tb_msleep(1000);
// trace
tb_trace_i("[coroutine: %p]: leave", tb_coroutine_self());
// leave lock
tb_co_lock_leave(lock);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_lock_main(tb_int_t argc, tb_char_t** argv)
{
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// init lock
tb_co_lock_ref_t lock = tb_co_lock_init();
tb_assert(lock);
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_lock_test_func, lock, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_lock_test_func, lock, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_lock_test_func, lock, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_lock_test_func, lock, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_lock_test_func, lock, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit lock
tb_co_lock_exit(lock);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/nest.c 0000664 0000000 0000000 00000003036 14142237372 0017347 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_nest_next(tb_size_t start, tb_size_t end)
{
// loop
for (; start < end; start++)
{
// trace
tb_trace_i("[coroutine: %p]: %lu", tb_coroutine_self(), start);
// yield
tb_coroutine_yield();
}
}
static tb_void_t tb_demo_coroutine_nest_func(tb_cpointer_t priv)
{
// loop
tb_size_t count = (tb_size_t)priv;
while (count--)
{
// trace
tb_trace_i("[coroutine: %p]: %lu", tb_coroutine_self(), count);
// call next level function
tb_demo_coroutine_nest_next(count * 10, count * 10 + 5);
// yield
tb_coroutine_yield();
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_nest_main(tb_int_t argc, tb_char_t** argv)
{
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_nest_func, (tb_cpointer_t)10, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_nest_func, (tb_cpointer_t)10, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/ping.c 0000664 0000000 0000000 00000015754 14142237372 0017345 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_ICMP_ECHOREPLY (0)
#define TB_ICMP_ECHOREQ (8)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
#include "tbox/prefix/packed.h"
// the ip header type - rfc791
typedef struct __tb_ip_header_t
{
// version and ihl
tb_uint8_t vihl;
// type of service
tb_uint8_t tos;
// total length of the packet
tb_uint16_t total_len;
// unique identifier
tb_uint16_t id;
// flags and fragment offset
tb_uint16_t frag_and_flags;
// time to live
tb_uint8_t ttl;
// the protocol, tcp, udp, ..
tb_uint8_t proto;
// the checksum
tb_uint16_t checksum;
// the source ipaddr
tb_uint32_t source_ip;
// the dest ipaddr
tb_uint32_t dest_ip;
} __tb_packed__ tb_ip_header_t;
// the icmp header type - rfc792
typedef struct __tb_icmp_header_t
{
// icmp type
tb_uint8_t type;
// type sub code
tb_uint8_t code;
// checksum
tb_uint16_t checksum;
// identifier
tb_uint16_t id;
// sequence numner
tb_uint16_t seq;
// data
tb_byte_t data[1];
} __tb_packed__ tb_icmp_header_t;
// the icmp echo request type
typedef struct __tb_icmp_echo_request_t
{
// the icmp header
tb_icmp_header_t icmp;
// the request time
tb_hong_t time;
} __tb_packed__ tb_icmp_echo_request_t;
// the icmp echo reply type
typedef struct __tb_icmp_echo_reply_t
{
// the ip header
tb_ip_header_t ip;
// the echo request
tb_icmp_echo_request_t request;
} __tb_packed__ tb_icmp_echo_reply_t;
#include "tbox/prefix/packed.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_uint16_t tb_calculate_checksum(tb_byte_t const* data, tb_long_t size)
{
// calculate sum
tb_uint32_t sum = 0;
tb_long_t nleft = size;
tb_byte_t const* p = data;
while (nleft > 1)
{
sum += tb_bits_get_u16_le(p);
nleft -= 2;
p += 2;
}
// calculate answer
tb_uint16_t answer = 0;
if (nleft == 1)
{
*(tb_byte_t *)(&answer) = *p;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
static tb_bool_t tb_ping_send(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_uint16_t seq)
{
// init echo
tb_icmp_echo_request_t echo;
tb_uint64_t time = tb_mclock();
echo.icmp.type = TB_ICMP_ECHOREQ;
echo.icmp.code = 0;
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.checksum, 0);
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.id, 0xbeaf);
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.seq, seq);
tb_bits_set_u64_le((tb_byte_t*)&echo.time, time);
tb_uint16_t checksum = tb_calculate_checksum((tb_byte_t const*)&echo, sizeof(echo));
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.checksum, checksum);
// send echo
tb_long_t send = 0;
tb_long_t size = sizeof(echo);
tb_bool_t wait = tb_false;
tb_byte_t const* data = (tb_byte_t const*)&echo;
while (send < size)
{
tb_long_t real = tb_socket_usend(sock, addr, data + send, size - send);
if (real > 0)
{
send += real;
wait = tb_false;
}
else if (!real && !wait)
{
wait = tb_true;
real = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, -1);
tb_assert_and_check_break(real > 0);
}
else break;
}
// ok?
return send == size;
}
static tb_bool_t tb_ping_recv(tb_socket_ref_t sock, tb_uint16_t seq)
{
// recv echo
tb_icmp_echo_reply_t echo;
tb_long_t recv = 0;
tb_long_t size = sizeof(echo);
tb_bool_t wait = tb_false;
tb_byte_t* data = (tb_byte_t*)&echo;
while (recv < size)
{
tb_long_t real = tb_socket_urecv(sock, tb_null, data + recv, size - recv);
if (real > 0)
{
recv += real;
wait = tb_false;
}
else if (!real && !wait)
{
wait = tb_true;
real = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, -1);
tb_assert_and_check_break(real > 0);
}
else break;
}
tb_assert_and_check_return_val(recv == size, tb_false);
// check protocol (icmp)
tb_assert_and_check_return_val(echo.ip.proto == 1, tb_false);
// check icmp type
tb_assert_and_check_return_val(echo.request.icmp.type == TB_ICMP_ECHOREPLY, tb_false);
// check id
tb_assert_and_check_return_val(tb_bits_get_u16_le((tb_byte_t const*)&echo.request.icmp.id) == 0xbeaf, tb_false);
// get source ip address
tb_ipv4_t source_ip;
source_ip.u32 = tb_bits_get_u32_le((tb_byte_t const*)&echo.ip.source_ip);
// trace
tb_uint64_t time = tb_bits_get_u64_le((tb_byte_t const*)&echo.request.time);
tb_trace_i("%ld bytes from %{ipv4}: icmp_seq=%d ttl=%d time=%ld ms", size, &source_ip, seq, echo.ip.ttl, tb_mclock() - (tb_hong_t)time);
// ok
return tb_true;
}
static tb_void_t tb_demo_coroutine_ping(tb_cpointer_t priv)
{
// get address
tb_ipaddr_ref_t addr = (tb_ipaddr_ref_t)priv;
tb_assert_and_check_return(addr);
// init socket
tb_socket_ref_t sock = tb_socket_init(TB_SOCKET_TYPE_ICMP, TB_IPADDR_FAMILY_IPV4);
if (sock)
{
// send ping
tb_uint16_t i = 0;
tb_uint16_t n = 10;
while (i < n && tb_ping_send(sock, addr, i))
{
// recv ping
if (!tb_ping_recv(sock, i)) break;
i++;
// wait some time
tb_sleep(1);
}
// exit socket
tb_socket_exit(sock);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_ping_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2 && argv[1], -1);
// init addr
tb_ipaddr_t addr;
if (!tb_dns_looker_done(argv[1], &addr)) return -1;
// trace
tb_trace_i("PING %s (%{ipv4}): %d data bytes", argv[1], tb_ipaddr_ipv4(&addr), sizeof(tb_icmp_echo_request_t));
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start ping
tb_size_t n = 10;
while (n--)
{
// start it
tb_coroutine_start(scheduler, tb_demo_coroutine_ping, &addr, 0);
}
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
// end
return 0;
}
tbox-1.6.7/src/demo/coroutine/pipe.c 0000664 0000000 0000000 00000003373 14142237372 0017337 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define BUFSIZE (32767)
#define COUNT (100000)
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_demo_coroutine_writ(tb_cpointer_t priv)
{
tb_byte_t data[BUFSIZE];
tb_pipe_file_ref_t pipe = (tb_pipe_file_ref_t) priv;
for (tb_size_t i = 0; i < COUNT; i++)
{
if (!tb_pipe_file_bwrit(pipe, data, sizeof(data))) break;
tb_trace_i("[-->] %.4llu", i);
}
tb_pipe_file_exit(pipe);
}
static tb_void_t tb_demo_coroutine_read(tb_cpointer_t priv)
{
tb_byte_t data[BUFSIZE];
tb_pipe_file_ref_t pipe = (tb_pipe_file_ref_t) priv;
for (tb_size_t count = 0;; count++)
{
if (!tb_pipe_file_bread(pipe, data, sizeof(data))) break;
tb_trace_i("[<--] %.4llu", count);
}
tb_pipe_file_exit(pipe);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_pipe_main(tb_int_t argc, tb_char_t** argv)
{
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
tb_pipe_file_ref_t pair[2];
if (tb_pipe_file_init_pair(pair, 4096))
{
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_writ, pair[1], 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_read, pair[0], 0);
// do loop
tb_co_scheduler_loop(scheduler, tb_true);
}
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/process.c 0000664 0000000 0000000 00000002715 14142237372 0020057 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define COUNT (50)
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_demo_coroutine_proc(tb_cpointer_t priv)
{
// get arguments
tb_char_t** argv = (tb_char_t**)priv;
tb_assert_and_check_return(argv);
// init process
tb_process_ref_t process = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), tb_null);
if (process)
{
// wait process
tb_long_t status = 0;
tb_process_wait(process, &status, -1);
// trace
tb_trace_i("run: %s, status: %ld", argv[1], status);
// exit process
tb_process_exit(process);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_process_main(tb_int_t argc, tb_char_t** argv)
{
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start coroutines
tb_size_t count = COUNT;
while (count--)
tb_coroutine_start(scheduler, tb_demo_coroutine_proc, argv, 0);
// do loop
tb_co_scheduler_loop(scheduler, tb_true);
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/process_pipe.c 0000664 0000000 0000000 00000005457 14142237372 0021102 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define COUNT (50)
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_demo_coroutine_proc(tb_cpointer_t priv)
{
// get arguments
tb_char_t** argv = (tb_char_t**)priv;
tb_assert_and_check_return(argv);
// init id
static tb_size_t count = 0;
tb_size_t id = count++;
// init pipe files
tb_pipe_file_ref_t file[2] = {0};
if (tb_pipe_file_init_pair(file, 0))
{
// init process
tb_process_attr_t attr = {0};
attr.out.pipe = file[1];
attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE;
tb_process_ref_t process = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), &attr);
if (process)
{
// read pipe data
tb_size_t read = 0;
tb_byte_t data[8192];
tb_size_t size = sizeof(data);
tb_bool_t wait = tb_false;
while (read < size)
{
tb_long_t real = tb_pipe_file_read(file[0], data + read, size - read);
if (real > 0)
{
read += real;
wait = tb_false;
}
else if (!real && !wait)
{
// wait pipe
tb_long_t ok = tb_pipe_file_wait(file[0], TB_PIPE_EVENT_READ, 1000);
tb_check_break(ok > 0);
wait = tb_true;
}
else break;
}
// dump data
tb_trace_i("[%lu]: read pipe: %ld", id, read);
// wait process
tb_long_t status = 0;
tb_process_wait(process, &status, -1);
// trace
tb_trace_i("[%lu]: run: %s, status: %ld", id, argv[1], status);
// exit process
tb_process_exit(process);
}
// exit pipe files
tb_pipe_file_exit(file[0]);
tb_pipe_file_exit(file[1]);
}
// end
tb_trace_i("[%lu]: end", id);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_process_pipe_main(tb_int_t argc, tb_char_t** argv)
{
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start coroutines
tb_size_t count = COUNT;
while (count--)
tb_coroutine_start(scheduler, tb_demo_coroutine_proc, argv, 0);
// do loop
tb_co_scheduler_loop(scheduler, tb_true);
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/semaphore.c 0000664 0000000 0000000 00000004267 14142237372 0020370 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_semaphore_wait_func(tb_cpointer_t priv)
{
// check
tb_co_semaphore_ref_t semaphore = (tb_co_semaphore_ref_t)priv;
tb_assert(semaphore);
// loop
while (1)
{
// wait it
tb_long_t ok = tb_co_semaphore_wait(semaphore, -1);
tb_assert_and_check_break(ok > 0);
// trace
tb_trace_i("[coroutine: %p]: wait ok", tb_coroutine_self());
}
}
static tb_void_t tb_demo_coroutine_semaphore_post_func(tb_cpointer_t priv)
{
// check
tb_co_semaphore_ref_t semaphore = (tb_co_semaphore_ref_t)priv;
tb_assert(semaphore);
// loop
while (1)
{
// trace
tb_trace_i("[coroutine: %p]: post", tb_coroutine_self());
// post it
tb_co_semaphore_post(semaphore, 2);
// wait some time
tb_msleep(1000);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_semaphore_main(tb_int_t argc, tb_char_t** argv)
{
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// init semaphore
tb_co_semaphore_ref_t semaphore = tb_co_semaphore_init(0);
tb_assert(semaphore);
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_semaphore_wait_func, semaphore, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_semaphore_wait_func, semaphore, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_semaphore_wait_func, semaphore, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_semaphore_wait_func, semaphore, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_semaphore_post_func, semaphore, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit semaphore
tb_co_semaphore_exit(semaphore);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/sleep.c 0000664 0000000 0000000 00000003071 14142237372 0017505 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_coroutine_sleep_func(tb_cpointer_t priv)
{
// the interval
tb_size_t interval = (tb_size_t)priv;
// loop
tb_size_t count = 10;
while (count--)
{
// get the start time
tb_hong_t time = tb_mclock();
// sleep it
tb_msleep(interval);
// update the interval time
time = tb_mclock() - time;
// trace
tb_trace_i("[coroutine: %lu]: count: %lu, interval: %lld ms", interval, count, time);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_coroutine_sleep_main(tb_int_t argc, tb_char_t** argv)
{
// init scheduler
tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init();
if (scheduler)
{
// start coroutines
tb_coroutine_start(scheduler, tb_demo_coroutine_sleep_func, (tb_cpointer_t)1000, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_sleep_func, (tb_cpointer_t)2000, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_sleep_func, (tb_cpointer_t)10, 0);
tb_coroutine_start(scheduler, tb_demo_coroutine_sleep_func, (tb_cpointer_t)100, 0);
// run scheduler
tb_co_scheduler_loop(scheduler, tb_true);
// exit scheduler
tb_co_scheduler_exit(scheduler);
}
return 0;
}
tbox-1.6.7/src/demo/coroutine/spider.c 0000664 0000000 0000000 00000042050 14142237372 0017663 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "spider"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the timeout
//#define TB_DEMO_TIMEOUT (-1)
#define TB_DEMO_TIMEOUT (15000)
// the limit rate, 256KB/s
#define TB_DEMO_LIMITRATE (0)
//#define TB_DEMO_LIMITRATE (256000)
// the filter maxn
#define TB_DEMO_FILTER_MAXN (100000)
// the task maxn
#define TB_DEMO_TASK_MAXN (50)
// the stack size
#define TB_DEMO_STACKSIZE (8192 << 4)
// the user agent
#define TB_DEMO_USER_AGENT "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the spider type
typedef struct __tb_demo_spider_t
{
// the homepage
tb_char_t const* homepage;
// the root directory
tb_char_t rootdir[TB_PATH_MAXN];
// the bloom filter
tb_bloom_filter_ref_t filter;
// the urls
tb_co_channel_ref_t urls;
// the scheduler
tb_co_scheduler_ref_t scheduler;
}tb_demo_spider_t, *tb_demo_spider_ref_t;
// the spider parser type
typedef struct __tb_demo_spider_parser_t
{
// the stream
tb_stream_ref_t stream;
// the data
tb_byte_t* data;
// the data size
tb_size_t size;
// the data maxn
tb_size_t maxn;
// the data offset
tb_size_t offset;
// the path buffer
tb_char_t path[TB_PATH_MAXN];
// the url
tb_url_t url;
}tb_demo_spider_parser_t, *tb_demo_spider_parser_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
static tb_void_t tb_demo_spider_urls_free(tb_pointer_t data, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_spider_exit(tb_demo_spider_ref_t spider)
{
// check
tb_assert_and_check_return(spider);
// exit homepage
if (spider->homepage) tb_free(spider->homepage);
spider->homepage = tb_null;
// exit filter
if (spider->filter) tb_bloom_filter_exit(spider->filter);
spider->filter = tb_null;
// exit scheduler
if (spider->scheduler) tb_co_scheduler_exit(spider->scheduler);
spider->scheduler = tb_null;
// exit urls
if (spider->urls) tb_co_channel_exit(spider->urls);
spider->urls = tb_null;
// exit spider
tb_free(spider);
}
static tb_demo_spider_ref_t tb_demo_spider_init(tb_char_t const* homepage, tb_char_t const* rootdir)
{
// check
tb_assert_and_check_return_val(homepage, tb_null);
// done
tb_bool_t ok = tb_false;
tb_demo_spider_ref_t spider = tb_null;
do
{
// make spider
spider = tb_malloc0_type(tb_demo_spider_t);
tb_assert_and_check_break(spider);
// init homepage
spider->homepage = tb_strdup(homepage);
tb_assert_and_check_break(spider->homepage);
// init the root directory
if (rootdir) tb_strlcpy(spider->rootdir, rootdir, sizeof(spider->rootdir));
else tb_directory_current(spider->rootdir, sizeof(spider->rootdir));
// init filter
spider->filter = tb_bloom_filter_init(TB_BLOOM_FILTER_PROBABILITY_0_001, 3, TB_DEMO_FILTER_MAXN, tb_element_str(tb_true));
tb_assert_and_check_break(spider->filter);
// init scheduler
spider->scheduler = tb_co_scheduler_init();
tb_assert_and_check_break(spider->scheduler);
// init urls
spider->urls = tb_co_channel_init(TB_DEMO_TASK_MAXN, tb_demo_spider_urls_free, tb_null);
tb_assert_and_check_break(spider->urls);
// trace
tb_trace_i("rootdir: %s, homepage: %s", spider->rootdir, spider->homepage);
// ok
ok = tb_true;
} while (0);
// failed
if (!ok)
{
// exit it
if (spider) tb_demo_spider_exit(spider);
spider = tb_null;
}
// ok?
return spider;
}
static tb_void_t tb_demo_spider_urls_free(tb_pointer_t data, tb_cpointer_t priv)
{
if (data) tb_free(data);
}
static tb_bool_t tb_demo_spider_make_ourl(tb_demo_spider_ref_t spider, tb_char_t const* url, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(spider && url && data && maxn, tb_false);
// skip protocol
tb_char_t* p = (tb_char_t*)url;
if (!tb_strnicmp(p, "http://", 7)) p += 7;
else if (!tb_strnicmp(p, "https://", 8)) p += 8;
// skip space
while (*p && tb_isspace(*p)) p++;
// format ourl
tb_long_t n = tb_snprintf(data, maxn, "%s/%s", spider->rootdir, p);
tb_check_return_val(n > 0 && n < maxn, tb_false);
// no root? append '/'
if (!tb_strchr(p, '/') && !tb_strchr(p, '\\')) data[n++] = '/';
tb_assert_and_check_return_val(n < maxn, tb_false);
// '\\' => '/'
if (data[n - 1] == '/') data[n - 1] = '/';
// directory? append index.html
if (data[n - 1] == '/') n += tb_snprintf(data + n, maxn - n, "%s", "index.html");
tb_assert_and_check_return_val(n > 0 && n < maxn, tb_false);
// end
data[n] = '\0';
// replace '?' => '_'
p = data;
while (*p)
{
// replace
if (*p == '?') *p = '_';
// next
p++;
}
// trace
tb_trace_d("make: %s => %s", url, data);
// ok?
return n > 0? tb_true : tb_false;
}
static tb_bool_t tb_demo_spider_parser_open(tb_demo_spider_parser_ref_t parser, tb_char_t const* iurl, tb_char_t const* ourl)
{
// check
tb_assert_and_check_return_val(parser && parser->stream && iurl && ourl, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// find the .suffix
tb_char_t const* p = tb_strrchr(ourl, '.');
if (p)
{
// not html?
tb_check_break ( tb_stricmp(p, ".css")
&& tb_stricmp(p, ".js")
&& tb_stricmp(p, ".png")
&& tb_stricmp(p, ".jpg")
&& tb_stricmp(p, ".gif")
&& tb_stricmp(p, ".ico")
&& tb_stricmp(p, ".bmp")
&& tb_stricmp(p, ".mp4")
&& tb_stricmp(p, ".mp3")
&& tb_stricmp(p, ".flv")
&& tb_stricmp(p, ".avi")
&& tb_stricmp(p, ".exe")
&& tb_stricmp(p, ".msi")
&& tb_stricmp(p, ".zip")
&& tb_stricmp(p, ".rar")
&& tb_stricmp(p, ".7z"));
}
// ctrl stream
if (!tb_stream_ctrl(parser->stream, TB_STREAM_CTRL_SET_URL, ourl)) break;
// open stream
if (!tb_stream_open(parser->stream)) break;
// the stream size
tb_hong_t size = tb_stream_size(parser->stream);
tb_check_break(size && size < 1024 * 1024);
// prefetch some data
tb_byte_t* data = tb_null;
tb_size_t need = tb_min((tb_size_t)size, 256);
if (!tb_stream_need(parser->stream, &data, need)) break;
// is html?
if ( tb_strnistr((tb_char_t const*)data, need, "")
|| tb_strnistr((tb_char_t const*)data, need, "url, iurl)) break;
// init data
if (!parser->data)
{
parser->maxn = (tb_size_t)size + 1;
parser->data = tb_malloc_bytes(parser->maxn);
}
else if (size + 1 > parser->maxn)
{
parser->maxn = (tb_size_t)size + 1;
parser->data = tb_ralloc_bytes(parser->data, parser->maxn);
}
// read data
if (parser->data && tb_stream_bread(parser->stream, parser->data, (tb_size_t)size))
{
// save data
parser->size = (tb_size_t)size;
parser->offset = 0;
parser->data[size] = '\0';
ok = tb_true;
}
}
} while (0);
// failed?
if (!ok) tb_stream_clos(parser->stream);
// ok?
return ok;
}
static tb_void_t tb_demo_spider_parser_clos(tb_demo_spider_parser_ref_t parser)
{
// check
tb_assert_and_check_return(parser);
// reset data
parser->size = 0;
parser->offset = 0;
// close stream
if (parser->stream) tb_stream_clos(parser->stream);
}
static tb_char_t const* tb_demo_spider_parser_read(tb_demo_spider_parser_ref_t parser)
{
// check
tb_assert_and_check_return_val(parser && parser->data && parser->size, tb_null);
// end?
tb_check_return_val(parser->offset + 16 < parser->size, tb_null);
/* read the next url
*
* ?
*
* * hole: bottom => top * init: * 16(top) * ------------------------- * | | * 14 10 * -------------- ------------- * | | | | * 8(parent) 7 9 3 * --------- * | | * 2 (hole) <= 11(val) * after: * 16(top) * ------------------------- * | | * 14(parent) 10 * -------------- ------------- * | | | | * 11(hole) 7 9 3 * --------- * | | * 2 8 **/ #if 0 static __tb_inline__ tb_void_t tb_heap_push(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t hole, tb_size_t top, tb_cpointer_t item, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(comp); // (hole - 1) / 2: the parent node of the hole // finds the final hole tb_size_t parent = 0; tb_cpointer_t parent_item = tb_null; for (parent = (hole - 1) >> 1; hole > top && (comp(iterator, (parent_item = tb_iterator_item(iterator, head + parent)), item) < 0); parent = (hole - 1) >> 1) { // move item: parent => hole // tb_iterator_copy(iterator, head + parent, item); tb_iterator_copy(iterator, head + hole, parent_item); // move node: hole => parent hole = parent; } // copy item tb_iterator_copy(iterator, head + hole, item); } #endif /*! adjust heap * *
* init: * 16(head) * ------------------------- * | | * (hole) 10 * -------------- ------------- * | | | | * 8(larger) 7 9 3 * --------- ---- * | | | * 2 4 1(tail - 1) * * after: * 16(head) * ------------------------- * | | * 8 10 * -------------- ------------- * | | | | * (hole) 7 9 3 * --------- ---- * | | | * 2 (larger)4 1(tail - 1) * * after: * 16(head) * ------------------------- * | | * 8 10 * -------------- ------------- * | | | | * 4 7 9 3 * --------- ---- * | | | * 2 (hole) 1(tail - 1) * **/ static __tb_inline__ tb_void_t tb_heap_adjust(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t hole, tb_size_t tail, tb_cpointer_t item, tb_iterator_comp_t comp) { // the comparer if (!comp) comp = tb_iterator_comp; #if 0 // save top position tb_size_t top = hole; // 2 * hole + 2: the right child node of hole tb_size_t child = (hole << 1) + 2; for (; child < tail; child = (child << 1) + 2) { // the larger child node if (comp(iterator, tb_iterator_item(iterator, head + child), tb_iterator_item(iterator, head + child - 1)) < 0) child--; // the larger child node => hole tb_iterator_copy(iterator, head + hole, tb_iterator_item(iterator, head + child)); // move the hole down to it's larger child node hole = child; } // no right child node? if (child == tail) { // the last child => hole tb_iterator_copy(iterator, head + hole, tb_iterator_item(iterator, head + tail - 1)); // move hole down to tail hole = tail - 1; } // push item into the hole tb_heap_push(iterator, head, hole, top, item, comp); #else // walk, 2 * hole + 1: the left child node of hole tb_size_t child = (hole << 1) + 1; tb_cpointer_t child_item = tb_null; tb_cpointer_t child_item_r = tb_null; for (; child < tail; child = (child << 1) + 1) { // the larger child node child_item = tb_iterator_item(iterator, head + child); if (child + 1 < tail && comp(iterator, child_item, (child_item_r = tb_iterator_item(iterator, head + child + 1))) < 0) { child++; child_item = child_item_r; } // end? if (comp(iterator, child_item, item) < 0) break; // the larger child node => hole tb_iterator_copy(iterator, head + hole, child_item); // move the hole down to it's larger child node hole = child; } // copy item tb_iterator_copy(iterator, head + hole, item); #endif } /*!make heap * *
* heap: 16 14 10 8 7 9 3 2 4 1 * * 16(head) * ------------------------- * | | * 14 10 * -------------- ------------- * | | | | * 8 (tail / 2 - 1)7 9 3 * --------- ---- * | | | * 2 4 1(tail - 1) **/ static __tb_inline__ tb_void_t tb_heap_make(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t temp = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp); // make tb_size_t hole; tb_size_t bottom = tail - head; for (hole = (bottom >> 1); hole > 0; ) { --hole; // save hole if (step <= sizeof(tb_pointer_t)) temp = tb_iterator_item(iterator, head + hole); else tb_memcpy(temp, tb_iterator_item(iterator, head + hole), step); // reheap top half, bottom to top tb_heap_adjust(iterator, head, hole, bottom, temp, comp); } // free if (temp && step > sizeof(tb_pointer_t)) tb_free(temp); // check tb_assert(tb_heap_check(iterator, head, tail, comp)); } /*!pop the top of heap to last and reheap * *
* 16(head) * ----------------|-------- * | | | * 14 | 10 * -------------- | ------------- * | | | | | * 8 7 | 9 3 * --------- ---- | * | | | | * 2 4 1(last)<----- * (hole) **/ static __tb_inline__ tb_void_t tb_heap_pop0(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t item, tb_iterator_comp_t comp) { // top => last tb_iterator_copy(iterator, tail - 1, tb_iterator_item(iterator, head)); // reheap it tb_heap_adjust(iterator, head, 0, tail - head - 1, item, comp); // check // tb_assert(tb_heap_check(iterator, head, tail - head - 1, comp)); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ /*!the heap sort * *
* init: * * 16(head) * ------------------------- * | | * 4 10 * -------------- ------------- * | | | | * 14 7 9 3 * --------- ---- * | | | * 2 8 1(last - 1) * * make_heap: * * 16(head) * ------------------------- * | | * 14 10 * -------------- ------------- * | | | | * 8 7 9 3 * --------- ---- * | | | * 2 4 1(last - 1) * pop_heap: * * 16(head)-------------------------- * ------------------------- | * | | | * 4 10 | * -------------- ------------- | * | | | | | * 14 7 9 3 | * --------- ---- | * | | | | * 2 8 1(last - 1) <------------------------------ * * (hole)(head) * ------------------------- * | | * 4 10 * -------------- ------------- * | | | | (val = 1) * 14 7 9 3 * --------- ---- * | | | * 2 8 16(last - 1) * * adjust_heap: * 14(head) * ------------------------- * | | * 8 10 * -------------- ------------- * | | | | (val = 1) * 4 7 9 3 * --------- * | | * 2 (hole)(last - 1) 16 * * * push_heap: * 14(head) * ------------------------- * | | * 8 10 * -------------- ------------- * | | | | (val = 1) * 4 7 9 3 | * --------- | * | | /----------------------------------------------- * 2 (hole)(last - 1) 16 * * 14(head) * ------------------------- * | | * 8 10 * -------------- ------------- * | | | | (val = 1) * 4 7 9 3 * --------- * | | * 2 1(last - 1) 16 * * pop_heap adjust_heap push_heap ... * * final_heap: * 1(head) * * * 2 3 * * * 4 7 8 9 * * * 10 14 16 * * result: 1 2 3 4 7 8 9 10 14 16 **/ tb_void_t tb_heap_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS)); tb_check_return(head != tail); // make tb_heap_make(iterator, head, tail, comp); // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t last = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || last); // pop0 ... for (; tail > head + 1; tail--) { // save last if (step <= sizeof(tb_pointer_t)) last = tb_iterator_item(iterator, tail - 1); else tb_memcpy(last, tb_iterator_item(iterator, tail - 1), step); // pop0 tb_heap_pop0(iterator, head, tail, last, comp); } // free if (last && step > sizeof(tb_pointer_t)) tb_free(last); } tb_void_t tb_heap_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp) { tb_heap_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp); } tbox-1.6.7/src/tbox/algorithm/heap_sort.h 0000664 0000000 0000000 00000003373 14142237372 0020402 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file heap_sort.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_HEAP_SORT_H #define TB_ALGORITHM_HEAP_SORT_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the heap sorter, O(nlog(n)) * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param comp the comparer */ tb_void_t tb_heap_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp); /*! the heap sorter for all * * @param iterator the iterator * @param comp the comparer */ tb_void_t tb_heap_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/insert_sort.c 0000664 0000000 0000000 00000007216 14142237372 0020764 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file insert_sort.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "insert_sort.h" #include "../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ /*!the insertion sort * *
* old: 5 2 6 2 8 6 1 * * (hole) * step1: ((5)) 2 6 2 8 6 1 * (next) <= * * (hole) * step2: ((2)) (5) 6 2 8 6 1 * (next) <= * * (hole) * step3: 2 5 ((6)) 2 8 6 1 * (next) <= * * (hole) * step4: 2 ((2)) (5) (6) 8 6 1 * (next) <= * * (hole) * step5: 2 2 5 6 ((8)) 6 1 * (next) <= * * (hole) * step6: 2 2 5 6 ((6)) (8) 1 * (next) <= * * (hole) * step7: ((1)) (2) (2) (5) (6) (6) (8) * (next) **/ tb_void_t tb_insert_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(iterator); tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE)); tb_check_return(head != tail); // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t temp = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp); // the comparer if (!comp) comp = tb_iterator_comp; // sort tb_size_t last, next; for (next = tb_iterator_next(iterator, head); next != tail; next = tb_iterator_next(iterator, next)) { // save next if (step <= sizeof(tb_pointer_t)) temp = tb_iterator_item(iterator, next); else tb_memcpy(temp, tb_iterator_item(iterator, next), step); // look for hole and move elements[hole, next - 1] => [hole + 1, next] for (last = next; last != head && (last = tb_iterator_prev(iterator, last), comp(iterator, temp, tb_iterator_item(iterator, last)) < 0); next = last) tb_iterator_copy(iterator, next, tb_iterator_item(iterator, last)); // item => hole tb_iterator_copy(iterator, next, temp); } // free if (temp && step > sizeof(tb_pointer_t)) tb_free(temp); } tb_void_t tb_insert_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp) { tb_insert_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp); } tbox-1.6.7/src/tbox/algorithm/insert_sort.h 0000664 0000000 0000000 00000003405 14142237372 0020765 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file insert_sort.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_INSERT_SORT_H #define TB_ALGORITHM_INSERT_SORT_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the insert sorter, O(n^2) * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param comp the comparer */ tb_void_t tb_insert_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp); /*! the insert sorter for all * * @param iterator the iterator * @param comp the comparer */ tb_void_t tb_insert_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/predicate.c 0000664 0000000 0000000 00000004001 14142237372 0020336 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file predicate.c * @ingroup algorithm */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "predicate.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_predicate_eq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert(iterator); // item == value? return !tb_iterator_comp(iterator, item, value); } tb_bool_t tb_predicate_le(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert(iterator); // item < value? return tb_iterator_comp(iterator, item, value) < 0; } tb_bool_t tb_predicate_be(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert(iterator); // item > value? return tb_iterator_comp(iterator, item, value) > 0; } tb_bool_t tb_predicate_leq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert(iterator); // item <= value? return tb_iterator_comp(iterator, item, value) <= 0; } tb_bool_t tb_predicate_beq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert(iterator); // item >= value? return tb_iterator_comp(iterator, item, value) >= 0; } tbox-1.6.7/src/tbox/algorithm/predicate.h 0000664 0000000 0000000 00000007124 14142237372 0020354 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file predicate.h * @ingroup algorithm */ #ifndef TB_ALGORITHM_PREDICATE_H #define TB_ALGORITHM_PREDICATE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the predicate ref type * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * * @return tb_true or tb_false */ typedef tb_bool_t (*tb_predicate_ref_t)(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value); /*! the predicate break ref type * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * @param is_break is break now? * * @return tb_true or tb_false */ typedef tb_bool_t (*tb_predicate_break_ref_t)(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value, tb_bool_t* is_break); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the predicate: if (item == value)? * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * * @return tb_true or tb_false */ tb_bool_t tb_predicate_eq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value); /*! the predicate: if (item < value)? * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * * @return tb_true or tb_false */ tb_bool_t tb_predicate_le(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value); /*! the predicate: if (item > value)? * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * * @return tb_true or tb_false */ tb_bool_t tb_predicate_be(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value); /*! the predicate: if (item <= value)? * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * * @return tb_true or tb_false */ tb_bool_t tb_predicate_leq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value); /*! the predicate: if (item >= value)? * * @param iterator the iterator * @param item the inner item of the container * @param value the outer value * * @return tb_true or tb_false */ tb_bool_t tb_predicate_beq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/prefix.h 0000664 0000000 0000000 00000001701 14142237372 0017704 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_PREFIX_H #define TB_ALGORITHM_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../container/container.h" #endif tbox-1.6.7/src/tbox/algorithm/quick_sort.c 0000664 0000000 0000000 00000005352 14142237372 0020573 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file quick_sort.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "quick_sort.h" #include "../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_quick_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS)); tb_check_return(head != tail); // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t key = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || key); // the comparer if (!comp) comp = tb_iterator_comp; // hole => key if (step <= sizeof(tb_pointer_t)) key = tb_iterator_item(iterator, head); else tb_memcpy(key, tb_iterator_item(iterator, head), step); // quick_sort tb_size_t l = head; tb_size_t r = tail - 1; while (r > l) { // find: <= for (; r != l; r--) if (comp(iterator, tb_iterator_item(iterator, r), key) < 0) break; if (r != l) { tb_iterator_copy(iterator, l, tb_iterator_item(iterator, r)); l++; } // find: => for (; l != r; l++) if (comp(iterator, tb_iterator_item(iterator, l), key) > 0) break; if (l != r) { tb_iterator_copy(iterator, r, tb_iterator_item(iterator, l)); r--; } } // key => hole tb_iterator_copy(iterator, l, key); // quick_sort [head, hole - 1] tb_quick_sort(iterator, head, l, comp); // quick_sort [hole + 1, tail] tb_quick_sort(iterator, ++l, tail, comp); // free if (key && step > sizeof(tb_pointer_t)) tb_free(key); } tb_void_t tb_quick_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp) { tb_quick_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp); } tbox-1.6.7/src/tbox/algorithm/quick_sort.h 0000664 0000000 0000000 00000003402 14142237372 0020572 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file quick_sort.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_QUICK_SORT_H #define TB_ALGORITHM_QUICK_SORT_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the quick sorter, O(nlog(n)) * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param comp the comparer */ tb_void_t tb_quick_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp); /*! the quick sorter for all * * @param iterator the iterator * @param comp the comparer */ tb_void_t tb_quick_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/remove.c 0000664 0000000 0000000 00000002155 14142237372 0017703 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "remove.h" #include "remove_if.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_remove(tb_iterator_ref_t iterator, tb_cpointer_t value) { // remove it tb_remove_if(iterator, tb_predicate_eq, value); } tbox-1.6.7/src/tbox/algorithm/remove.h 0000664 0000000 0000000 00000002675 14142237372 0017717 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_REMOVE_H #define TB_ALGORITHM_REMOVE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! remove items * * @param iterator the iterator * @param value the value of the predicate */ tb_void_t tb_remove(tb_iterator_ref_t iterator, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/remove_first.c 0000664 0000000 0000000 00000002213 14142237372 0021105 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove_first.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "remove_first.h" #include "remove_first_if.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_remove_first(tb_iterator_ref_t iterator, tb_cpointer_t value) { // remove it tb_remove_first_if(iterator, tb_predicate_eq, value); } tbox-1.6.7/src/tbox/algorithm/remove_first.h 0000664 0000000 0000000 00000002736 14142237372 0021124 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove_first.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_REMOVE_FIRST_H #define TB_ALGORITHM_REMOVE_FIRST_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! remove the first item * * @param iterator the iterator * @param value the value of the predicate */ tb_void_t tb_remove_first(tb_iterator_ref_t iterator, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/remove_first_if.c 0000664 0000000 0000000 00000003341 14142237372 0021566 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove_first_if.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "remove_first_if.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_remove_first_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value) { // check tb_assert_and_check_return(iterator && pred); // the iterator mode tb_size_t mode = tb_iterator_mode(iterator); tb_assert_and_check_return((mode & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return(!(mode & TB_ITERATOR_MODE_READONLY)); // done tb_size_t itor = tb_iterator_head(iterator); while (itor != tb_iterator_tail(iterator)) { // done predicate if (pred(iterator, tb_iterator_item(iterator, itor), value)) { // remove it tb_iterator_remove(iterator, itor); break; } // next itor = tb_iterator_next(iterator, itor); } } tbox-1.6.7/src/tbox/algorithm/remove_first_if.h 0000664 0000000 0000000 00000003121 14142237372 0021567 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove_first_if.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_REMOVE_FIRST_IF_H #define TB_ALGORITHM_REMOVE_FIRST_IF_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "predicate.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! remove the first item if pred(item, value) * * @param iterator the iterator * @param pred the predicate * @param value the value of the predicate */ tb_void_t tb_remove_first_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/remove_if.c 0000664 0000000 0000000 00000010734 14142237372 0020363 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove_if.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "remove_if.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t tb_remove_if_pred(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value, tb_bool_t* pbreak) { // check tb_value_ref_t tuple = (tb_value_ref_t)value; tb_assert(tuple && tuple[0].cptr); // the pred return ((tb_predicate_ref_t)tuple[0].cptr)(iterator, item, tuple[1].cptr); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_remove_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value) { // init tuple tb_value_t tuple[2]; tuple[0].cptr = pred; tuple[1].cptr = value; // remove it tb_remove_if_until(iterator, tb_remove_if_pred, tuple); } tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_t pred, tb_cpointer_t value) { // check tb_assert_and_check_return(iterator && pred); // the iterator mode tb_size_t mode = tb_iterator_mode(iterator); tb_assert_and_check_return((mode & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return(!(mode & TB_ITERATOR_MODE_READONLY)); // done tb_size_t next; tb_size_t size = 0; tb_bool_t ok = tb_false; tb_bool_t need = tb_false; tb_bool_t is_break = tb_false; tb_size_t prev = tb_iterator_tail(iterator); tb_size_t itor = tb_iterator_head(iterator); tb_size_t base = tb_iterator_tail(iterator); tb_bool_t bmutable = (mode & TB_ITERATOR_MODE_MUTABLE)? tb_true : tb_false; while (itor != tb_iterator_tail(iterator)) { // save next next = tb_iterator_next(iterator, itor); // done predicate ok = pred(iterator, tb_iterator_item(iterator, itor), value, &is_break); // remove it? if (ok) { // is the first removed item? if (!need) { // save the removed range base base = prev; // need remove items need = tb_true; } // update size size++; } // the removed range have been passed or stop or end? if (!ok || next == tb_iterator_tail(iterator)) { // need remove items? if (need) { // check tb_assert(size); // the previous tail tb_size_t prev_tail = tb_iterator_tail(iterator); // remove items tb_iterator_nremove(iterator, base, ok? next : itor, size); // reset state need = tb_false; size = 0; // is the mutable iterator? if (bmutable) { // update itor prev = base; // the body items are removed? if (base != prev_tail) itor = tb_iterator_next(iterator, base); // the head items are removed? else itor = tb_iterator_head(iterator); // the last item be not removed? skip the last walked item if (!ok) { prev = itor; itor = tb_iterator_next(iterator, itor); } // break? tb_check_break(!is_break); // continue? continue ; } } // break? tb_check_break(!is_break); } // next prev = itor; itor = next; } } tbox-1.6.7/src/tbox/algorithm/remove_if.h 0000664 0000000 0000000 00000003570 14142237372 0020370 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file remove_if.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_REMOVE_IF_H #define TB_ALGORITHM_REMOVE_IF_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "predicate.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! remove items if pred(item, value) * * @param iterator the iterator * @param pred the predicate * @param value the value of the predicate */ tb_void_t tb_remove_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value); /*! remove items if pred(item, value, &is_break) until is_break == tb_true * * @param iterator the iterator * @param pred the predicate with break * @param value the value of the predicate */ tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_t pred, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/rfind.c 0000664 0000000 0000000 00000002424 14142237372 0017507 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rfind.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "rfind.h" #include "rfind_if.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_rfind(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value) { return tb_rfind_if(iterator, head, tail, tb_predicate_eq, value); } tb_size_t tb_rfind_all(tb_iterator_ref_t iterator, tb_cpointer_t value) { return tb_rfind_all_if(iterator, tb_predicate_eq, value); } tbox-1.6.7/src/tbox/algorithm/rfind.h 0000664 0000000 0000000 00000003645 14142237372 0017522 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rfind.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_RFIND_H #define TB_ALGORITHM_RFIND_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! reverse find item * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param value the value of the predicate * * @return the iterator itor, return tb_iterator_tail(iterator) if not found */ tb_size_t tb_rfind(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value); /*! reverse find item for all * * @param iterator the iterator * @param value the value of the predicate * * @return the iterator itor, return tb_iterator_tail(iterator) if not found */ tb_size_t tb_rfind_all(tb_iterator_ref_t iterator, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/rfind_if.c 0000664 0000000 0000000 00000003557 14142237372 0020175 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rfind_if.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "rfind_if.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_rfind_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value) { // check tb_assert_and_check_return_val(pred && iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE), tb_iterator_tail(iterator)); // null? tb_check_return_val(head != tail, tb_iterator_tail(iterator)); // find tb_size_t itor = tail; tb_bool_t find = tb_false; do { // the previous item itor = tb_iterator_prev(iterator, itor); // comp if ((find = pred(iterator, tb_iterator_item(iterator, itor), value))) break; } while (itor != head); // ok? return find? itor : tb_iterator_tail(iterator); } tb_size_t tb_rfind_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value) { return tb_rfind_if(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), pred, value); } tbox-1.6.7/src/tbox/algorithm/rfind_if.h 0000664 0000000 0000000 00000004153 14142237372 0020173 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rfind_if.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_RFIND_IF_H #define TB_ALGORITHM_RFIND_IF_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "predicate.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! reverse find item if pred(item, value) * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param pred the predicate * @param value the value of the predicate * * @return the iterator itor, return tb_iterator_tail(iterator) if not found */ tb_size_t tb_rfind_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value); /*! reverse find item for all if pred(item, value) * * @param iterator the iterator * @param pred the predicate * @param value the value of the predicate * * @return the iterator itor, return tb_iterator_tail(iterator) if not found */ tb_size_t tb_rfind_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/rfor.h 0000664 0000000 0000000 00000006154 14142237372 0017366 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rfor.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_RFOR_H #define TB_ALGORITHM_RFOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /*! for items using iterator * * @code * tb_rfor(tb_char_t*, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator) * { * tb_trace_d("item: %s", item); * } * * tb_rfor(tb_size_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator) * { * tb_trace_d("item: %lu", item); * } * * tb_rfor(tb_hash_map_item_ref_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator) * { * if (item) tb_trace_d("item: %p => %p", item->name, item->data); * } * @endcode */ #define tb_rfor(type, item, head, tail, iterator) \ /* iterator */ \ tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \ tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \ /* init */ \ type item; \ tb_size_t item##_itor; \ tb_size_t item##_head = head; \ tb_size_t item##_tail = tail; \ /* walk */ \ if (item##_iterator && item##_head != item##_tail) \ for ( item##_itor = tb_iterator_prev(item##_iterator, item##_tail); \ item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), item##_itor = item##_itor != item##_head? item##_itor : item##_tail, 1); \ item##_itor = item##_itor != item##_tail? tb_iterator_prev(item##_iterator, item##_itor) : item##_tail) /*! for all items using iterator * * @code * * tb_rfor_all(tb_char_t*, item, iterator) * { * tb_trace_d("item: %s", item); * } * * tb_rfor_all(tb_size_t, item, iterator) * { * tb_trace_d("item: %lu", item); * } * * tb_rfor_all(tb_hash_map_item_ref_t, item, iterator) * { * if (item) tb_trace_d("item: %p => %p", item->name, item->data); * } * @endcode */ #define tb_rfor_all(type, item, iterator) \ tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \ tb_rfor(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all) #endif tbox-1.6.7/src/tbox/algorithm/rfor_if.h 0000664 0000000 0000000 00000006325 14142237372 0020044 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rfor_if.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_RFOR_IF_H #define TB_ALGORITHM_RFOR_IF_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /*! for items using iterator * * @code * tb_rfor_if(tb_char_t*, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item) * { * tb_trace_d("item: %s", item); * } * * tb_rfor_if(tb_size_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item > 10) * { * tb_trace_d("item: %lu", item); * } * * tb_rfor_if(tb_hash_map_item_ref_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item != tb_null) * { * tb_trace_d("item: %p => %p", item->name, item->data); * } * @endcode */ #define tb_rfor_if(type, item, head, tail, iterator, cond) \ /* iterator */ \ tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \ tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \ /* init */ \ type item; \ tb_size_t item##_itor; \ tb_size_t item##_head = head; \ tb_size_t item##_tail = tail; \ /* walk */ \ if (item##_iterator && item##_head != item##_tail) \ for ( item##_itor = tb_iterator_prev(item##_iterator, item##_tail); \ item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), item##_itor = item##_itor != item##_head? item##_itor : item##_tail, 1); \ item##_itor = item##_itor != item##_tail? tb_iterator_prev(item##_iterator, item##_itor) : item##_tail) if ((cond)) /*! for all items using iterator * * @code * * tb_rfor_all(tb_char_t*, item, iterator, item) * { * tb_trace_d("item: %s", item); * } * * tb_rfor_all(tb_size_t, item, iterator, itme > 10) * { * tb_trace_d("item: %lu", item); * } * * tb_rfor_all(tb_hash_map_item_ref_t, item, iterator, item != tb_null) * { * tb_trace_d("item: %p => %p", item->name, item->data); * } * @endcode */ #define tb_rfor_all_if(type, item, iterator, cond) \ tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \ tb_rfor_if(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all, cond) #endif tbox-1.6.7/src/tbox/algorithm/rwalk.c 0000664 0000000 0000000 00000003276 14142237372 0017533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rwalk.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "rwalk.h" #include "rfor.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_rwalk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_rwalk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE) && func, 0); // null? tb_check_return_val(head != tail, 0); // rwalk tb_size_t count = 0; tb_rfor (tb_pointer_t, item, head, tail, iterator) { // done if (!func(iterator, item, priv)) break; // count++ count++; } // ok? return count; } tb_size_t tb_rwalk_all(tb_iterator_ref_t iterator, tb_rwalk_func_t func, tb_cpointer_t priv) { return tb_rwalk(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), func, priv); } tbox-1.6.7/src/tbox/algorithm/rwalk.h 0000664 0000000 0000000 00000004234 14142237372 0017533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file rwalk.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_RWALK_H #define TB_ALGORITHM_RWALK_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the reverse walk func type typedef tb_bool_t (*tb_rwalk_func_t)(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the reverse walker * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param func the walker func * @param priv the func private data * * @return the item count */ tb_size_t tb_rwalk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_rwalk_func_t func, tb_cpointer_t priv); /*! the reverse walker for all * * @param iterator the iterator * @param func the walker func * @param priv the func private data * * @return the item count */ tb_size_t tb_rwalk_all(tb_iterator_ref_t iterator, tb_rwalk_func_t func, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/sort.c 0000664 0000000 0000000 00000004207 14142237372 0017375 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file sort.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "sort.h" #include "distance.h" #include "heap_sort.h" #include "quick_sort.h" #include "insert_sort.h" #include "bubble_sort.h" #include "../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(iterator); // no elements? tb_check_return(head != tail); // readonly? tb_assert_and_check_return(!(tb_iterator_mode(iterator) & TB_ITERATOR_MODE_READONLY)); #ifdef TB_CONFIG_MICRO_ENABLE // random access iterator? tb_assert_and_check_return(tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS); // sort it tb_quick_sort(iterator, head, tail, comp); #else // random access iterator? if (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS) { if (tb_distance(iterator, head, tail) > 100000) tb_heap_sort(iterator, head, tail, comp); else tb_quick_sort(iterator, head, tail, comp); //!< @note the recursive stack size is limit } else tb_insert_sort(iterator, head, tail, comp); #endif } tb_void_t tb_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp) { tb_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp); } tbox-1.6.7/src/tbox/algorithm/sort.h 0000664 0000000 0000000 00000003314 14142237372 0017400 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file sort.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_SORT_H #define TB_ALGORITHM_SORT_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the sorter * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param comp the comparer */ tb_void_t tb_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp); /*! the sorter for all * * @param iterator the iterator * @param comp the comparer */ tb_void_t tb_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/algorithm/walk.c 0000664 0000000 0000000 00000003264 14142237372 0017346 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file walk.c * @ingroup algorithm * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "walk.h" #include "for.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_walk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD) && func, 0); // null? tb_check_return_val(head != tail, 0); // walk tb_size_t count = 0; tb_for (tb_pointer_t, item, head, tail, iterator) { // done if (!func(iterator, item, priv)) break; // count++ count++; } // ok? return count; } tb_size_t tb_walk_all(tb_iterator_ref_t iterator, tb_walk_func_t func, tb_cpointer_t priv) { return tb_walk(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), func, priv); } tbox-1.6.7/src/tbox/algorithm/walk.h 0000664 0000000 0000000 00000004174 14142237372 0017354 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file walk.h * @ingroup algorithm * */ #ifndef TB_ALGORITHM_WALK_H #define TB_ALGORITHM_WALK_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the walk func type typedef tb_bool_t (*tb_walk_func_t)(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the walker * * @param iterator the iterator * @param head the iterator head * @param tail the iterator tail * @param func the walker func * @param priv the func private data * * @return the item count */ tb_size_t tb_walk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_walk_func_t func, tb_cpointer_t priv); /*! the walker for all * * @param iterator the iterator * @param func the walker func * @param priv the func private data * * @return the item count */ tb_size_t tb_walk_all(tb_iterator_ref_t iterator, tb_walk_func_t func, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/charset/ 0000775 0000000 0000000 00000000000 14142237372 0015702 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/charset/ascii.c 0000664 0000000 0000000 00000002764 14142237372 0017147 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file ascii.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_ascii_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_ascii_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { *ch = tb_static_stream_read_u8(sstream); return 1; } tb_long_t tb_charset_ascii_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_ascii_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { if (ch <= 0xff) tb_static_stream_writ_u8(sstream, (tb_uint8_t)ch); return 1; } tbox-1.6.7/src/tbox/charset/charset.c 0000664 0000000 0000000 00000020455 14142237372 0017505 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file charset.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "charset.h" #include "../algorithm/algorithm.h" #include "../platform/impl/charset.h" /* ////////////////////////////////////////////////////////////////////////////////////// * declaration */ // ascii tb_long_t tb_charset_ascii_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_ascii_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // utf8 tb_long_t tb_charset_utf8_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_utf8_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // utf16 tb_long_t tb_charset_utf16_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_utf16_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // utf32 tb_long_t tb_charset_utf32_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_utf32_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // ucs2 tb_long_t tb_charset_ucs2_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_ucs2_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // ucs4 tb_long_t tb_charset_ucs4_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_ucs4_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // gb2312 tb_long_t tb_charset_gb2312_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_gb2312_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); // iso8859 tb_long_t tb_charset_iso8859_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_iso8859_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // the charsets, @note: type & name is sorted static tb_charset_t g_charsets[] = { {TB_CHARSET_TYPE_ASCII, "ascii", tb_charset_ascii_get, tb_charset_ascii_set } , {TB_CHARSET_TYPE_GB2312, "gb2312", tb_charset_gb2312_get, tb_charset_gb2312_set } , {TB_CHARSET_TYPE_GBK, "gbk", tb_charset_gb2312_get, tb_charset_gb2312_set } , {TB_CHARSET_TYPE_ISO8859, "iso8859", tb_charset_iso8859_get, tb_charset_iso8859_set } , {TB_CHARSET_TYPE_UCS2, "ucs3", tb_charset_ucs2_get, tb_charset_ucs2_set } , {TB_CHARSET_TYPE_UCS4, "ucs4", tb_charset_ucs4_get, tb_charset_ucs4_set } , {TB_CHARSET_TYPE_UTF16, "utf16", tb_charset_utf16_get, tb_charset_utf16_set } , {TB_CHARSET_TYPE_UTF32, "utf32", tb_charset_utf32_get, tb_charset_utf32_set } , {TB_CHARSET_TYPE_UTF8, "utf8", tb_charset_utf8_get, tb_charset_utf8_set } }; /* ////////////////////////////////////////////////////////////////////////////////////// * finder */ static tb_long_t tb_charset_comp_by_name(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert(item); // comp return tb_stricmp(((tb_charset_ref_t)item)->name, (tb_char_t const*)name); } static tb_long_t tb_charset_comp_by_type(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t type) { // check tb_assert(item && type); // comp return (tb_long_t)((tb_charset_ref_t)item)->type - (tb_long_t)type; } static tb_charset_ref_t tb_charset_find_by_name(tb_char_t const* name) { // make iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t)); tb_assert_and_check_return_val(iterator, tb_null); // find it by the binary search tb_size_t itor = tb_binary_find_all_if(iterator, tb_charset_comp_by_name, name); // ok? if (itor != tb_iterator_tail(iterator)) return (tb_charset_ref_t)tb_iterator_item(iterator, itor); else return tb_null; } static tb_charset_ref_t tb_charset_find_by_type(tb_size_t type) { // make iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t)); tb_assert_and_check_return_val(iterator, tb_null); // find it by the binary search tb_size_t itor = tb_binary_find_all_if(iterator, tb_charset_comp_by_type, (tb_cpointer_t)TB_CHARSET_TYPE(type)); // ok? if (itor != tb_iterator_tail(iterator)) return (tb_charset_ref_t)tb_iterator_item(iterator, itor); else return tb_null; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_char_t const* tb_charset_name(tb_size_t type) { // find tb_charset_ref_t charset = tb_charset_find_by_type(type); tb_assert_and_check_return_val(charset, tb_null); // type return charset->name; } tb_size_t tb_charset_type(tb_char_t const* name) { // find tb_charset_ref_t charset = tb_charset_find_by_name(name); tb_assert_and_check_return_val(charset, TB_CHARSET_TYPE_NONE); // type return charset->type; } tb_charset_ref_t tb_charset_find(tb_size_t type) { return tb_charset_find_by_type(type); } tb_long_t tb_charset_conv_bst(tb_size_t ftype, tb_size_t ttype, tb_static_stream_ref_t fst, tb_static_stream_ref_t tst) { // check tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && fst && tst, -1); tb_assert_and_check_return_val(tb_static_stream_valid(fst) && tb_static_stream_valid(tst), -1); // attempt to convert charset using the platform implementation tb_long_t ok = tb_charset_conv_impl(ftype, ttype, fst, tst); tb_check_return_val(ok < 0, ok); // init the charset tb_charset_ref_t fr = tb_charset_find_by_type(ftype); tb_charset_ref_t to = tb_charset_find_by_type(ttype); tb_assert_and_check_return_val(fr && to && fr->get && fr->set, -1); // no data? tb_check_return_val(tb_static_stream_left(fst), 0); // big endian? tb_bool_t fbe = !(ftype & TB_CHARSET_TYPE_LE)? tb_true : tb_false; tb_bool_t tbe = !(ttype & TB_CHARSET_TYPE_LE)? tb_true : tb_false; // walk tb_uint32_t ch; tb_byte_t const* tp = tb_static_stream_pos(tst); while (tb_static_stream_left(fst) && tb_static_stream_left(tst)) { // get ucs4 character tb_long_t ok = 0; if ((ok = fr->get(fst, fbe, &ch)) > 0) { // set ucs4 character if (to->set(tst, tbe, ch) < 0) break; } else if (ok < 0) break; } // ok? return tb_static_stream_pos(tst) - tp; } tb_long_t tb_charset_conv_cstr(tb_size_t ftype, tb_size_t ttype, tb_char_t const* cstr, tb_byte_t* data, tb_size_t size) { // check tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && cstr && data && size, -1); // conv return tb_charset_conv_data(ftype, ttype, (tb_byte_t const*)cstr, tb_strlen(cstr), data, size); } tb_long_t tb_charset_conv_data(tb_size_t ftype, tb_size_t ttype, tb_byte_t const* idata, tb_size_t isize, tb_byte_t* odata, tb_size_t osize) { // check tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && idata && isize && odata && osize, -1); // init static stream tb_static_stream_t ist; tb_static_stream_t ost; tb_static_stream_init(&ist, (tb_byte_t*)idata, isize); tb_static_stream_init(&ost, odata, osize); // conv return tb_charset_conv_bst(ftype, ttype, &ist, &ost); } tbox-1.6.7/src/tbox/charset/charset.h 0000664 0000000 0000000 00000012145 14142237372 0017507 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file charset.h * @defgroup charset * @ingroup charset * */ #ifndef TB_CHARSET_H #define TB_CHARSET_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the endian for the charset type #define TB_CHARSET_TYPE_LE (0x0100) #define TB_CHARSET_TYPE_BE (0x0000) #define TB_CHARSET_TYPE_ME (0x0100) #ifdef TB_WORDS_BIGENDIAN # define TB_CHARSET_TYPE_NE (TB_CHARSET_TYPE_BE) #else # define TB_CHARSET_TYPE_NE (TB_CHARSET_TYPE_LE) #endif // type #define TB_CHARSET_TYPE(type) (((type) & ~TB_CHARSET_TYPE_ME)) // ok? #define TB_CHARSET_TYPE_OK(type) (TB_CHARSET_TYPE(type) != TB_CHARSET_TYPE_NONE) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the charset type enum * * @note default: big endian */ typedef enum __tb_charset_type_e { TB_CHARSET_TYPE_NONE = 0x00 , TB_CHARSET_TYPE_ASCII = 0x01 , TB_CHARSET_TYPE_GB2312 = 0x02 , TB_CHARSET_TYPE_GBK = 0x03 , TB_CHARSET_TYPE_ISO8859 = 0x04 , TB_CHARSET_TYPE_UCS2 = 0x05 , TB_CHARSET_TYPE_UCS4 = 0x06 , TB_CHARSET_TYPE_UTF16 = 0x07 , TB_CHARSET_TYPE_UTF32 = 0x08 , TB_CHARSET_TYPE_UTF8 = 0x09 , TB_CHARSET_TYPE_ANSI = 0x10 #ifdef TB_CONFIG_OS_WINDOWS , TB_CHARSET_TYPE_COCP = 0x11 //!< console output cp #endif }tb_charset_type_e; /// the charset type typedef struct __tb_charset_t { /// the charset type tb_size_t type; /// the charset name tb_char_t const* name; /*! get ucs4 character * * return: -1, 0 or 1 * * -1: failed, break it * 0: no character, skip and continue it * 1: ok, continue it */ tb_long_t (*get)(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); /*! set ucs4 character * * return: -1, 0 or 1 * * -1: failed, break it * 0: no character, skip and continue it * 1: ok, continue it */ tb_long_t (*set)(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); }tb_charset_t; /// the charset ref type typedef tb_charset_t* tb_charset_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the charset name * * @param type the charset type * * @return the charset name */ tb_char_t const* tb_charset_name(tb_size_t type); /*! the charset type * * @param name the charset name * * @return the charset type */ tb_size_t tb_charset_type(tb_char_t const* name); /*! find the charset * * @param type the charset type * * @return the charset pointer */ tb_charset_ref_t tb_charset_find(tb_size_t type); /*! convert charset from static stream * * @param ftype the from charset * @param ttype the to charset * @param fst the from stream * @param tst the to stream * * @return the converted bytes for output or -1 */ tb_long_t tb_charset_conv_bst(tb_size_t ftype, tb_size_t ttype, tb_static_stream_ref_t fst, tb_static_stream_ref_t tst); /*! convert charset from cstr * * @param ftype the from charset * @param ttype the to charset * @param cstr the cstr * @param data the data * @param size the size * * @return the converted bytes for output or -1 */ tb_long_t tb_charset_conv_cstr(tb_size_t ftype, tb_size_t ttype, tb_char_t const* cstr, tb_byte_t* data, tb_size_t size); /*! convert charset from data * * @param ftype the from charset * @param ttype the to charset * @param idata the idata * @param isize the isize * @param odata the odata * @param osize the osize * * @return the converted bytes for output or -1 */ tb_long_t tb_charset_conv_data(tb_size_t ftype, tb_size_t ttype, tb_byte_t const* idata, tb_size_t isize, tb_byte_t* odata, tb_size_t osize); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/charset/gb2312.c 0000664 0000000 0000000 00000006775 14142237372 0016765 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file gb2312.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" #include "gb2312.g" /* ////////////////////////////////////////////////////////////////////////////////////// * helper */ static tb_uint32_t tb_charset_gb2312_from_ucs4(tb_uint32_t ch) { // is ascii? if (ch <= 0x7f) return ch; // find the gb2312 character tb_long_t left = 0; tb_long_t right = (g_charset_ucs4_to_gb2312_table_size / sizeof(g_charset_ucs4_to_gb2312_table_data[0])) - 1; while (left <= right) { // the middle character tb_long_t mid = (left + right) >> 1; tb_uint16_t mid_ucs4 = g_charset_ucs4_to_gb2312_table_data[mid][0]; // find it? if (mid_ucs4 == ch) return g_charset_ucs4_to_gb2312_table_data[mid][1]; if (ch > mid_ucs4) left = mid + 1; else right = mid - 1; } return 0; } static tb_uint32_t tb_charset_gb2312_to_ucs4(tb_uint32_t ch) { // is ascii? if (ch <= 0x7f) return ch; // is gb2312? if (ch >= 0xa1a1 && ch <= 0xf7fe) return g_charset_gb2312_to_ucs4_table_data[ch - 0xa1a1]; else return 0; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_gb2312_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_gb2312_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { // init tb_byte_t const* p = tb_static_stream_pos(sstream); tb_size_t n = tb_static_stream_left(sstream); if (*p <= 0x7f) { // not enough? break it tb_check_return_val(n, -1); // get character *ch = tb_static_stream_read_u8(sstream); } else { // not enough? break it tb_check_return_val(n > 1, -1); // get character *ch = tb_charset_gb2312_to_ucs4(be? tb_static_stream_read_u16_be(sstream) : tb_static_stream_read_u16_le(sstream)); } // ok return 1; } tb_long_t tb_charset_gb2312_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_gb2312_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { // init tb_size_t n = tb_static_stream_left(sstream); // character ch = tb_charset_gb2312_from_ucs4(ch); if (ch <= 0x7f) { // not enough? break it tb_check_return_val(n, -1); // set character tb_static_stream_writ_u8(sstream, ch & 0xff); } else { // not enough? break it tb_check_return_val(n > 1, 0); // set character if (be) tb_static_stream_writ_u16_be(sstream, ch & 0xffff); else tb_static_stream_writ_u16_le(sstream, ch & 0xffff); } // ok return 1; } tbox-1.6.7/src/tbox/charset/gb2312.g 0000664 0000000 0000000 00001714456 14142237372 0016774 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-2020, TBOOX Open Source Group. * * @author ruki * @file gb2312.g * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #ifdef TB_COMPILER_IS_MSVC # pragma warning(disable: 4819) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ static tb_uint16_t g_charset_gb2312_to_ucs4_table_data[] = { 0x3000 , 0x3001 , 0x3002 , 0x30fb , 0x02c9 , 0x02c7 , 0x00a8 , 0x3003 , 0x3005 , 0x2015 , 0xff5e , 0x2016 , 0x2026 , 0x2018 , 0x2019 , 0x201c , 0x201d , 0x3014 , 0x3015 , 0x3008 , 0x3009 , 0x300a , 0x300b , 0x300c , 0x300d , 0x300e , 0x300f , 0x3016 , 0x3017 , 0x3010 , 0x3011 , 0x00b1 , 0x00d7 , 0x00f7 , 0x2236 , 0x2227 , 0x2228 , 0x2211 , 0x220f , 0x222a , 0x2229 , 0x2208 , 0x2237 , 0x221a , 0x22a5 , 0x2225 , 0x2220 , 0x2312 , 0x2299 , 0x222b , 0x222e , 0x2261 , 0x224c , 0x2248 , 0x223d , 0x221d , 0x2260 , 0x226e , 0x226f , 0x2264 , 0x2265 , 0x221e , 0x2235 , 0x2234 , 0x2642 , 0x2640 , 0x00b0 , 0x2032 , 0x2033 , 0x2103 , 0xff04 , 0x00a4 , 0xffe0 , 0xffe1 , 0x2030 , 0x00a7 , 0x2116 , 0x2606 , 0x2605 , 0x25cb , 0x25cf , 0x25ce , 0x25c7 , 0x25c6 , 0x25a1 , 0x25a0 , 0x25b3 , 0x25b2 , 0x203b , 0x2192 , 0x2190 , 0x2191 , 0x2193 , 0x3013 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x2488 , 0x2489 , 0x248a , 0x248b , 0x248c , 0x248d , 0x248e , 0x248f , 0x2490 , 0x2491 , 0x2492 , 0x2493 , 0x2494 , 0x2495 , 0x2496 , 0x2497 , 0x2498 , 0x2499 , 0x249a , 0x249b , 0x2474 , 0x2475 , 0x2476 , 0x2477 , 0x2478 , 0x2479 , 0x247a , 0x247b , 0x247c , 0x247d , 0x247e , 0x247f , 0x2480 , 0x2481 , 0x2482 , 0x2483 , 0x2484 , 0x2485 , 0x2486 , 0x2487 , 0x2460 , 0x2461 , 0x2462 , 0x2463 , 0x2464 , 0x2465 , 0x2466 , 0x2467 , 0x2468 , 0x2469 , 0x0000 , 0x0000 , 0x3220 , 0x3221 , 0x3222 , 0x3223 , 0x3224 , 0x3225 , 0x3226 , 0x3227 , 0x3228 , 0x3229 , 0x0000 , 0x0000 , 0x2160 , 0x2161 , 0x2162 , 0x2163 , 0x2164 , 0x2165 , 0x2166 , 0x2167 , 0x2168 , 0x2169 , 0x216a , 0x216b , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0xff01 , 0xff02 , 0xff03 , 0xffe5 , 0xff05 , 0xff06 , 0xff07 , 0xff08 , 0xff09 , 0xff0a , 0xff0b , 0xff0c , 0xff0d , 0xff0e , 0xff0f , 0xff10 , 0xff11 , 0xff12 , 0xff13 , 0xff14 , 0xff15 , 0xff16 , 0xff17 , 0xff18 , 0xff19 , 0xff1a , 0xff1b , 0xff1c , 0xff1d , 0xff1e , 0xff1f , 0xff20 , 0xff21 , 0xff22 , 0xff23 , 0xff24 , 0xff25 , 0xff26 , 0xff27 , 0xff28 , 0xff29 , 0xff2a , 0xff2b , 0xff2c , 0xff2d , 0xff2e , 0xff2f , 0xff30 , 0xff31 , 0xff32 , 0xff33 , 0xff34 , 0xff35 , 0xff36 , 0xff37 , 0xff38 , 0xff39 , 0xff3a , 0xff3b , 0xff3c , 0xff3d , 0xff3e , 0xff3f , 0xff40 , 0xff41 , 0xff42 , 0xff43 , 0xff44 , 0xff45 , 0xff46 , 0xff47 , 0xff48 , 0xff49 , 0xff4a , 0xff4b , 0xff4c , 0xff4d , 0xff4e , 0xff4f , 0xff50 , 0xff51 , 0xff52 , 0xff53 , 0xff54 , 0xff55 , 0xff56 , 0xff57 , 0xff58 , 0xff59 , 0xff5a , 0xff5b , 0xff5c , 0xff5d , 0xffe3 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x3041 , 0x3042 , 0x3043 , 0x3044 , 0x3045 , 0x3046 , 0x3047 , 0x3048 , 0x3049 , 0x304a , 0x304b , 0x304c , 0x304d , 0x304e , 0x304f , 0x3050 , 0x3051 , 0x3052 , 0x3053 , 0x3054 , 0x3055 , 0x3056 , 0x3057 , 0x3058 , 0x3059 , 0x305a , 0x305b , 0x305c , 0x305d , 0x305e , 0x305f , 0x3060 , 0x3061 , 0x3062 , 0x3063 , 0x3064 , 0x3065 , 0x3066 , 0x3067 , 0x3068 , 0x3069 , 0x306a , 0x306b , 0x306c , 0x306d , 0x306e , 0x306f , 0x3070 , 0x3071 , 0x3072 , 0x3073 , 0x3074 , 0x3075 , 0x3076 , 0x3077 , 0x3078 , 0x3079 , 0x307a , 0x307b , 0x307c , 0x307d , 0x307e , 0x307f , 0x3080 , 0x3081 , 0x3082 , 0x3083 , 0x3084 , 0x3085 , 0x3086 , 0x3087 , 0x3088 , 0x3089 , 0x308a , 0x308b , 0x308c , 0x308d , 0x308e , 0x308f , 0x3090 , 0x3091 , 0x3092 , 0x3093 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x30a1 , 0x30a2 , 0x30a3 , 0x30a4 , 0x30a5 , 0x30a6 , 0x30a7 , 0x30a8 , 0x30a9 , 0x30aa , 0x30ab , 0x30ac , 0x30ad , 0x30ae , 0x30af , 0x30b0 , 0x30b1 , 0x30b2 , 0x30b3 , 0x30b4 , 0x30b5 , 0x30b6 , 0x30b7 , 0x30b8 , 0x30b9 , 0x30ba , 0x30bb , 0x30bc , 0x30bd , 0x30be , 0x30bf , 0x30c0 , 0x30c1 , 0x30c2 , 0x30c3 , 0x30c4 , 0x30c5 , 0x30c6 , 0x30c7 , 0x30c8 , 0x30c9 , 0x30ca , 0x30cb , 0x30cc , 0x30cd , 0x30ce , 0x30cf , 0x30d0 , 0x30d1 , 0x30d2 , 0x30d3 , 0x30d4 , 0x30d5 , 0x30d6 , 0x30d7 , 0x30d8 , 0x30d9 , 0x30da , 0x30db , 0x30dc , 0x30dd , 0x30de , 0x30df , 0x30e0 , 0x30e1 , 0x30e2 , 0x30e3 , 0x30e4 , 0x30e5 , 0x30e6 , 0x30e7 , 0x30e8 , 0x30e9 , 0x30ea , 0x30eb , 0x30ec , 0x30ed , 0x30ee , 0x30ef , 0x30f0 , 0x30f1 , 0x30f2 , 0x30f3 , 0x30f4 , 0x30f5 , 0x30f6 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0391 , 0x0392 , 0x0393 , 0x0394 , 0x0395 , 0x0396 , 0x0397 , 0x0398 , 0x0399 , 0x039a , 0x039b , 0x039c , 0x039d , 0x039e , 0x039f , 0x03a0 , 0x03a1 , 0x03a3 , 0x03a4 , 0x03a5 , 0x03a6 , 0x03a7 , 0x03a8 , 0x03a9 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x03b1 , 0x03b2 , 0x03b3 , 0x03b4 , 0x03b5 , 0x03b6 , 0x03b7 , 0x03b8 , 0x03b9 , 0x03ba , 0x03bb , 0x03bc , 0x03bd , 0x03be , 0x03bf , 0x03c0 , 0x03c1 , 0x03c3 , 0x03c4 , 0x03c5 , 0x03c6 , 0x03c7 , 0x03c8 , 0x03c9 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0410 , 0x0411 , 0x0412 , 0x0413 , 0x0414 , 0x0415 , 0x0401 , 0x0416 , 0x0417 , 0x0418 , 0x0419 , 0x041a , 0x041b , 0x041c , 0x041d , 0x041e , 0x041f , 0x0420 , 0x0421 , 0x0422 , 0x0423 , 0x0424 , 0x0425 , 0x0426 , 0x0427 , 0x0428 , 0x0429 , 0x042a , 0x042b , 0x042c , 0x042d , 0x042e , 0x042f , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0430 , 0x0431 , 0x0432 , 0x0433 , 0x0434 , 0x0435 , 0x0451 , 0x0436 , 0x0437 , 0x0438 , 0x0439 , 0x043a , 0x043b , 0x043c , 0x043d , 0x043e , 0x043f , 0x0440 , 0x0441 , 0x0442 , 0x0443 , 0x0444 , 0x0445 , 0x0446 , 0x0447 , 0x0448 , 0x0449 , 0x044a , 0x044b , 0x044c , 0x044d , 0x044e , 0x044f , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0101 , 0x00e1 , 0x01ce , 0x00e0 , 0x0113 , 0x00e9 , 0x011b , 0x00e8 , 0x012b , 0x00ed , 0x01d0 , 0x00ec , 0x014d , 0x00f3 , 0x01d2 , 0x00f2 , 0x016b , 0x00fa , 0x01d4 , 0x00f9 , 0x01d6 , 0x01d8 , 0x01da , 0x01dc , 0x00fc , 0x00ea , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x3105 , 0x3106 , 0x3107 , 0x3108 , 0x3109 , 0x310a , 0x310b , 0x310c , 0x310d , 0x310e , 0x310f , 0x3110 , 0x3111 , 0x3112 , 0x3113 , 0x3114 , 0x3115 , 0x3116 , 0x3117 , 0x3118 , 0x3119 , 0x311a , 0x311b , 0x311c , 0x311d , 0x311e , 0x311f , 0x3120 , 0x3121 , 0x3122 , 0x3123 , 0x3124 , 0x3125 , 0x3126 , 0x3127 , 0x3128 , 0x3129 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x2500 , 0x2501 , 0x2502 , 0x2503 , 0x2504 , 0x2505 , 0x2506 , 0x2507 , 0x2508 , 0x2509 , 0x250a , 0x250b , 0x250c , 0x250d , 0x250e , 0x250f , 0x2510 , 0x2511 , 0x2512 , 0x2513 , 0x2514 , 0x2515 , 0x2516 , 0x2517 , 0x2518 , 0x2519 , 0x251a , 0x251b , 0x251c , 0x251d , 0x251e , 0x251f , 0x2520 , 0x2521 , 0x2522 , 0x2523 , 0x2524 , 0x2525 , 0x2526 , 0x2527 , 0x2528 , 0x2529 , 0x252a , 0x252b , 0x252c , 0x252d , 0x252e , 0x252f , 0x2530 , 0x2531 , 0x2532 , 0x2533 , 0x2534 , 0x2535 , 0x2536 , 0x2537 , 0x2538 , 0x2539 , 0x253a , 0x253b , 0x253c , 0x253d , 0x253e , 0x253f , 0x2540 , 0x2541 , 0x2542 , 0x2543 , 0x2544 , 0x2545 , 0x2546 , 0x2547 , 0x2548 , 0x2549 , 0x254a , 0x254b , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x554a , 0x963f , 0x57c3 , 0x6328 , 0x54ce , 0x5509 , 0x54c0 , 0x7691 , 0x764c , 0x853c , 0x77ee , 0x827e , 0x788d , 0x7231 , 0x9698 , 0x978d , 0x6c28 , 0x5b89 , 0x4ffa , 0x6309 , 0x6697 , 0x5cb8 , 0x80fa , 0x6848 , 0x80ae , 0x6602 , 0x76ce , 0x51f9 , 0x6556 , 0x71ac , 0x7ff1 , 0x8884 , 0x50b2 , 0x5965 , 0x61ca , 0x6fb3 , 0x82ad , 0x634c , 0x6252 , 0x53ed , 0x5427 , 0x7b06 , 0x516b , 0x75a4 , 0x5df4 , 0x62d4 , 0x8dcb , 0x9776 , 0x628a , 0x8019 , 0x575d , 0x9738 , 0x7f62 , 0x7238 , 0x767d , 0x67cf , 0x767e , 0x6446 , 0x4f70 , 0x8d25 , 0x62dc , 0x7a17 , 0x6591 , 0x73ed , 0x642c , 0x6273 , 0x822c , 0x9881 , 0x677f , 0x7248 , 0x626e , 0x62cc , 0x4f34 , 0x74e3 , 0x534a , 0x529e , 0x7eca , 0x90a6 , 0x5e2e , 0x6886 , 0x699c , 0x8180 , 0x7ed1 , 0x68d2 , 0x78c5 , 0x868c , 0x9551 , 0x508d , 0x8c24 , 0x82de , 0x80de , 0x5305 , 0x8912 , 0x5265 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x8584 , 0x96f9 , 0x4fdd , 0x5821 , 0x9971 , 0x5b9d , 0x62b1 , 0x62a5 , 0x66b4 , 0x8c79 , 0x9c8d , 0x7206 , 0x676f , 0x7891 , 0x60b2 , 0x5351 , 0x5317 , 0x8f88 , 0x80cc , 0x8d1d , 0x94a1 , 0x500d , 0x72c8 , 0x5907 , 0x60eb , 0x7119 , 0x88ab , 0x5954 , 0x82ef , 0x672c , 0x7b28 , 0x5d29 , 0x7ef7 , 0x752d , 0x6cf5 , 0x8e66 , 0x8ff8 , 0x903c , 0x9f3b , 0x6bd4 , 0x9119 , 0x7b14 , 0x5f7c , 0x78a7 , 0x84d6 , 0x853d , 0x6bd5 , 0x6bd9 , 0x6bd6 , 0x5e01 , 0x5e87 , 0x75f9 , 0x95ed , 0x655d , 0x5f0a , 0x5fc5 , 0x8f9f , 0x58c1 , 0x81c2 , 0x907f , 0x965b , 0x97ad , 0x8fb9 , 0x7f16 , 0x8d2c , 0x6241 , 0x4fbf , 0x53d8 , 0x535e , 0x8fa8 , 0x8fa9 , 0x8fab , 0x904d , 0x6807 , 0x5f6a , 0x8198 , 0x8868 , 0x9cd6 , 0x618b , 0x522b , 0x762a , 0x5f6c , 0x658c , 0x6fd2 , 0x6ee8 , 0x5bbe , 0x6448 , 0x5175 , 0x51b0 , 0x67c4 , 0x4e19 , 0x79c9 , 0x997c , 0x70b3 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x75c5 , 0x5e76 , 0x73bb , 0x83e0 , 0x64ad , 0x62e8 , 0x94b5 , 0x6ce2 , 0x535a , 0x52c3 , 0x640f , 0x94c2 , 0x7b94 , 0x4f2f , 0x5e1b , 0x8236 , 0x8116 , 0x818a , 0x6e24 , 0x6cca , 0x9a73 , 0x6355 , 0x535c , 0x54fa , 0x8865 , 0x57e0 , 0x4e0d , 0x5e03 , 0x6b65 , 0x7c3f , 0x90e8 , 0x6016 , 0x64e6 , 0x731c , 0x88c1 , 0x6750 , 0x624d , 0x8d22 , 0x776c , 0x8e29 , 0x91c7 , 0x5f69 , 0x83dc , 0x8521 , 0x9910 , 0x53c2 , 0x8695 , 0x6b8b , 0x60ed , 0x60e8 , 0x707f , 0x82cd , 0x8231 , 0x4ed3 , 0x6ca7 , 0x85cf , 0x64cd , 0x7cd9 , 0x69fd , 0x66f9 , 0x8349 , 0x5395 , 0x7b56 , 0x4fa7 , 0x518c , 0x6d4b , 0x5c42 , 0x8e6d , 0x63d2 , 0x53c9 , 0x832c , 0x8336 , 0x67e5 , 0x78b4 , 0x643d , 0x5bdf , 0x5c94 , 0x5dee , 0x8be7 , 0x62c6 , 0x67f4 , 0x8c7a , 0x6400 , 0x63ba , 0x8749 , 0x998b , 0x8c17 , 0x7f20 , 0x94f2 , 0x4ea7 , 0x9610 , 0x98a4 , 0x660c , 0x7316 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x573a , 0x5c1d , 0x5e38 , 0x957f , 0x507f , 0x80a0 , 0x5382 , 0x655e , 0x7545 , 0x5531 , 0x5021 , 0x8d85 , 0x6284 , 0x949e , 0x671d , 0x5632 , 0x6f6e , 0x5de2 , 0x5435 , 0x7092 , 0x8f66 , 0x626f , 0x64a4 , 0x63a3 , 0x5f7b , 0x6f88 , 0x90f4 , 0x81e3 , 0x8fb0 , 0x5c18 , 0x6668 , 0x5ff1 , 0x6c89 , 0x9648 , 0x8d81 , 0x886c , 0x6491 , 0x79f0 , 0x57ce , 0x6a59 , 0x6210 , 0x5448 , 0x4e58 , 0x7a0b , 0x60e9 , 0x6f84 , 0x8bda , 0x627f , 0x901e , 0x9a8b , 0x79e4 , 0x5403 , 0x75f4 , 0x6301 , 0x5319 , 0x6c60 , 0x8fdf , 0x5f1b , 0x9a70 , 0x803b , 0x9f7f , 0x4f88 , 0x5c3a , 0x8d64 , 0x7fc5 , 0x65a5 , 0x70bd , 0x5145 , 0x51b2 , 0x866b , 0x5d07 , 0x5ba0 , 0x62bd , 0x916c , 0x7574 , 0x8e0c , 0x7a20 , 0x6101 , 0x7b79 , 0x4ec7 , 0x7ef8 , 0x7785 , 0x4e11 , 0x81ed , 0x521d , 0x51fa , 0x6a71 , 0x53a8 , 0x8e87 , 0x9504 , 0x96cf , 0x6ec1 , 0x9664 , 0x695a , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7840 , 0x50a8 , 0x77d7 , 0x6410 , 0x89e6 , 0x5904 , 0x63e3 , 0x5ddd , 0x7a7f , 0x693d , 0x4f20 , 0x8239 , 0x5598 , 0x4e32 , 0x75ae , 0x7a97 , 0x5e62 , 0x5e8a , 0x95ef , 0x521b , 0x5439 , 0x708a , 0x6376 , 0x9524 , 0x5782 , 0x6625 , 0x693f , 0x9187 , 0x5507 , 0x6df3 , 0x7eaf , 0x8822 , 0x6233 , 0x7ef0 , 0x75b5 , 0x8328 , 0x78c1 , 0x96cc , 0x8f9e , 0x6148 , 0x74f7 , 0x8bcd , 0x6b64 , 0x523a , 0x8d50 , 0x6b21 , 0x806a , 0x8471 , 0x56f1 , 0x5306 , 0x4ece , 0x4e1b , 0x51d1 , 0x7c97 , 0x918b , 0x7c07 , 0x4fc3 , 0x8e7f , 0x7be1 , 0x7a9c , 0x6467 , 0x5d14 , 0x50ac , 0x8106 , 0x7601 , 0x7cb9 , 0x6dec , 0x7fe0 , 0x6751 , 0x5b58 , 0x5bf8 , 0x78cb , 0x64ae , 0x6413 , 0x63aa , 0x632b , 0x9519 , 0x642d , 0x8fbe , 0x7b54 , 0x7629 , 0x6253 , 0x5927 , 0x5446 , 0x6b79 , 0x50a3 , 0x6234 , 0x5e26 , 0x6b86 , 0x4ee3 , 0x8d37 , 0x888b , 0x5f85 , 0x902e , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6020 , 0x803d , 0x62c5 , 0x4e39 , 0x5355 , 0x90f8 , 0x63b8 , 0x80c6 , 0x65e6 , 0x6c2e , 0x4f46 , 0x60ee , 0x6de1 , 0x8bde , 0x5f39 , 0x86cb , 0x5f53 , 0x6321 , 0x515a , 0x8361 , 0x6863 , 0x5200 , 0x6363 , 0x8e48 , 0x5012 , 0x5c9b , 0x7977 , 0x5bfc , 0x5230 , 0x7a3b , 0x60bc , 0x9053 , 0x76d7 , 0x5fb7 , 0x5f97 , 0x7684 , 0x8e6c , 0x706f , 0x767b , 0x7b49 , 0x77aa , 0x51f3 , 0x9093 , 0x5824 , 0x4f4e , 0x6ef4 , 0x8fea , 0x654c , 0x7b1b , 0x72c4 , 0x6da4 , 0x7fdf , 0x5ae1 , 0x62b5 , 0x5e95 , 0x5730 , 0x8482 , 0x7b2c , 0x5e1d , 0x5f1f , 0x9012 , 0x7f14 , 0x98a0 , 0x6382 , 0x6ec7 , 0x7898 , 0x70b9 , 0x5178 , 0x975b , 0x57ab , 0x7535 , 0x4f43 , 0x7538 , 0x5e97 , 0x60e6 , 0x5960 , 0x6dc0 , 0x6bbf , 0x7889 , 0x53fc , 0x96d5 , 0x51cb , 0x5201 , 0x6389 , 0x540a , 0x9493 , 0x8c03 , 0x8dcc , 0x7239 , 0x789f , 0x8776 , 0x8fed , 0x8c0d , 0x53e0 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x4e01 , 0x76ef , 0x53ee , 0x9489 , 0x9876 , 0x9f0e , 0x952d , 0x5b9a , 0x8ba2 , 0x4e22 , 0x4e1c , 0x51ac , 0x8463 , 0x61c2 , 0x52a8 , 0x680b , 0x4f97 , 0x606b , 0x51bb , 0x6d1e , 0x515c , 0x6296 , 0x6597 , 0x9661 , 0x8c46 , 0x9017 , 0x75d8 , 0x90fd , 0x7763 , 0x6bd2 , 0x728a , 0x72ec , 0x8bfb , 0x5835 , 0x7779 , 0x8d4c , 0x675c , 0x9540 , 0x809a , 0x5ea6 , 0x6e21 , 0x5992 , 0x7aef , 0x77ed , 0x953b , 0x6bb5 , 0x65ad , 0x7f0e , 0x5806 , 0x5151 , 0x961f , 0x5bf9 , 0x58a9 , 0x5428 , 0x8e72 , 0x6566 , 0x987f , 0x56e4 , 0x949d , 0x76fe , 0x9041 , 0x6387 , 0x54c6 , 0x591a , 0x593a , 0x579b , 0x8eb2 , 0x6735 , 0x8dfa , 0x8235 , 0x5241 , 0x60f0 , 0x5815 , 0x86fe , 0x5ce8 , 0x9e45 , 0x4fc4 , 0x989d , 0x8bb9 , 0x5a25 , 0x6076 , 0x5384 , 0x627c , 0x904f , 0x9102 , 0x997f , 0x6069 , 0x800c , 0x513f , 0x8033 , 0x5c14 , 0x9975 , 0x6d31 , 0x4e8c , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x8d30 , 0x53d1 , 0x7f5a , 0x7b4f , 0x4f10 , 0x4e4f , 0x9600 , 0x6cd5 , 0x73d0 , 0x85e9 , 0x5e06 , 0x756a , 0x7ffb , 0x6a0a , 0x77fe , 0x9492 , 0x7e41 , 0x51e1 , 0x70e6 , 0x53cd , 0x8fd4 , 0x8303 , 0x8d29 , 0x72af , 0x996d , 0x6cdb , 0x574a , 0x82b3 , 0x65b9 , 0x80aa , 0x623f , 0x9632 , 0x59a8 , 0x4eff , 0x8bbf , 0x7eba , 0x653e , 0x83f2 , 0x975e , 0x5561 , 0x98de , 0x80a5 , 0x532a , 0x8bfd , 0x5420 , 0x80ba , 0x5e9f , 0x6cb8 , 0x8d39 , 0x82ac , 0x915a , 0x5429 , 0x6c1b , 0x5206 , 0x7eb7 , 0x575f , 0x711a , 0x6c7e , 0x7c89 , 0x594b , 0x4efd , 0x5fff , 0x6124 , 0x7caa , 0x4e30 , 0x5c01 , 0x67ab , 0x8702 , 0x5cf0 , 0x950b , 0x98ce , 0x75af , 0x70fd , 0x9022 , 0x51af , 0x7f1d , 0x8bbd , 0x5949 , 0x51e4 , 0x4f5b , 0x5426 , 0x592b , 0x6577 , 0x80a4 , 0x5b75 , 0x6276 , 0x62c2 , 0x8f90 , 0x5e45 , 0x6c1f , 0x7b26 , 0x4f0f , 0x4fd8 , 0x670d , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6d6e , 0x6daa , 0x798f , 0x88b1 , 0x5f17 , 0x752b , 0x629a , 0x8f85 , 0x4fef , 0x91dc , 0x65a7 , 0x812f , 0x8151 , 0x5e9c , 0x8150 , 0x8d74 , 0x526f , 0x8986 , 0x8d4b , 0x590d , 0x5085 , 0x4ed8 , 0x961c , 0x7236 , 0x8179 , 0x8d1f , 0x5bcc , 0x8ba3 , 0x9644 , 0x5987 , 0x7f1a , 0x5490 , 0x5676 , 0x560e , 0x8be5 , 0x6539 , 0x6982 , 0x9499 , 0x76d6 , 0x6e89 , 0x5e72 , 0x7518 , 0x6746 , 0x67d1 , 0x7aff , 0x809d , 0x8d76 , 0x611f , 0x79c6 , 0x6562 , 0x8d63 , 0x5188 , 0x521a , 0x94a2 , 0x7f38 , 0x809b , 0x7eb2 , 0x5c97 , 0x6e2f , 0x6760 , 0x7bd9 , 0x768b , 0x9ad8 , 0x818f , 0x7f94 , 0x7cd5 , 0x641e , 0x9550 , 0x7a3f , 0x544a , 0x54e5 , 0x6b4c , 0x6401 , 0x6208 , 0x9e3d , 0x80f3 , 0x7599 , 0x5272 , 0x9769 , 0x845b , 0x683c , 0x86e4 , 0x9601 , 0x9694 , 0x94ec , 0x4e2a , 0x5404 , 0x7ed9 , 0x6839 , 0x8ddf , 0x8015 , 0x66f4 , 0x5e9a , 0x7fb9 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x57c2 , 0x803f , 0x6897 , 0x5de5 , 0x653b , 0x529f , 0x606d , 0x9f9a , 0x4f9b , 0x8eac , 0x516c , 0x5bab , 0x5f13 , 0x5de9 , 0x6c5e , 0x62f1 , 0x8d21 , 0x5171 , 0x94a9 , 0x52fe , 0x6c9f , 0x82df , 0x72d7 , 0x57a2 , 0x6784 , 0x8d2d , 0x591f , 0x8f9c , 0x83c7 , 0x5495 , 0x7b8d , 0x4f30 , 0x6cbd , 0x5b64 , 0x59d1 , 0x9f13 , 0x53e4 , 0x86ca , 0x9aa8 , 0x8c37 , 0x80a1 , 0x6545 , 0x987e , 0x56fa , 0x96c7 , 0x522e , 0x74dc , 0x5250 , 0x5be1 , 0x6302 , 0x8902 , 0x4e56 , 0x62d0 , 0x602a , 0x68fa , 0x5173 , 0x5b98 , 0x51a0 , 0x89c2 , 0x7ba1 , 0x9986 , 0x7f50 , 0x60ef , 0x704c , 0x8d2f , 0x5149 , 0x5e7f , 0x901b , 0x7470 , 0x89c4 , 0x572d , 0x7845 , 0x5f52 , 0x9f9f , 0x95fa , 0x8f68 , 0x9b3c , 0x8be1 , 0x7678 , 0x6842 , 0x67dc , 0x8dea , 0x8d35 , 0x523d , 0x8f8a , 0x6eda , 0x68cd , 0x9505 , 0x90ed , 0x56fd , 0x679c , 0x88f9 , 0x8fc7 , 0x54c8 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9ab8 , 0x5b69 , 0x6d77 , 0x6c26 , 0x4ea5 , 0x5bb3 , 0x9a87 , 0x9163 , 0x61a8 , 0x90af , 0x97e9 , 0x542b , 0x6db5 , 0x5bd2 , 0x51fd , 0x558a , 0x7f55 , 0x7ff0 , 0x64bc , 0x634d , 0x65f1 , 0x61be , 0x608d , 0x710a , 0x6c57 , 0x6c49 , 0x592f , 0x676d , 0x822a , 0x58d5 , 0x568e , 0x8c6a , 0x6beb , 0x90dd , 0x597d , 0x8017 , 0x53f7 , 0x6d69 , 0x5475 , 0x559d , 0x8377 , 0x83cf , 0x6838 , 0x79be , 0x548c , 0x4f55 , 0x5408 , 0x76d2 , 0x8c89 , 0x9602 , 0x6cb3 , 0x6db8 , 0x8d6b , 0x8910 , 0x9e64 , 0x8d3a , 0x563f , 0x9ed1 , 0x75d5 , 0x5f88 , 0x72e0 , 0x6068 , 0x54fc , 0x4ea8 , 0x6a2a , 0x8861 , 0x6052 , 0x8f70 , 0x54c4 , 0x70d8 , 0x8679 , 0x9e3f , 0x6d2a , 0x5b8f , 0x5f18 , 0x7ea2 , 0x5589 , 0x4faf , 0x7334 , 0x543c , 0x539a , 0x5019 , 0x540e , 0x547c , 0x4e4e , 0x5ffd , 0x745a , 0x58f6 , 0x846b , 0x80e1 , 0x8774 , 0x72d0 , 0x7cca , 0x6e56 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5f27 , 0x864e , 0x552c , 0x62a4 , 0x4e92 , 0x6caa , 0x6237 , 0x82b1 , 0x54d7 , 0x534e , 0x733e , 0x6ed1 , 0x753b , 0x5212 , 0x5316 , 0x8bdd , 0x69d0 , 0x5f8a , 0x6000 , 0x6dee , 0x574f , 0x6b22 , 0x73af , 0x6853 , 0x8fd8 , 0x7f13 , 0x6362 , 0x60a3 , 0x5524 , 0x75ea , 0x8c62 , 0x7115 , 0x6da3 , 0x5ba6 , 0x5e7b , 0x8352 , 0x614c , 0x9ec4 , 0x78fa , 0x8757 , 0x7c27 , 0x7687 , 0x51f0 , 0x60f6 , 0x714c , 0x6643 , 0x5e4c , 0x604d , 0x8c0e , 0x7070 , 0x6325 , 0x8f89 , 0x5fbd , 0x6062 , 0x86d4 , 0x56de , 0x6bc1 , 0x6094 , 0x6167 , 0x5349 , 0x60e0 , 0x6666 , 0x8d3f , 0x79fd , 0x4f1a , 0x70e9 , 0x6c47 , 0x8bb3 , 0x8bf2 , 0x7ed8 , 0x8364 , 0x660f , 0x5a5a , 0x9b42 , 0x6d51 , 0x6df7 , 0x8c41 , 0x6d3b , 0x4f19 , 0x706b , 0x83b7 , 0x6216 , 0x60d1 , 0x970d , 0x8d27 , 0x7978 , 0x51fb , 0x573e , 0x57fa , 0x673a , 0x7578 , 0x7a3d , 0x79ef , 0x7b95 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x808c , 0x9965 , 0x8ff9 , 0x6fc0 , 0x8ba5 , 0x9e21 , 0x59ec , 0x7ee9 , 0x7f09 , 0x5409 , 0x6781 , 0x68d8 , 0x8f91 , 0x7c4d , 0x96c6 , 0x53ca , 0x6025 , 0x75be , 0x6c72 , 0x5373 , 0x5ac9 , 0x7ea7 , 0x6324 , 0x51e0 , 0x810a , 0x5df1 , 0x84df , 0x6280 , 0x5180 , 0x5b63 , 0x4f0e , 0x796d , 0x5242 , 0x60b8 , 0x6d4e , 0x5bc4 , 0x5bc2 , 0x8ba1 , 0x8bb0 , 0x65e2 , 0x5fcc , 0x9645 , 0x5993 , 0x7ee7 , 0x7eaa , 0x5609 , 0x67b7 , 0x5939 , 0x4f73 , 0x5bb6 , 0x52a0 , 0x835a , 0x988a , 0x8d3e , 0x7532 , 0x94be , 0x5047 , 0x7a3c , 0x4ef7 , 0x67b6 , 0x9a7e , 0x5ac1 , 0x6b7c , 0x76d1 , 0x575a , 0x5c16 , 0x7b3a , 0x95f4 , 0x714e , 0x517c , 0x80a9 , 0x8270 , 0x5978 , 0x7f04 , 0x8327 , 0x68c0 , 0x67ec , 0x78b1 , 0x7877 , 0x62e3 , 0x6361 , 0x7b80 , 0x4fed , 0x526a , 0x51cf , 0x8350 , 0x69db , 0x9274 , 0x8df5 , 0x8d31 , 0x89c1 , 0x952e , 0x7bad , 0x4ef6 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5065 , 0x8230 , 0x5251 , 0x996f , 0x6e10 , 0x6e85 , 0x6da7 , 0x5efa , 0x50f5 , 0x59dc , 0x5c06 , 0x6d46 , 0x6c5f , 0x7586 , 0x848b , 0x6868 , 0x5956 , 0x8bb2 , 0x5320 , 0x9171 , 0x964d , 0x8549 , 0x6912 , 0x7901 , 0x7126 , 0x80f6 , 0x4ea4 , 0x90ca , 0x6d47 , 0x9a84 , 0x5a07 , 0x56bc , 0x6405 , 0x94f0 , 0x77eb , 0x4fa5 , 0x811a , 0x72e1 , 0x89d2 , 0x997a , 0x7f34 , 0x7ede , 0x527f , 0x6559 , 0x9175 , 0x8f7f , 0x8f83 , 0x53eb , 0x7a96 , 0x63ed , 0x63a5 , 0x7686 , 0x79f8 , 0x8857 , 0x9636 , 0x622a , 0x52ab , 0x8282 , 0x6854 , 0x6770 , 0x6377 , 0x776b , 0x7aed , 0x6d01 , 0x7ed3 , 0x89e3 , 0x59d0 , 0x6212 , 0x85c9 , 0x82a5 , 0x754c , 0x501f , 0x4ecb , 0x75a5 , 0x8beb , 0x5c4a , 0x5dfe , 0x7b4b , 0x65a4 , 0x91d1 , 0x4eca , 0x6d25 , 0x895f , 0x7d27 , 0x9526 , 0x4ec5 , 0x8c28 , 0x8fdb , 0x9773 , 0x664b , 0x7981 , 0x8fd1 , 0x70ec , 0x6d78 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5c3d , 0x52b2 , 0x8346 , 0x5162 , 0x830e , 0x775b , 0x6676 , 0x9cb8 , 0x4eac , 0x60ca , 0x7cbe , 0x7cb3 , 0x7ecf , 0x4e95 , 0x8b66 , 0x666f , 0x9888 , 0x9759 , 0x5883 , 0x656c , 0x955c , 0x5f84 , 0x75c9 , 0x9756 , 0x7adf , 0x7ade , 0x51c0 , 0x70af , 0x7a98 , 0x63ea , 0x7a76 , 0x7ea0 , 0x7396 , 0x97ed , 0x4e45 , 0x7078 , 0x4e5d , 0x9152 , 0x53a9 , 0x6551 , 0x65e7 , 0x81fc , 0x8205 , 0x548e , 0x5c31 , 0x759a , 0x97a0 , 0x62d8 , 0x72d9 , 0x75bd , 0x5c45 , 0x9a79 , 0x83ca , 0x5c40 , 0x5480 , 0x77e9 , 0x4e3e , 0x6cae , 0x805a , 0x62d2 , 0x636e , 0x5de8 , 0x5177 , 0x8ddd , 0x8e1e , 0x952f , 0x4ff1 , 0x53e5 , 0x60e7 , 0x70ac , 0x5267 , 0x6350 , 0x9e43 , 0x5a1f , 0x5026 , 0x7737 , 0x5377 , 0x7ee2 , 0x6485 , 0x652b , 0x6289 , 0x6398 , 0x5014 , 0x7235 , 0x89c9 , 0x51b3 , 0x8bc0 , 0x7edd , 0x5747 , 0x83cc , 0x94a7 , 0x519b , 0x541b , 0x5cfb , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x4fca , 0x7ae3 , 0x6d5a , 0x90e1 , 0x9a8f , 0x5580 , 0x5496 , 0x5361 , 0x54af , 0x5f00 , 0x63e9 , 0x6977 , 0x51ef , 0x6168 , 0x520a , 0x582a , 0x52d8 , 0x574e , 0x780d , 0x770b , 0x5eb7 , 0x6177 , 0x7ce0 , 0x625b , 0x6297 , 0x4ea2 , 0x7095 , 0x8003 , 0x62f7 , 0x70e4 , 0x9760 , 0x5777 , 0x82db , 0x67ef , 0x68f5 , 0x78d5 , 0x9897 , 0x79d1 , 0x58f3 , 0x54b3 , 0x53ef , 0x6e34 , 0x514b , 0x523b , 0x5ba2 , 0x8bfe , 0x80af , 0x5543 , 0x57a6 , 0x6073 , 0x5751 , 0x542d , 0x7a7a , 0x6050 , 0x5b54 , 0x63a7 , 0x62a0 , 0x53e3 , 0x6263 , 0x5bc7 , 0x67af , 0x54ed , 0x7a9f , 0x82e6 , 0x9177 , 0x5e93 , 0x88e4 , 0x5938 , 0x57ae , 0x630e , 0x8de8 , 0x80ef , 0x5757 , 0x7b77 , 0x4fa9 , 0x5feb , 0x5bbd , 0x6b3e , 0x5321 , 0x7b50 , 0x72c2 , 0x6846 , 0x77ff , 0x7736 , 0x65f7 , 0x51b5 , 0x4e8f , 0x76d4 , 0x5cbf , 0x7aa5 , 0x8475 , 0x594e , 0x9b41 , 0x5080 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9988 , 0x6127 , 0x6e83 , 0x5764 , 0x6606 , 0x6346 , 0x56f0 , 0x62ec , 0x6269 , 0x5ed3 , 0x9614 , 0x5783 , 0x62c9 , 0x5587 , 0x8721 , 0x814a , 0x8fa3 , 0x5566 , 0x83b1 , 0x6765 , 0x8d56 , 0x84dd , 0x5a6a , 0x680f , 0x62e6 , 0x7bee , 0x9611 , 0x5170 , 0x6f9c , 0x8c30 , 0x63fd , 0x89c8 , 0x61d2 , 0x7f06 , 0x70c2 , 0x6ee5 , 0x7405 , 0x6994 , 0x72fc , 0x5eca , 0x90ce , 0x6717 , 0x6d6a , 0x635e , 0x52b3 , 0x7262 , 0x8001 , 0x4f6c , 0x59e5 , 0x916a , 0x70d9 , 0x6d9d , 0x52d2 , 0x4e50 , 0x96f7 , 0x956d , 0x857e , 0x78ca , 0x7d2f , 0x5121 , 0x5792 , 0x64c2 , 0x808b , 0x7c7b , 0x6cea , 0x68f1 , 0x695e , 0x51b7 , 0x5398 , 0x68a8 , 0x7281 , 0x9ece , 0x7bf1 , 0x72f8 , 0x79bb , 0x6f13 , 0x7406 , 0x674e , 0x91cc , 0x9ca4 , 0x793c , 0x8389 , 0x8354 , 0x540f , 0x6817 , 0x4e3d , 0x5389 , 0x52b1 , 0x783e , 0x5386 , 0x5229 , 0x5088 , 0x4f8b , 0x4fd0 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x75e2 , 0x7acb , 0x7c92 , 0x6ca5 , 0x96b6 , 0x529b , 0x7483 , 0x54e9 , 0x4fe9 , 0x8054 , 0x83b2 , 0x8fde , 0x9570 , 0x5ec9 , 0x601c , 0x6d9f , 0x5e18 , 0x655b , 0x8138 , 0x94fe , 0x604b , 0x70bc , 0x7ec3 , 0x7cae , 0x51c9 , 0x6881 , 0x7cb1 , 0x826f , 0x4e24 , 0x8f86 , 0x91cf , 0x667e , 0x4eae , 0x8c05 , 0x64a9 , 0x804a , 0x50da , 0x7597 , 0x71ce , 0x5be5 , 0x8fbd , 0x6f66 , 0x4e86 , 0x6482 , 0x9563 , 0x5ed6 , 0x6599 , 0x5217 , 0x88c2 , 0x70c8 , 0x52a3 , 0x730e , 0x7433 , 0x6797 , 0x78f7 , 0x9716 , 0x4e34 , 0x90bb , 0x9cde , 0x6dcb , 0x51db , 0x8d41 , 0x541d , 0x62ce , 0x73b2 , 0x83f1 , 0x96f6 , 0x9f84 , 0x94c3 , 0x4f36 , 0x7f9a , 0x51cc , 0x7075 , 0x9675 , 0x5cad , 0x9886 , 0x53e6 , 0x4ee4 , 0x6e9c , 0x7409 , 0x69b4 , 0x786b , 0x998f , 0x7559 , 0x5218 , 0x7624 , 0x6d41 , 0x67f3 , 0x516d , 0x9f99 , 0x804b , 0x5499 , 0x7b3c , 0x7abf , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9686 , 0x5784 , 0x62e2 , 0x9647 , 0x697c , 0x5a04 , 0x6402 , 0x7bd3 , 0x6f0f , 0x964b , 0x82a6 , 0x5362 , 0x9885 , 0x5e90 , 0x7089 , 0x63b3 , 0x5364 , 0x864f , 0x9c81 , 0x9e93 , 0x788c , 0x9732 , 0x8def , 0x8d42 , 0x9e7f , 0x6f5e , 0x7984 , 0x5f55 , 0x9646 , 0x622e , 0x9a74 , 0x5415 , 0x94dd , 0x4fa3 , 0x65c5 , 0x5c65 , 0x5c61 , 0x7f15 , 0x8651 , 0x6c2f , 0x5f8b , 0x7387 , 0x6ee4 , 0x7eff , 0x5ce6 , 0x631b , 0x5b6a , 0x6ee6 , 0x5375 , 0x4e71 , 0x63a0 , 0x7565 , 0x62a1 , 0x8f6e , 0x4f26 , 0x4ed1 , 0x6ca6 , 0x7eb6 , 0x8bba , 0x841d , 0x87ba , 0x7f57 , 0x903b , 0x9523 , 0x7ba9 , 0x9aa1 , 0x88f8 , 0x843d , 0x6d1b , 0x9a86 , 0x7edc , 0x5988 , 0x9ebb , 0x739b , 0x7801 , 0x8682 , 0x9a6c , 0x9a82 , 0x561b , 0x5417 , 0x57cb , 0x4e70 , 0x9ea6 , 0x5356 , 0x8fc8 , 0x8109 , 0x7792 , 0x9992 , 0x86ee , 0x6ee1 , 0x8513 , 0x66fc , 0x6162 , 0x6f2b , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x8c29 , 0x8292 , 0x832b , 0x76f2 , 0x6c13 , 0x5fd9 , 0x83bd , 0x732b , 0x8305 , 0x951a , 0x6bdb , 0x77db , 0x94c6 , 0x536f , 0x8302 , 0x5192 , 0x5e3d , 0x8c8c , 0x8d38 , 0x4e48 , 0x73ab , 0x679a , 0x6885 , 0x9176 , 0x9709 , 0x7164 , 0x6ca1 , 0x7709 , 0x5a92 , 0x9541 , 0x6bcf , 0x7f8e , 0x6627 , 0x5bd0 , 0x59b9 , 0x5a9a , 0x95e8 , 0x95f7 , 0x4eec , 0x840c , 0x8499 , 0x6aac , 0x76df , 0x9530 , 0x731b , 0x68a6 , 0x5b5f , 0x772f , 0x919a , 0x9761 , 0x7cdc , 0x8ff7 , 0x8c1c , 0x5f25 , 0x7c73 , 0x79d8 , 0x89c5 , 0x6ccc , 0x871c , 0x5bc6 , 0x5e42 , 0x68c9 , 0x7720 , 0x7ef5 , 0x5195 , 0x514d , 0x52c9 , 0x5a29 , 0x7f05 , 0x9762 , 0x82d7 , 0x63cf , 0x7784 , 0x85d0 , 0x79d2 , 0x6e3a , 0x5e99 , 0x5999 , 0x8511 , 0x706d , 0x6c11 , 0x62bf , 0x76bf , 0x654f , 0x60af , 0x95fd , 0x660e , 0x879f , 0x9e23 , 0x94ed , 0x540d , 0x547d , 0x8c2c , 0x6478 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6479 , 0x8611 , 0x6a21 , 0x819c , 0x78e8 , 0x6469 , 0x9b54 , 0x62b9 , 0x672b , 0x83ab , 0x58a8 , 0x9ed8 , 0x6cab , 0x6f20 , 0x5bde , 0x964c , 0x8c0b , 0x725f , 0x67d0 , 0x62c7 , 0x7261 , 0x4ea9 , 0x59c6 , 0x6bcd , 0x5893 , 0x66ae , 0x5e55 , 0x52df , 0x6155 , 0x6728 , 0x76ee , 0x7766 , 0x7267 , 0x7a46 , 0x62ff , 0x54ea , 0x5450 , 0x94a0 , 0x90a3 , 0x5a1c , 0x7eb3 , 0x6c16 , 0x4e43 , 0x5976 , 0x8010 , 0x5948 , 0x5357 , 0x7537 , 0x96be , 0x56ca , 0x6320 , 0x8111 , 0x607c , 0x95f9 , 0x6dd6 , 0x5462 , 0x9981 , 0x5185 , 0x5ae9 , 0x80fd , 0x59ae , 0x9713 , 0x502a , 0x6ce5 , 0x5c3c , 0x62df , 0x4f60 , 0x533f , 0x817b , 0x9006 , 0x6eba , 0x852b , 0x62c8 , 0x5e74 , 0x78be , 0x64b5 , 0x637b , 0x5ff5 , 0x5a18 , 0x917f , 0x9e1f , 0x5c3f , 0x634f , 0x8042 , 0x5b7d , 0x556e , 0x954a , 0x954d , 0x6d85 , 0x60a8 , 0x67e0 , 0x72de , 0x51dd , 0x5b81 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x62e7 , 0x6cde , 0x725b , 0x626d , 0x94ae , 0x7ebd , 0x8113 , 0x6d53 , 0x519c , 0x5f04 , 0x5974 , 0x52aa , 0x6012 , 0x5973 , 0x6696 , 0x8650 , 0x759f , 0x632a , 0x61e6 , 0x7cef , 0x8bfa , 0x54e6 , 0x6b27 , 0x9e25 , 0x6bb4 , 0x85d5 , 0x5455 , 0x5076 , 0x6ca4 , 0x556a , 0x8db4 , 0x722c , 0x5e15 , 0x6015 , 0x7436 , 0x62cd , 0x6392 , 0x724c , 0x5f98 , 0x6e43 , 0x6d3e , 0x6500 , 0x6f58 , 0x76d8 , 0x78d0 , 0x76fc , 0x7554 , 0x5224 , 0x53db , 0x4e53 , 0x5e9e , 0x65c1 , 0x802a , 0x80d6 , 0x629b , 0x5486 , 0x5228 , 0x70ae , 0x888d , 0x8dd1 , 0x6ce1 , 0x5478 , 0x80da , 0x57f9 , 0x88f4 , 0x8d54 , 0x966a , 0x914d , 0x4f69 , 0x6c9b , 0x55b7 , 0x76c6 , 0x7830 , 0x62a8 , 0x70f9 , 0x6f8e , 0x5f6d , 0x84ec , 0x68da , 0x787c , 0x7bf7 , 0x81a8 , 0x670b , 0x9e4f , 0x6367 , 0x78b0 , 0x576f , 0x7812 , 0x9739 , 0x6279 , 0x62ab , 0x5288 , 0x7435 , 0x6bd7 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5564 , 0x813e , 0x75b2 , 0x76ae , 0x5339 , 0x75de , 0x50fb , 0x5c41 , 0x8b6c , 0x7bc7 , 0x504f , 0x7247 , 0x9a97 , 0x98d8 , 0x6f02 , 0x74e2 , 0x7968 , 0x6487 , 0x77a5 , 0x62fc , 0x9891 , 0x8d2b , 0x54c1 , 0x8058 , 0x4e52 , 0x576a , 0x82f9 , 0x840d , 0x5e73 , 0x51ed , 0x74f6 , 0x8bc4 , 0x5c4f , 0x5761 , 0x6cfc , 0x9887 , 0x5a46 , 0x7834 , 0x9b44 , 0x8feb , 0x7c95 , 0x5256 , 0x6251 , 0x94fa , 0x4ec6 , 0x8386 , 0x8461 , 0x83e9 , 0x84b2 , 0x57d4 , 0x6734 , 0x5703 , 0x666e , 0x6d66 , 0x8c31 , 0x66dd , 0x7011 , 0x671f , 0x6b3a , 0x6816 , 0x621a , 0x59bb , 0x4e03 , 0x51c4 , 0x6f06 , 0x67d2 , 0x6c8f , 0x5176 , 0x68cb , 0x5947 , 0x6b67 , 0x7566 , 0x5d0e , 0x8110 , 0x9f50 , 0x65d7 , 0x7948 , 0x7941 , 0x9a91 , 0x8d77 , 0x5c82 , 0x4e5e , 0x4f01 , 0x542f , 0x5951 , 0x780c , 0x5668 , 0x6c14 , 0x8fc4 , 0x5f03 , 0x6c7d , 0x6ce3 , 0x8bab , 0x6390 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6070 , 0x6d3d , 0x7275 , 0x6266 , 0x948e , 0x94c5 , 0x5343 , 0x8fc1 , 0x7b7e , 0x4edf , 0x8c26 , 0x4e7e , 0x9ed4 , 0x94b1 , 0x94b3 , 0x524d , 0x6f5c , 0x9063 , 0x6d45 , 0x8c34 , 0x5811 , 0x5d4c , 0x6b20 , 0x6b49 , 0x67aa , 0x545b , 0x8154 , 0x7f8c , 0x5899 , 0x8537 , 0x5f3a , 0x62a2 , 0x6a47 , 0x9539 , 0x6572 , 0x6084 , 0x6865 , 0x77a7 , 0x4e54 , 0x4fa8 , 0x5de7 , 0x9798 , 0x64ac , 0x7fd8 , 0x5ced , 0x4fcf , 0x7a8d , 0x5207 , 0x8304 , 0x4e14 , 0x602f , 0x7a83 , 0x94a6 , 0x4fb5 , 0x4eb2 , 0x79e6 , 0x7434 , 0x52e4 , 0x82b9 , 0x64d2 , 0x79bd , 0x5bdd , 0x6c81 , 0x9752 , 0x8f7b , 0x6c22 , 0x503e , 0x537f , 0x6e05 , 0x64ce , 0x6674 , 0x6c30 , 0x60c5 , 0x9877 , 0x8bf7 , 0x5e86 , 0x743c , 0x7a77 , 0x79cb , 0x4e18 , 0x90b1 , 0x7403 , 0x6c42 , 0x56da , 0x914b , 0x6cc5 , 0x8d8b , 0x533a , 0x86c6 , 0x66f2 , 0x8eaf , 0x5c48 , 0x9a71 , 0x6e20 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x53d6 , 0x5a36 , 0x9f8b , 0x8da3 , 0x53bb , 0x5708 , 0x98a7 , 0x6743 , 0x919b , 0x6cc9 , 0x5168 , 0x75ca , 0x62f3 , 0x72ac , 0x5238 , 0x529d , 0x7f3a , 0x7094 , 0x7638 , 0x5374 , 0x9e4a , 0x69b7 , 0x786e , 0x96c0 , 0x88d9 , 0x7fa4 , 0x7136 , 0x71c3 , 0x5189 , 0x67d3 , 0x74e4 , 0x58e4 , 0x6518 , 0x56b7 , 0x8ba9 , 0x9976 , 0x6270 , 0x7ed5 , 0x60f9 , 0x70ed , 0x58ec , 0x4ec1 , 0x4eba , 0x5fcd , 0x97e7 , 0x4efb , 0x8ba4 , 0x5203 , 0x598a , 0x7eab , 0x6254 , 0x4ecd , 0x65e5 , 0x620e , 0x8338 , 0x84c9 , 0x8363 , 0x878d , 0x7194 , 0x6eb6 , 0x5bb9 , 0x7ed2 , 0x5197 , 0x63c9 , 0x67d4 , 0x8089 , 0x8339 , 0x8815 , 0x5112 , 0x5b7a , 0x5982 , 0x8fb1 , 0x4e73 , 0x6c5d , 0x5165 , 0x8925 , 0x8f6f , 0x962e , 0x854a , 0x745e , 0x9510 , 0x95f0 , 0x6da6 , 0x82e5 , 0x5f31 , 0x6492 , 0x6d12 , 0x8428 , 0x816e , 0x9cc3 , 0x585e , 0x8d5b , 0x4e09 , 0x53c1 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x4f1e , 0x6563 , 0x6851 , 0x55d3 , 0x4e27 , 0x6414 , 0x9a9a , 0x626b , 0x5ac2 , 0x745f , 0x8272 , 0x6da9 , 0x68ee , 0x50e7 , 0x838e , 0x7802 , 0x6740 , 0x5239 , 0x6c99 , 0x7eb1 , 0x50bb , 0x5565 , 0x715e , 0x7b5b , 0x6652 , 0x73ca , 0x82eb , 0x6749 , 0x5c71 , 0x5220 , 0x717d , 0x886b , 0x95ea , 0x9655 , 0x64c5 , 0x8d61 , 0x81b3 , 0x5584 , 0x6c55 , 0x6247 , 0x7f2e , 0x5892 , 0x4f24 , 0x5546 , 0x8d4f , 0x664c , 0x4e0a , 0x5c1a , 0x88f3 , 0x68a2 , 0x634e , 0x7a0d , 0x70e7 , 0x828d , 0x52fa , 0x97f6 , 0x5c11 , 0x54e8 , 0x90b5 , 0x7ecd , 0x5962 , 0x8d4a , 0x86c7 , 0x820c , 0x820d , 0x8d66 , 0x6444 , 0x5c04 , 0x6151 , 0x6d89 , 0x793e , 0x8bbe , 0x7837 , 0x7533 , 0x547b , 0x4f38 , 0x8eab , 0x6df1 , 0x5a20 , 0x7ec5 , 0x795e , 0x6c88 , 0x5ba1 , 0x5a76 , 0x751a , 0x80be , 0x614e , 0x6e17 , 0x58f0 , 0x751f , 0x7525 , 0x7272 , 0x5347 , 0x7ef3 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7701 , 0x76db , 0x5269 , 0x80dc , 0x5723 , 0x5e08 , 0x5931 , 0x72ee , 0x65bd , 0x6e7f , 0x8bd7 , 0x5c38 , 0x8671 , 0x5341 , 0x77f3 , 0x62fe , 0x65f6 , 0x4ec0 , 0x98df , 0x8680 , 0x5b9e , 0x8bc6 , 0x53f2 , 0x77e2 , 0x4f7f , 0x5c4e , 0x9a76 , 0x59cb , 0x5f0f , 0x793a , 0x58eb , 0x4e16 , 0x67ff , 0x4e8b , 0x62ed , 0x8a93 , 0x901d , 0x52bf , 0x662f , 0x55dc , 0x566c , 0x9002 , 0x4ed5 , 0x4f8d , 0x91ca , 0x9970 , 0x6c0f , 0x5e02 , 0x6043 , 0x5ba4 , 0x89c6 , 0x8bd5 , 0x6536 , 0x624b , 0x9996 , 0x5b88 , 0x5bff , 0x6388 , 0x552e , 0x53d7 , 0x7626 , 0x517d , 0x852c , 0x67a2 , 0x68b3 , 0x6b8a , 0x6292 , 0x8f93 , 0x53d4 , 0x8212 , 0x6dd1 , 0x758f , 0x4e66 , 0x8d4e , 0x5b70 , 0x719f , 0x85af , 0x6691 , 0x66d9 , 0x7f72 , 0x8700 , 0x9ecd , 0x9f20 , 0x5c5e , 0x672f , 0x8ff0 , 0x6811 , 0x675f , 0x620d , 0x7ad6 , 0x5885 , 0x5eb6 , 0x6570 , 0x6f31 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6055 , 0x5237 , 0x800d , 0x6454 , 0x8870 , 0x7529 , 0x5e05 , 0x6813 , 0x62f4 , 0x971c , 0x53cc , 0x723d , 0x8c01 , 0x6c34 , 0x7761 , 0x7a0e , 0x542e , 0x77ac , 0x987a , 0x821c , 0x8bf4 , 0x7855 , 0x6714 , 0x70c1 , 0x65af , 0x6495 , 0x5636 , 0x601d , 0x79c1 , 0x53f8 , 0x4e1d , 0x6b7b , 0x8086 , 0x5bfa , 0x55e3 , 0x56db , 0x4f3a , 0x4f3c , 0x9972 , 0x5df3 , 0x677e , 0x8038 , 0x6002 , 0x9882 , 0x9001 , 0x5b8b , 0x8bbc , 0x8bf5 , 0x641c , 0x8258 , 0x64de , 0x55fd , 0x82cf , 0x9165 , 0x4fd7 , 0x7d20 , 0x901f , 0x7c9f , 0x50f3 , 0x5851 , 0x6eaf , 0x5bbf , 0x8bc9 , 0x8083 , 0x9178 , 0x849c , 0x7b97 , 0x867d , 0x968b , 0x968f , 0x7ee5 , 0x9ad3 , 0x788e , 0x5c81 , 0x7a57 , 0x9042 , 0x96a7 , 0x795f , 0x5b59 , 0x635f , 0x7b0b , 0x84d1 , 0x68ad , 0x5506 , 0x7f29 , 0x7410 , 0x7d22 , 0x9501 , 0x6240 , 0x584c , 0x4ed6 , 0x5b83 , 0x5979 , 0x5854 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x736d , 0x631e , 0x8e4b , 0x8e0f , 0x80ce , 0x82d4 , 0x62ac , 0x53f0 , 0x6cf0 , 0x915e , 0x592a , 0x6001 , 0x6c70 , 0x574d , 0x644a , 0x8d2a , 0x762b , 0x6ee9 , 0x575b , 0x6a80 , 0x75f0 , 0x6f6d , 0x8c2d , 0x8c08 , 0x5766 , 0x6bef , 0x8892 , 0x78b3 , 0x63a2 , 0x53f9 , 0x70ad , 0x6c64 , 0x5858 , 0x642a , 0x5802 , 0x68e0 , 0x819b , 0x5510 , 0x7cd6 , 0x5018 , 0x8eba , 0x6dcc , 0x8d9f , 0x70eb , 0x638f , 0x6d9b , 0x6ed4 , 0x7ee6 , 0x8404 , 0x6843 , 0x9003 , 0x6dd8 , 0x9676 , 0x8ba8 , 0x5957 , 0x7279 , 0x85e4 , 0x817e , 0x75bc , 0x8a8a , 0x68af , 0x5254 , 0x8e22 , 0x9511 , 0x63d0 , 0x9898 , 0x8e44 , 0x557c , 0x4f53 , 0x66ff , 0x568f , 0x60d5 , 0x6d95 , 0x5243 , 0x5c49 , 0x5929 , 0x6dfb , 0x586b , 0x7530 , 0x751c , 0x606c , 0x8214 , 0x8146 , 0x6311 , 0x6761 , 0x8fe2 , 0x773a , 0x8df3 , 0x8d34 , 0x94c1 , 0x5e16 , 0x5385 , 0x542c , 0x70c3 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6c40 , 0x5ef7 , 0x505c , 0x4ead , 0x5ead , 0x633a , 0x8247 , 0x901a , 0x6850 , 0x916e , 0x77b3 , 0x540c , 0x94dc , 0x5f64 , 0x7ae5 , 0x6876 , 0x6345 , 0x7b52 , 0x7edf , 0x75db , 0x5077 , 0x6295 , 0x5934 , 0x900f , 0x51f8 , 0x79c3 , 0x7a81 , 0x56fe , 0x5f92 , 0x9014 , 0x6d82 , 0x5c60 , 0x571f , 0x5410 , 0x5154 , 0x6e4d , 0x56e2 , 0x63a8 , 0x9893 , 0x817f , 0x8715 , 0x892a , 0x9000 , 0x541e , 0x5c6f , 0x81c0 , 0x62d6 , 0x6258 , 0x8131 , 0x9e35 , 0x9640 , 0x9a6e , 0x9a7c , 0x692d , 0x59a5 , 0x62d3 , 0x553e , 0x6316 , 0x54c7 , 0x86d9 , 0x6d3c , 0x5a03 , 0x74e6 , 0x889c , 0x6b6a , 0x5916 , 0x8c4c , 0x5f2f , 0x6e7e , 0x73a9 , 0x987d , 0x4e38 , 0x70f7 , 0x5b8c , 0x7897 , 0x633d , 0x665a , 0x7696 , 0x60cb , 0x5b9b , 0x5a49 , 0x4e07 , 0x8155 , 0x6c6a , 0x738b , 0x4ea1 , 0x6789 , 0x7f51 , 0x5f80 , 0x65fa , 0x671b , 0x5fd8 , 0x5984 , 0x5a01 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5dcd , 0x5fae , 0x5371 , 0x97e6 , 0x8fdd , 0x6845 , 0x56f4 , 0x552f , 0x60df , 0x4e3a , 0x6f4d , 0x7ef4 , 0x82c7 , 0x840e , 0x59d4 , 0x4f1f , 0x4f2a , 0x5c3e , 0x7eac , 0x672a , 0x851a , 0x5473 , 0x754f , 0x80c3 , 0x5582 , 0x9b4f , 0x4f4d , 0x6e2d , 0x8c13 , 0x5c09 , 0x6170 , 0x536b , 0x761f , 0x6e29 , 0x868a , 0x6587 , 0x95fb , 0x7eb9 , 0x543b , 0x7a33 , 0x7d0a , 0x95ee , 0x55e1 , 0x7fc1 , 0x74ee , 0x631d , 0x8717 , 0x6da1 , 0x7a9d , 0x6211 , 0x65a1 , 0x5367 , 0x63e1 , 0x6c83 , 0x5deb , 0x545c , 0x94a8 , 0x4e4c , 0x6c61 , 0x8bec , 0x5c4b , 0x65e0 , 0x829c , 0x68a7 , 0x543e , 0x5434 , 0x6bcb , 0x6b66 , 0x4e94 , 0x6342 , 0x5348 , 0x821e , 0x4f0d , 0x4fae , 0x575e , 0x620a , 0x96fe , 0x6664 , 0x7269 , 0x52ff , 0x52a1 , 0x609f , 0x8bef , 0x6614 , 0x7199 , 0x6790 , 0x897f , 0x7852 , 0x77fd , 0x6670 , 0x563b , 0x5438 , 0x9521 , 0x727a , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7a00 , 0x606f , 0x5e0c , 0x6089 , 0x819d , 0x5915 , 0x60dc , 0x7184 , 0x70ef , 0x6eaa , 0x6c50 , 0x7280 , 0x6a84 , 0x88ad , 0x5e2d , 0x4e60 , 0x5ab3 , 0x559c , 0x94e3 , 0x6d17 , 0x7cfb , 0x9699 , 0x620f , 0x7ec6 , 0x778e , 0x867e , 0x5323 , 0x971e , 0x8f96 , 0x6687 , 0x5ce1 , 0x4fa0 , 0x72ed , 0x4e0b , 0x53a6 , 0x590f , 0x5413 , 0x6380 , 0x9528 , 0x5148 , 0x4ed9 , 0x9c9c , 0x7ea4 , 0x54b8 , 0x8d24 , 0x8854 , 0x8237 , 0x95f2 , 0x6d8e , 0x5f26 , 0x5acc , 0x663e , 0x9669 , 0x73b0 , 0x732e , 0x53bf , 0x817a , 0x9985 , 0x7fa1 , 0x5baa , 0x9677 , 0x9650 , 0x7ebf , 0x76f8 , 0x53a2 , 0x9576 , 0x9999 , 0x7bb1 , 0x8944 , 0x6e58 , 0x4e61 , 0x7fd4 , 0x7965 , 0x8be6 , 0x60f3 , 0x54cd , 0x4eab , 0x9879 , 0x5df7 , 0x6a61 , 0x50cf , 0x5411 , 0x8c61 , 0x8427 , 0x785d , 0x9704 , 0x524a , 0x54ee , 0x56a3 , 0x9500 , 0x6d88 , 0x5bb5 , 0x6dc6 , 0x6653 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5c0f , 0x5b5d , 0x6821 , 0x8096 , 0x5578 , 0x7b11 , 0x6548 , 0x6954 , 0x4e9b , 0x6b47 , 0x874e , 0x978b , 0x534f , 0x631f , 0x643a , 0x90aa , 0x659c , 0x80c1 , 0x8c10 , 0x5199 , 0x68b0 , 0x5378 , 0x87f9 , 0x61c8 , 0x6cc4 , 0x6cfb , 0x8c22 , 0x5c51 , 0x85aa , 0x82af , 0x950c , 0x6b23 , 0x8f9b , 0x65b0 , 0x5ffb , 0x5fc3 , 0x4fe1 , 0x8845 , 0x661f , 0x8165 , 0x7329 , 0x60fa , 0x5174 , 0x5211 , 0x578b , 0x5f62 , 0x90a2 , 0x884c , 0x9192 , 0x5e78 , 0x674f , 0x6027 , 0x59d3 , 0x5144 , 0x51f6 , 0x80f8 , 0x5308 , 0x6c79 , 0x96c4 , 0x718a , 0x4f11 , 0x4fee , 0x7f9e , 0x673d , 0x55c5 , 0x9508 , 0x79c0 , 0x8896 , 0x7ee3 , 0x589f , 0x620c , 0x9700 , 0x865a , 0x5618 , 0x987b , 0x5f90 , 0x8bb8 , 0x84c4 , 0x9157 , 0x53d9 , 0x65ed , 0x5e8f , 0x755c , 0x6064 , 0x7d6e , 0x5a7f , 0x7eea , 0x7eed , 0x8f69 , 0x55a7 , 0x5ba3 , 0x60ac , 0x65cb , 0x7384 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9009 , 0x7663 , 0x7729 , 0x7eda , 0x9774 , 0x859b , 0x5b66 , 0x7a74 , 0x96ea , 0x8840 , 0x52cb , 0x718f , 0x5faa , 0x65ec , 0x8be2 , 0x5bfb , 0x9a6f , 0x5de1 , 0x6b89 , 0x6c5b , 0x8bad , 0x8baf , 0x900a , 0x8fc5 , 0x538b , 0x62bc , 0x9e26 , 0x9e2d , 0x5440 , 0x4e2b , 0x82bd , 0x7259 , 0x869c , 0x5d16 , 0x8859 , 0x6daf , 0x96c5 , 0x54d1 , 0x4e9a , 0x8bb6 , 0x7109 , 0x54bd , 0x9609 , 0x70df , 0x6df9 , 0x76d0 , 0x4e25 , 0x7814 , 0x8712 , 0x5ca9 , 0x5ef6 , 0x8a00 , 0x989c , 0x960e , 0x708e , 0x6cbf , 0x5944 , 0x63a9 , 0x773c , 0x884d , 0x6f14 , 0x8273 , 0x5830 , 0x71d5 , 0x538c , 0x781a , 0x96c1 , 0x5501 , 0x5f66 , 0x7130 , 0x5bb4 , 0x8c1a , 0x9a8c , 0x6b83 , 0x592e , 0x9e2f , 0x79e7 , 0x6768 , 0x626c , 0x4f6f , 0x75a1 , 0x7f8a , 0x6d0b , 0x9633 , 0x6c27 , 0x4ef0 , 0x75d2 , 0x517b , 0x6837 , 0x6f3e , 0x9080 , 0x8170 , 0x5996 , 0x7476 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6447 , 0x5c27 , 0x9065 , 0x7a91 , 0x8c23 , 0x59da , 0x54ac , 0x8200 , 0x836f , 0x8981 , 0x8000 , 0x6930 , 0x564e , 0x8036 , 0x7237 , 0x91ce , 0x51b6 , 0x4e5f , 0x9875 , 0x6396 , 0x4e1a , 0x53f6 , 0x66f3 , 0x814b , 0x591c , 0x6db2 , 0x4e00 , 0x58f9 , 0x533b , 0x63d6 , 0x94f1 , 0x4f9d , 0x4f0a , 0x8863 , 0x9890 , 0x5937 , 0x9057 , 0x79fb , 0x4eea , 0x80f0 , 0x7591 , 0x6c82 , 0x5b9c , 0x59e8 , 0x5f5d , 0x6905 , 0x8681 , 0x501a , 0x5df2 , 0x4e59 , 0x77e3 , 0x4ee5 , 0x827a , 0x6291 , 0x6613 , 0x9091 , 0x5c79 , 0x4ebf , 0x5f79 , 0x81c6 , 0x9038 , 0x8084 , 0x75ab , 0x4ea6 , 0x88d4 , 0x610f , 0x6bc5 , 0x5fc6 , 0x4e49 , 0x76ca , 0x6ea2 , 0x8be3 , 0x8bae , 0x8c0a , 0x8bd1 , 0x5f02 , 0x7ffc , 0x7fcc , 0x7ece , 0x8335 , 0x836b , 0x56e0 , 0x6bb7 , 0x97f3 , 0x9634 , 0x59fb , 0x541f , 0x94f6 , 0x6deb , 0x5bc5 , 0x996e , 0x5c39 , 0x5f15 , 0x9690 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5370 , 0x82f1 , 0x6a31 , 0x5a74 , 0x9e70 , 0x5e94 , 0x7f28 , 0x83b9 , 0x8424 , 0x8425 , 0x8367 , 0x8747 , 0x8fce , 0x8d62 , 0x76c8 , 0x5f71 , 0x9896 , 0x786c , 0x6620 , 0x54df , 0x62e5 , 0x4f63 , 0x81c3 , 0x75c8 , 0x5eb8 , 0x96cd , 0x8e0a , 0x86f9 , 0x548f , 0x6cf3 , 0x6d8c , 0x6c38 , 0x607f , 0x52c7 , 0x7528 , 0x5e7d , 0x4f18 , 0x60a0 , 0x5fe7 , 0x5c24 , 0x7531 , 0x90ae , 0x94c0 , 0x72b9 , 0x6cb9 , 0x6e38 , 0x9149 , 0x6709 , 0x53cb , 0x53f3 , 0x4f51 , 0x91c9 , 0x8bf1 , 0x53c8 , 0x5e7c , 0x8fc2 , 0x6de4 , 0x4e8e , 0x76c2 , 0x6986 , 0x865e , 0x611a , 0x8206 , 0x4f59 , 0x4fde , 0x903e , 0x9c7c , 0x6109 , 0x6e1d , 0x6e14 , 0x9685 , 0x4e88 , 0x5a31 , 0x96e8 , 0x4e0e , 0x5c7f , 0x79b9 , 0x5b87 , 0x8bed , 0x7fbd , 0x7389 , 0x57df , 0x828b , 0x90c1 , 0x5401 , 0x9047 , 0x55bb , 0x5cea , 0x5fa1 , 0x6108 , 0x6b32 , 0x72f1 , 0x80b2 , 0x8a89 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6d74 , 0x5bd3 , 0x88d5 , 0x9884 , 0x8c6b , 0x9a6d , 0x9e33 , 0x6e0a , 0x51a4 , 0x5143 , 0x57a3 , 0x8881 , 0x539f , 0x63f4 , 0x8f95 , 0x56ed , 0x5458 , 0x5706 , 0x733f , 0x6e90 , 0x7f18 , 0x8fdc , 0x82d1 , 0x613f , 0x6028 , 0x9662 , 0x66f0 , 0x7ea6 , 0x8d8a , 0x8dc3 , 0x94a5 , 0x5cb3 , 0x7ca4 , 0x6708 , 0x60a6 , 0x9605 , 0x8018 , 0x4e91 , 0x90e7 , 0x5300 , 0x9668 , 0x5141 , 0x8fd0 , 0x8574 , 0x915d , 0x6655 , 0x97f5 , 0x5b55 , 0x531d , 0x7838 , 0x6742 , 0x683d , 0x54c9 , 0x707e , 0x5bb0 , 0x8f7d , 0x518d , 0x5728 , 0x54b1 , 0x6512 , 0x6682 , 0x8d5e , 0x8d43 , 0x810f , 0x846c , 0x906d , 0x7cdf , 0x51ff , 0x85fb , 0x67a3 , 0x65e9 , 0x6fa1 , 0x86a4 , 0x8e81 , 0x566a , 0x9020 , 0x7682 , 0x7076 , 0x71e5 , 0x8d23 , 0x62e9 , 0x5219 , 0x6cfd , 0x8d3c , 0x600e , 0x589e , 0x618e , 0x66fe , 0x8d60 , 0x624e , 0x55b3 , 0x6e23 , 0x672d , 0x8f67 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x94e1 , 0x95f8 , 0x7728 , 0x6805 , 0x69a8 , 0x548b , 0x4e4d , 0x70b8 , 0x8bc8 , 0x6458 , 0x658b , 0x5b85 , 0x7a84 , 0x503a , 0x5be8 , 0x77bb , 0x6be1 , 0x8a79 , 0x7c98 , 0x6cbe , 0x76cf , 0x65a9 , 0x8f97 , 0x5d2d , 0x5c55 , 0x8638 , 0x6808 , 0x5360 , 0x6218 , 0x7ad9 , 0x6e5b , 0x7efd , 0x6a1f , 0x7ae0 , 0x5f70 , 0x6f33 , 0x5f20 , 0x638c , 0x6da8 , 0x6756 , 0x4e08 , 0x5e10 , 0x8d26 , 0x4ed7 , 0x80c0 , 0x7634 , 0x969c , 0x62db , 0x662d , 0x627e , 0x6cbc , 0x8d75 , 0x7167 , 0x7f69 , 0x5146 , 0x8087 , 0x53ec , 0x906e , 0x6298 , 0x54f2 , 0x86f0 , 0x8f99 , 0x8005 , 0x9517 , 0x8517 , 0x8fd9 , 0x6d59 , 0x73cd , 0x659f , 0x771f , 0x7504 , 0x7827 , 0x81fb , 0x8d1e , 0x9488 , 0x4fa6 , 0x6795 , 0x75b9 , 0x8bca , 0x9707 , 0x632f , 0x9547 , 0x9635 , 0x84b8 , 0x6323 , 0x7741 , 0x5f81 , 0x72f0 , 0x4e89 , 0x6014 , 0x6574 , 0x62ef , 0x6b63 , 0x653f , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5e27 , 0x75c7 , 0x90d1 , 0x8bc1 , 0x829d , 0x679d , 0x652f , 0x5431 , 0x8718 , 0x77e5 , 0x80a2 , 0x8102 , 0x6c41 , 0x4e4b , 0x7ec7 , 0x804c , 0x76f4 , 0x690d , 0x6b96 , 0x6267 , 0x503c , 0x4f84 , 0x5740 , 0x6307 , 0x6b62 , 0x8dbe , 0x53ea , 0x65e8 , 0x7eb8 , 0x5fd7 , 0x631a , 0x63b7 , 0x81f3 , 0x81f4 , 0x7f6e , 0x5e1c , 0x5cd9 , 0x5236 , 0x667a , 0x79e9 , 0x7a1a , 0x8d28 , 0x7099 , 0x75d4 , 0x6ede , 0x6cbb , 0x7a92 , 0x4e2d , 0x76c5 , 0x5fe0 , 0x949f , 0x8877 , 0x7ec8 , 0x79cd , 0x80bf , 0x91cd , 0x4ef2 , 0x4f17 , 0x821f , 0x5468 , 0x5dde , 0x6d32 , 0x8bcc , 0x7ca5 , 0x8f74 , 0x8098 , 0x5e1a , 0x5492 , 0x76b1 , 0x5b99 , 0x663c , 0x9aa4 , 0x73e0 , 0x682a , 0x86db , 0x6731 , 0x732a , 0x8bf8 , 0x8bdb , 0x9010 , 0x7af9 , 0x70db , 0x716e , 0x62c4 , 0x77a9 , 0x5631 , 0x4e3b , 0x8457 , 0x67f1 , 0x52a9 , 0x86c0 , 0x8d2e , 0x94f8 , 0x7b51 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x4f4f , 0x6ce8 , 0x795d , 0x9a7b , 0x6293 , 0x722a , 0x62fd , 0x4e13 , 0x7816 , 0x8f6c , 0x64b0 , 0x8d5a , 0x7bc6 , 0x6869 , 0x5e84 , 0x88c5 , 0x5986 , 0x649e , 0x58ee , 0x72b6 , 0x690e , 0x9525 , 0x8ffd , 0x8d58 , 0x5760 , 0x7f00 , 0x8c06 , 0x51c6 , 0x6349 , 0x62d9 , 0x5353 , 0x684c , 0x7422 , 0x8301 , 0x914c , 0x5544 , 0x7740 , 0x707c , 0x6d4a , 0x5179 , 0x54a8 , 0x8d44 , 0x59ff , 0x6ecb , 0x6dc4 , 0x5b5c , 0x7d2b , 0x4ed4 , 0x7c7d , 0x6ed3 , 0x5b50 , 0x81ea , 0x6e0d , 0x5b57 , 0x9b03 , 0x68d5 , 0x8e2a , 0x5b97 , 0x7efc , 0x603b , 0x7eb5 , 0x90b9 , 0x8d70 , 0x594f , 0x63cd , 0x79df , 0x8db3 , 0x5352 , 0x65cf , 0x7956 , 0x8bc5 , 0x963b , 0x7ec4 , 0x94bb , 0x7e82 , 0x5634 , 0x9189 , 0x6700 , 0x7f6a , 0x5c0a , 0x9075 , 0x6628 , 0x5de6 , 0x4f50 , 0x67de , 0x505a , 0x4f5c , 0x5750 , 0x5ea7 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x4e8d , 0x4e0c , 0x5140 , 0x4e10 , 0x5eff , 0x5345 , 0x4e15 , 0x4e98 , 0x4e1e , 0x9b32 , 0x5b6c , 0x5669 , 0x4e28 , 0x79ba , 0x4e3f , 0x5315 , 0x4e47 , 0x592d , 0x723b , 0x536e , 0x6c10 , 0x56df , 0x80e4 , 0x9997 , 0x6bd3 , 0x777e , 0x9f17 , 0x4e36 , 0x4e9f , 0x9f10 , 0x4e5c , 0x4e69 , 0x4e93 , 0x8288 , 0x5b5b , 0x556c , 0x560f , 0x4ec4 , 0x538d , 0x539d , 0x53a3 , 0x53a5 , 0x53ae , 0x9765 , 0x8d5d , 0x531a , 0x53f5 , 0x5326 , 0x532e , 0x533e , 0x8d5c , 0x5366 , 0x5363 , 0x5202 , 0x5208 , 0x520e , 0x522d , 0x5233 , 0x523f , 0x5240 , 0x524c , 0x525e , 0x5261 , 0x525c , 0x84af , 0x527d , 0x5282 , 0x5281 , 0x5290 , 0x5293 , 0x5182 , 0x7f54 , 0x4ebb , 0x4ec3 , 0x4ec9 , 0x4ec2 , 0x4ee8 , 0x4ee1 , 0x4eeb , 0x4ede , 0x4f1b , 0x4ef3 , 0x4f22 , 0x4f64 , 0x4ef5 , 0x4f25 , 0x4f27 , 0x4f09 , 0x4f2b , 0x4f5e , 0x4f67 , 0x6538 , 0x4f5a , 0x4f5d , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x4f5f , 0x4f57 , 0x4f32 , 0x4f3d , 0x4f76 , 0x4f74 , 0x4f91 , 0x4f89 , 0x4f83 , 0x4f8f , 0x4f7e , 0x4f7b , 0x4faa , 0x4f7c , 0x4fac , 0x4f94 , 0x4fe6 , 0x4fe8 , 0x4fea , 0x4fc5 , 0x4fda , 0x4fe3 , 0x4fdc , 0x4fd1 , 0x4fdf , 0x4ff8 , 0x5029 , 0x504c , 0x4ff3 , 0x502c , 0x500f , 0x502e , 0x502d , 0x4ffe , 0x501c , 0x500c , 0x5025 , 0x5028 , 0x507e , 0x5043 , 0x5055 , 0x5048 , 0x504e , 0x506c , 0x507b , 0x50a5 , 0x50a7 , 0x50a9 , 0x50ba , 0x50d6 , 0x5106 , 0x50ed , 0x50ec , 0x50e6 , 0x50ee , 0x5107 , 0x510b , 0x4edd , 0x6c3d , 0x4f58 , 0x4f65 , 0x4fce , 0x9fa0 , 0x6c46 , 0x7c74 , 0x516e , 0x5dfd , 0x9ec9 , 0x9998 , 0x5181 , 0x5914 , 0x52f9 , 0x530d , 0x8a07 , 0x5310 , 0x51eb , 0x5919 , 0x5155 , 0x4ea0 , 0x5156 , 0x4eb3 , 0x886e , 0x88a4 , 0x4eb5 , 0x8114 , 0x88d2 , 0x7980 , 0x5b34 , 0x8803 , 0x7fb8 , 0x51ab , 0x51b1 , 0x51bd , 0x51bc , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x51c7 , 0x5196 , 0x51a2 , 0x51a5 , 0x8ba0 , 0x8ba6 , 0x8ba7 , 0x8baa , 0x8bb4 , 0x8bb5 , 0x8bb7 , 0x8bc2 , 0x8bc3 , 0x8bcb , 0x8bcf , 0x8bce , 0x8bd2 , 0x8bd3 , 0x8bd4 , 0x8bd6 , 0x8bd8 , 0x8bd9 , 0x8bdc , 0x8bdf , 0x8be0 , 0x8be4 , 0x8be8 , 0x8be9 , 0x8bee , 0x8bf0 , 0x8bf3 , 0x8bf6 , 0x8bf9 , 0x8bfc , 0x8bff , 0x8c00 , 0x8c02 , 0x8c04 , 0x8c07 , 0x8c0c , 0x8c0f , 0x8c11 , 0x8c12 , 0x8c14 , 0x8c15 , 0x8c16 , 0x8c19 , 0x8c1b , 0x8c18 , 0x8c1d , 0x8c1f , 0x8c20 , 0x8c21 , 0x8c25 , 0x8c27 , 0x8c2a , 0x8c2b , 0x8c2e , 0x8c2f , 0x8c32 , 0x8c33 , 0x8c35 , 0x8c36 , 0x5369 , 0x537a , 0x961d , 0x9622 , 0x9621 , 0x9631 , 0x962a , 0x963d , 0x963c , 0x9642 , 0x9649 , 0x9654 , 0x965f , 0x9667 , 0x966c , 0x9672 , 0x9674 , 0x9688 , 0x968d , 0x9697 , 0x96b0 , 0x9097 , 0x909b , 0x909d , 0x9099 , 0x90ac , 0x90a1 , 0x90b4 , 0x90b3 , 0x90b6 , 0x90ba , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x90b8 , 0x90b0 , 0x90cf , 0x90c5 , 0x90be , 0x90d0 , 0x90c4 , 0x90c7 , 0x90d3 , 0x90e6 , 0x90e2 , 0x90dc , 0x90d7 , 0x90db , 0x90eb , 0x90ef , 0x90fe , 0x9104 , 0x9122 , 0x911e , 0x9123 , 0x9131 , 0x912f , 0x9139 , 0x9143 , 0x9146 , 0x520d , 0x5942 , 0x52a2 , 0x52ac , 0x52ad , 0x52be , 0x54ff , 0x52d0 , 0x52d6 , 0x52f0 , 0x53df , 0x71ee , 0x77cd , 0x5ef4 , 0x51f5 , 0x51fc , 0x9b2f , 0x53b6 , 0x5f01 , 0x755a , 0x5def , 0x574c , 0x57a9 , 0x57a1 , 0x587e , 0x58bc , 0x58c5 , 0x58d1 , 0x5729 , 0x572c , 0x572a , 0x5733 , 0x5739 , 0x572e , 0x572f , 0x575c , 0x573b , 0x5742 , 0x5769 , 0x5785 , 0x576b , 0x5786 , 0x577c , 0x577b , 0x5768 , 0x576d , 0x5776 , 0x5773 , 0x57ad , 0x57a4 , 0x578c , 0x57b2 , 0x57cf , 0x57a7 , 0x57b4 , 0x5793 , 0x57a0 , 0x57d5 , 0x57d8 , 0x57da , 0x57d9 , 0x57d2 , 0x57b8 , 0x57f4 , 0x57ef , 0x57f8 , 0x57e4 , 0x57dd , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x580b , 0x580d , 0x57fd , 0x57ed , 0x5800 , 0x581e , 0x5819 , 0x5844 , 0x5820 , 0x5865 , 0x586c , 0x5881 , 0x5889 , 0x589a , 0x5880 , 0x99a8 , 0x9f19 , 0x61ff , 0x8279 , 0x827d , 0x827f , 0x828f , 0x828a , 0x82a8 , 0x8284 , 0x828e , 0x8291 , 0x8297 , 0x8299 , 0x82ab , 0x82b8 , 0x82be , 0x82b0 , 0x82c8 , 0x82ca , 0x82e3 , 0x8298 , 0x82b7 , 0x82ae , 0x82cb , 0x82cc , 0x82c1 , 0x82a9 , 0x82b4 , 0x82a1 , 0x82aa , 0x829f , 0x82c4 , 0x82ce , 0x82a4 , 0x82e1 , 0x8309 , 0x82f7 , 0x82e4 , 0x830f , 0x8307 , 0x82dc , 0x82f4 , 0x82d2 , 0x82d8 , 0x830c , 0x82fb , 0x82d3 , 0x8311 , 0x831a , 0x8306 , 0x8314 , 0x8315 , 0x82e0 , 0x82d5 , 0x831c , 0x8351 , 0x835b , 0x835c , 0x8308 , 0x8392 , 0x833c , 0x8334 , 0x8331 , 0x839b , 0x835e , 0x832f , 0x834f , 0x8347 , 0x8343 , 0x835f , 0x8340 , 0x8317 , 0x8360 , 0x832d , 0x833a , 0x8333 , 0x8366 , 0x8365 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x8368 , 0x831b , 0x8369 , 0x836c , 0x836a , 0x836d , 0x836e , 0x83b0 , 0x8378 , 0x83b3 , 0x83b4 , 0x83a0 , 0x83aa , 0x8393 , 0x839c , 0x8385 , 0x837c , 0x83b6 , 0x83a9 , 0x837d , 0x83b8 , 0x837b , 0x8398 , 0x839e , 0x83a8 , 0x83ba , 0x83bc , 0x83c1 , 0x8401 , 0x83e5 , 0x83d8 , 0x5807 , 0x8418 , 0x840b , 0x83dd , 0x83fd , 0x83d6 , 0x841c , 0x8438 , 0x8411 , 0x8406 , 0x83d4 , 0x83df , 0x840f , 0x8403 , 0x83f8 , 0x83f9 , 0x83ea , 0x83c5 , 0x83c0 , 0x8426 , 0x83f0 , 0x83e1 , 0x845c , 0x8451 , 0x845a , 0x8459 , 0x8473 , 0x8487 , 0x8488 , 0x847a , 0x8489 , 0x8478 , 0x843c , 0x8446 , 0x8469 , 0x8476 , 0x848c , 0x848e , 0x8431 , 0x846d , 0x84c1 , 0x84cd , 0x84d0 , 0x84e6 , 0x84bd , 0x84d3 , 0x84ca , 0x84bf , 0x84ba , 0x84e0 , 0x84a1 , 0x84b9 , 0x84b4 , 0x8497 , 0x84e5 , 0x84e3 , 0x850c , 0x750d , 0x8538 , 0x84f0 , 0x8539 , 0x851f , 0x853a , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x8556 , 0x853b , 0x84ff , 0x84fc , 0x8559 , 0x8548 , 0x8568 , 0x8564 , 0x855e , 0x857a , 0x77a2 , 0x8543 , 0x8572 , 0x857b , 0x85a4 , 0x85a8 , 0x8587 , 0x858f , 0x8579 , 0x85ae , 0x859c , 0x8585 , 0x85b9 , 0x85b7 , 0x85b0 , 0x85d3 , 0x85c1 , 0x85dc , 0x85ff , 0x8627 , 0x8605 , 0x8629 , 0x8616 , 0x863c , 0x5efe , 0x5f08 , 0x593c , 0x5941 , 0x8037 , 0x5955 , 0x595a , 0x5958 , 0x530f , 0x5c22 , 0x5c25 , 0x5c2c , 0x5c34 , 0x624c , 0x626a , 0x629f , 0x62bb , 0x62ca , 0x62da , 0x62d7 , 0x62ee , 0x6322 , 0x62f6 , 0x6339 , 0x634b , 0x6343 , 0x63ad , 0x63f6 , 0x6371 , 0x637a , 0x638e , 0x63b4 , 0x636d , 0x63ac , 0x638a , 0x6369 , 0x63ae , 0x63bc , 0x63f2 , 0x63f8 , 0x63e0 , 0x63ff , 0x63c4 , 0x63de , 0x63ce , 0x6452 , 0x63c6 , 0x63be , 0x6445 , 0x6441 , 0x640b , 0x641b , 0x6420 , 0x640c , 0x6426 , 0x6421 , 0x645e , 0x6484 , 0x646d , 0x6496 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x647a , 0x64b7 , 0x64b8 , 0x6499 , 0x64ba , 0x64c0 , 0x64d0 , 0x64d7 , 0x64e4 , 0x64e2 , 0x6509 , 0x6525 , 0x652e , 0x5f0b , 0x5fd2 , 0x7519 , 0x5f11 , 0x535f , 0x53f1 , 0x53fd , 0x53e9 , 0x53e8 , 0x53fb , 0x5412 , 0x5416 , 0x5406 , 0x544b , 0x5452 , 0x5453 , 0x5454 , 0x5456 , 0x5443 , 0x5421 , 0x5457 , 0x5459 , 0x5423 , 0x5432 , 0x5482 , 0x5494 , 0x5477 , 0x5471 , 0x5464 , 0x549a , 0x549b , 0x5484 , 0x5476 , 0x5466 , 0x549d , 0x54d0 , 0x54ad , 0x54c2 , 0x54b4 , 0x54d2 , 0x54a7 , 0x54a6 , 0x54d3 , 0x54d4 , 0x5472 , 0x54a3 , 0x54d5 , 0x54bb , 0x54bf , 0x54cc , 0x54d9 , 0x54da , 0x54dc , 0x54a9 , 0x54aa , 0x54a4 , 0x54dd , 0x54cf , 0x54de , 0x551b , 0x54e7 , 0x5520 , 0x54fd , 0x5514 , 0x54f3 , 0x5522 , 0x5523 , 0x550f , 0x5511 , 0x5527 , 0x552a , 0x5567 , 0x558f , 0x55b5 , 0x5549 , 0x556d , 0x5541 , 0x5555 , 0x553f , 0x5550 , 0x553c , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5537 , 0x5556 , 0x5575 , 0x5576 , 0x5577 , 0x5533 , 0x5530 , 0x555c , 0x558b , 0x55d2 , 0x5583 , 0x55b1 , 0x55b9 , 0x5588 , 0x5581 , 0x559f , 0x557e , 0x55d6 , 0x5591 , 0x557b , 0x55df , 0x55bd , 0x55be , 0x5594 , 0x5599 , 0x55ea , 0x55f7 , 0x55c9 , 0x561f , 0x55d1 , 0x55eb , 0x55ec , 0x55d4 , 0x55e6 , 0x55dd , 0x55c4 , 0x55ef , 0x55e5 , 0x55f2 , 0x55f3 , 0x55cc , 0x55cd , 0x55e8 , 0x55f5 , 0x55e4 , 0x8f94 , 0x561e , 0x5608 , 0x560c , 0x5601 , 0x5624 , 0x5623 , 0x55fe , 0x5600 , 0x5627 , 0x562d , 0x5658 , 0x5639 , 0x5657 , 0x562c , 0x564d , 0x5662 , 0x5659 , 0x565c , 0x564c , 0x5654 , 0x5686 , 0x5664 , 0x5671 , 0x566b , 0x567b , 0x567c , 0x5685 , 0x5693 , 0x56af , 0x56d4 , 0x56d7 , 0x56dd , 0x56e1 , 0x56f5 , 0x56eb , 0x56f9 , 0x56ff , 0x5704 , 0x570a , 0x5709 , 0x571c , 0x5e0f , 0x5e19 , 0x5e14 , 0x5e11 , 0x5e31 , 0x5e3b , 0x5e3c , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5e37 , 0x5e44 , 0x5e54 , 0x5e5b , 0x5e5e , 0x5e61 , 0x5c8c , 0x5c7a , 0x5c8d , 0x5c90 , 0x5c96 , 0x5c88 , 0x5c98 , 0x5c99 , 0x5c91 , 0x5c9a , 0x5c9c , 0x5cb5 , 0x5ca2 , 0x5cbd , 0x5cac , 0x5cab , 0x5cb1 , 0x5ca3 , 0x5cc1 , 0x5cb7 , 0x5cc4 , 0x5cd2 , 0x5ce4 , 0x5ccb , 0x5ce5 , 0x5d02 , 0x5d03 , 0x5d27 , 0x5d26 , 0x5d2e , 0x5d24 , 0x5d1e , 0x5d06 , 0x5d1b , 0x5d58 , 0x5d3e , 0x5d34 , 0x5d3d , 0x5d6c , 0x5d5b , 0x5d6f , 0x5d5d , 0x5d6b , 0x5d4b , 0x5d4a , 0x5d69 , 0x5d74 , 0x5d82 , 0x5d99 , 0x5d9d , 0x8c73 , 0x5db7 , 0x5dc5 , 0x5f73 , 0x5f77 , 0x5f82 , 0x5f87 , 0x5f89 , 0x5f8c , 0x5f95 , 0x5f99 , 0x5f9c , 0x5fa8 , 0x5fad , 0x5fb5 , 0x5fbc , 0x8862 , 0x5f61 , 0x72ad , 0x72b0 , 0x72b4 , 0x72b7 , 0x72b8 , 0x72c3 , 0x72c1 , 0x72ce , 0x72cd , 0x72d2 , 0x72e8 , 0x72ef , 0x72e9 , 0x72f2 , 0x72f4 , 0x72f7 , 0x7301 , 0x72f3 , 0x7303 , 0x72fa , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x72fb , 0x7317 , 0x7313 , 0x7321 , 0x730a , 0x731e , 0x731d , 0x7315 , 0x7322 , 0x7339 , 0x7325 , 0x732c , 0x7338 , 0x7331 , 0x7350 , 0x734d , 0x7357 , 0x7360 , 0x736c , 0x736f , 0x737e , 0x821b , 0x5925 , 0x98e7 , 0x5924 , 0x5902 , 0x9963 , 0x9967 , 0x9968 , 0x9969 , 0x996a , 0x996b , 0x996c , 0x9974 , 0x9977 , 0x997d , 0x9980 , 0x9984 , 0x9987 , 0x998a , 0x998d , 0x9990 , 0x9991 , 0x9993 , 0x9994 , 0x9995 , 0x5e80 , 0x5e91 , 0x5e8b , 0x5e96 , 0x5ea5 , 0x5ea0 , 0x5eb9 , 0x5eb5 , 0x5ebe , 0x5eb3 , 0x8d53 , 0x5ed2 , 0x5ed1 , 0x5edb , 0x5ee8 , 0x5eea , 0x81ba , 0x5fc4 , 0x5fc9 , 0x5fd6 , 0x5fcf , 0x6003 , 0x5fee , 0x6004 , 0x5fe1 , 0x5fe4 , 0x5ffe , 0x6005 , 0x6006 , 0x5fea , 0x5fed , 0x5ff8 , 0x6019 , 0x6035 , 0x6026 , 0x601b , 0x600f , 0x600d , 0x6029 , 0x602b , 0x600a , 0x603f , 0x6021 , 0x6078 , 0x6079 , 0x607b , 0x607a , 0x6042 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x606a , 0x607d , 0x6096 , 0x609a , 0x60ad , 0x609d , 0x6083 , 0x6092 , 0x608c , 0x609b , 0x60ec , 0x60bb , 0x60b1 , 0x60dd , 0x60d8 , 0x60c6 , 0x60da , 0x60b4 , 0x6120 , 0x6126 , 0x6115 , 0x6123 , 0x60f4 , 0x6100 , 0x610e , 0x612b , 0x614a , 0x6175 , 0x61ac , 0x6194 , 0x61a7 , 0x61b7 , 0x61d4 , 0x61f5 , 0x5fdd , 0x96b3 , 0x95e9 , 0x95eb , 0x95f1 , 0x95f3 , 0x95f5 , 0x95f6 , 0x95fc , 0x95fe , 0x9603 , 0x9604 , 0x9606 , 0x9608 , 0x960a , 0x960b , 0x960c , 0x960d , 0x960f , 0x9612 , 0x9615 , 0x9616 , 0x9617 , 0x9619 , 0x961a , 0x4e2c , 0x723f , 0x6215 , 0x6c35 , 0x6c54 , 0x6c5c , 0x6c4a , 0x6ca3 , 0x6c85 , 0x6c90 , 0x6c94 , 0x6c8c , 0x6c68 , 0x6c69 , 0x6c74 , 0x6c76 , 0x6c86 , 0x6ca9 , 0x6cd0 , 0x6cd4 , 0x6cad , 0x6cf7 , 0x6cf8 , 0x6cf1 , 0x6cd7 , 0x6cb2 , 0x6ce0 , 0x6cd6 , 0x6cfa , 0x6ceb , 0x6cee , 0x6cb1 , 0x6cd3 , 0x6cef , 0x6cfe , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6d39 , 0x6d27 , 0x6d0c , 0x6d43 , 0x6d48 , 0x6d07 , 0x6d04 , 0x6d19 , 0x6d0e , 0x6d2b , 0x6d4d , 0x6d2e , 0x6d35 , 0x6d1a , 0x6d4f , 0x6d52 , 0x6d54 , 0x6d33 , 0x6d91 , 0x6d6f , 0x6d9e , 0x6da0 , 0x6d5e , 0x6d93 , 0x6d94 , 0x6d5c , 0x6d60 , 0x6d7c , 0x6d63 , 0x6e1a , 0x6dc7 , 0x6dc5 , 0x6dde , 0x6e0e , 0x6dbf , 0x6de0 , 0x6e11 , 0x6de6 , 0x6ddd , 0x6dd9 , 0x6e16 , 0x6dab , 0x6e0c , 0x6dae , 0x6e2b , 0x6e6e , 0x6e4e , 0x6e6b , 0x6eb2 , 0x6e5f , 0x6e86 , 0x6e53 , 0x6e54 , 0x6e32 , 0x6e25 , 0x6e44 , 0x6edf , 0x6eb1 , 0x6e98 , 0x6ee0 , 0x6f2d , 0x6ee2 , 0x6ea5 , 0x6ea7 , 0x6ebd , 0x6ebb , 0x6eb7 , 0x6ed7 , 0x6eb4 , 0x6ecf , 0x6e8f , 0x6ec2 , 0x6e9f , 0x6f62 , 0x6f46 , 0x6f47 , 0x6f24 , 0x6f15 , 0x6ef9 , 0x6f2f , 0x6f36 , 0x6f4b , 0x6f74 , 0x6f2a , 0x6f09 , 0x6f29 , 0x6f89 , 0x6f8d , 0x6f8c , 0x6f78 , 0x6f72 , 0x6f7c , 0x6f7a , 0x6fd1 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6fc9 , 0x6fa7 , 0x6fb9 , 0x6fb6 , 0x6fc2 , 0x6fe1 , 0x6fee , 0x6fde , 0x6fe0 , 0x6fef , 0x701a , 0x7023 , 0x701b , 0x7039 , 0x7035 , 0x704f , 0x705e , 0x5b80 , 0x5b84 , 0x5b95 , 0x5b93 , 0x5ba5 , 0x5bb8 , 0x752f , 0x9a9e , 0x6434 , 0x5be4 , 0x5bee , 0x8930 , 0x5bf0 , 0x8e47 , 0x8b07 , 0x8fb6 , 0x8fd3 , 0x8fd5 , 0x8fe5 , 0x8fee , 0x8fe4 , 0x8fe9 , 0x8fe6 , 0x8ff3 , 0x8fe8 , 0x9005 , 0x9004 , 0x900b , 0x9026 , 0x9011 , 0x900d , 0x9016 , 0x9021 , 0x9035 , 0x9036 , 0x902d , 0x902f , 0x9044 , 0x9051 , 0x9052 , 0x9050 , 0x9068 , 0x9058 , 0x9062 , 0x905b , 0x66b9 , 0x9074 , 0x907d , 0x9082 , 0x9088 , 0x9083 , 0x908b , 0x5f50 , 0x5f57 , 0x5f56 , 0x5f58 , 0x5c3b , 0x54ab , 0x5c50 , 0x5c59 , 0x5b71 , 0x5c63 , 0x5c66 , 0x7fbc , 0x5f2a , 0x5f29 , 0x5f2d , 0x8274 , 0x5f3c , 0x9b3b , 0x5c6e , 0x5981 , 0x5983 , 0x598d , 0x59a9 , 0x59aa , 0x59a3 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x5997 , 0x59ca , 0x59ab , 0x599e , 0x59a4 , 0x59d2 , 0x59b2 , 0x59af , 0x59d7 , 0x59be , 0x5a05 , 0x5a06 , 0x59dd , 0x5a08 , 0x59e3 , 0x59d8 , 0x59f9 , 0x5a0c , 0x5a09 , 0x5a32 , 0x5a34 , 0x5a11 , 0x5a23 , 0x5a13 , 0x5a40 , 0x5a67 , 0x5a4a , 0x5a55 , 0x5a3c , 0x5a62 , 0x5a75 , 0x80ec , 0x5aaa , 0x5a9b , 0x5a77 , 0x5a7a , 0x5abe , 0x5aeb , 0x5ab2 , 0x5ad2 , 0x5ad4 , 0x5ab8 , 0x5ae0 , 0x5ae3 , 0x5af1 , 0x5ad6 , 0x5ae6 , 0x5ad8 , 0x5adc , 0x5b09 , 0x5b17 , 0x5b16 , 0x5b32 , 0x5b37 , 0x5b40 , 0x5c15 , 0x5c1c , 0x5b5a , 0x5b65 , 0x5b73 , 0x5b51 , 0x5b53 , 0x5b62 , 0x9a75 , 0x9a77 , 0x9a78 , 0x9a7a , 0x9a7f , 0x9a7d , 0x9a80 , 0x9a81 , 0x9a85 , 0x9a88 , 0x9a8a , 0x9a90 , 0x9a92 , 0x9a93 , 0x9a96 , 0x9a98 , 0x9a9b , 0x9a9c , 0x9a9d , 0x9a9f , 0x9aa0 , 0x9aa2 , 0x9aa3 , 0x9aa5 , 0x9aa7 , 0x7e9f , 0x7ea1 , 0x7ea3 , 0x7ea5 , 0x7ea8 , 0x7ea9 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7ead , 0x7eb0 , 0x7ebe , 0x7ec0 , 0x7ec1 , 0x7ec2 , 0x7ec9 , 0x7ecb , 0x7ecc , 0x7ed0 , 0x7ed4 , 0x7ed7 , 0x7edb , 0x7ee0 , 0x7ee1 , 0x7ee8 , 0x7eeb , 0x7eee , 0x7eef , 0x7ef1 , 0x7ef2 , 0x7f0d , 0x7ef6 , 0x7efa , 0x7efb , 0x7efe , 0x7f01 , 0x7f02 , 0x7f03 , 0x7f07 , 0x7f08 , 0x7f0b , 0x7f0c , 0x7f0f , 0x7f11 , 0x7f12 , 0x7f17 , 0x7f19 , 0x7f1c , 0x7f1b , 0x7f1f , 0x7f21 , 0x7f22 , 0x7f23 , 0x7f24 , 0x7f25 , 0x7f26 , 0x7f27 , 0x7f2a , 0x7f2b , 0x7f2c , 0x7f2d , 0x7f2f , 0x7f30 , 0x7f31 , 0x7f32 , 0x7f33 , 0x7f35 , 0x5e7a , 0x757f , 0x5ddb , 0x753e , 0x9095 , 0x738e , 0x7391 , 0x73ae , 0x73a2 , 0x739f , 0x73cf , 0x73c2 , 0x73d1 , 0x73b7 , 0x73b3 , 0x73c0 , 0x73c9 , 0x73c8 , 0x73e5 , 0x73d9 , 0x987c , 0x740a , 0x73e9 , 0x73e7 , 0x73de , 0x73ba , 0x73f2 , 0x740f , 0x742a , 0x745b , 0x7426 , 0x7425 , 0x7428 , 0x7430 , 0x742e , 0x742c , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x741b , 0x741a , 0x7441 , 0x745c , 0x7457 , 0x7455 , 0x7459 , 0x7477 , 0x746d , 0x747e , 0x749c , 0x748e , 0x7480 , 0x7481 , 0x7487 , 0x748b , 0x749e , 0x74a8 , 0x74a9 , 0x7490 , 0x74a7 , 0x74d2 , 0x74ba , 0x97ea , 0x97eb , 0x97ec , 0x674c , 0x6753 , 0x675e , 0x6748 , 0x6769 , 0x67a5 , 0x6787 , 0x676a , 0x6773 , 0x6798 , 0x67a7 , 0x6775 , 0x67a8 , 0x679e , 0x67ad , 0x678b , 0x6777 , 0x677c , 0x67f0 , 0x6809 , 0x67d8 , 0x680a , 0x67e9 , 0x67b0 , 0x680c , 0x67d9 , 0x67b5 , 0x67da , 0x67b3 , 0x67dd , 0x6800 , 0x67c3 , 0x67b8 , 0x67e2 , 0x680e , 0x67c1 , 0x67fd , 0x6832 , 0x6833 , 0x6860 , 0x6861 , 0x684e , 0x6862 , 0x6844 , 0x6864 , 0x6883 , 0x681d , 0x6855 , 0x6866 , 0x6841 , 0x6867 , 0x6840 , 0x683e , 0x684a , 0x6849 , 0x6829 , 0x68b5 , 0x688f , 0x6874 , 0x6877 , 0x6893 , 0x686b , 0x68c2 , 0x696e , 0x68fc , 0x691f , 0x6920 , 0x68f9 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x6924 , 0x68f0 , 0x690b , 0x6901 , 0x6957 , 0x68e3 , 0x6910 , 0x6971 , 0x6939 , 0x6960 , 0x6942 , 0x695d , 0x6984 , 0x696b , 0x6980 , 0x6998 , 0x6978 , 0x6934 , 0x69cc , 0x6987 , 0x6988 , 0x69ce , 0x6989 , 0x6966 , 0x6963 , 0x6979 , 0x699b , 0x69a7 , 0x69bb , 0x69ab , 0x69ad , 0x69d4 , 0x69b1 , 0x69c1 , 0x69ca , 0x69df , 0x6995 , 0x69e0 , 0x698d , 0x69ff , 0x6a2f , 0x69ed , 0x6a17 , 0x6a18 , 0x6a65 , 0x69f2 , 0x6a44 , 0x6a3e , 0x6aa0 , 0x6a50 , 0x6a5b , 0x6a35 , 0x6a8e , 0x6a79 , 0x6a3d , 0x6a28 , 0x6a58 , 0x6a7c , 0x6a91 , 0x6a90 , 0x6aa9 , 0x6a97 , 0x6aab , 0x7337 , 0x7352 , 0x6b81 , 0x6b82 , 0x6b87 , 0x6b84 , 0x6b92 , 0x6b93 , 0x6b8d , 0x6b9a , 0x6b9b , 0x6ba1 , 0x6baa , 0x8f6b , 0x8f6d , 0x8f71 , 0x8f72 , 0x8f73 , 0x8f75 , 0x8f76 , 0x8f78 , 0x8f77 , 0x8f79 , 0x8f7a , 0x8f7c , 0x8f7e , 0x8f81 , 0x8f82 , 0x8f84 , 0x8f87 , 0x8f8b , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x8f8d , 0x8f8e , 0x8f8f , 0x8f98 , 0x8f9a , 0x8ece , 0x620b , 0x6217 , 0x621b , 0x621f , 0x6222 , 0x6221 , 0x6225 , 0x6224 , 0x622c , 0x81e7 , 0x74ef , 0x74f4 , 0x74ff , 0x750f , 0x7511 , 0x7513 , 0x6534 , 0x65ee , 0x65ef , 0x65f0 , 0x660a , 0x6619 , 0x6772 , 0x6603 , 0x6615 , 0x6600 , 0x7085 , 0x66f7 , 0x661d , 0x6634 , 0x6631 , 0x6636 , 0x6635 , 0x8006 , 0x665f , 0x6654 , 0x6641 , 0x664f , 0x6656 , 0x6661 , 0x6657 , 0x6677 , 0x6684 , 0x668c , 0x66a7 , 0x669d , 0x66be , 0x66db , 0x66dc , 0x66e6 , 0x66e9 , 0x8d32 , 0x8d33 , 0x8d36 , 0x8d3b , 0x8d3d , 0x8d40 , 0x8d45 , 0x8d46 , 0x8d48 , 0x8d49 , 0x8d47 , 0x8d4d , 0x8d55 , 0x8d59 , 0x89c7 , 0x89ca , 0x89cb , 0x89cc , 0x89ce , 0x89cf , 0x89d0 , 0x89d1 , 0x726e , 0x729f , 0x725d , 0x7266 , 0x726f , 0x727e , 0x727f , 0x7284 , 0x728b , 0x728d , 0x728f , 0x7292 , 0x6308 , 0x6332 , 0x63b0 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x643f , 0x64d8 , 0x8004 , 0x6bea , 0x6bf3 , 0x6bfd , 0x6bf5 , 0x6bf9 , 0x6c05 , 0x6c07 , 0x6c06 , 0x6c0d , 0x6c15 , 0x6c18 , 0x6c19 , 0x6c1a , 0x6c21 , 0x6c29 , 0x6c24 , 0x6c2a , 0x6c32 , 0x6535 , 0x6555 , 0x656b , 0x724d , 0x7252 , 0x7256 , 0x7230 , 0x8662 , 0x5216 , 0x809f , 0x809c , 0x8093 , 0x80bc , 0x670a , 0x80bd , 0x80b1 , 0x80ab , 0x80ad , 0x80b4 , 0x80b7 , 0x80e7 , 0x80e8 , 0x80e9 , 0x80ea , 0x80db , 0x80c2 , 0x80c4 , 0x80d9 , 0x80cd , 0x80d7 , 0x6710 , 0x80dd , 0x80eb , 0x80f1 , 0x80f4 , 0x80ed , 0x810d , 0x810e , 0x80f2 , 0x80fc , 0x6715 , 0x8112 , 0x8c5a , 0x8136 , 0x811e , 0x812c , 0x8118 , 0x8132 , 0x8148 , 0x814c , 0x8153 , 0x8174 , 0x8159 , 0x815a , 0x8171 , 0x8160 , 0x8169 , 0x817c , 0x817d , 0x816d , 0x8167 , 0x584d , 0x5ab5 , 0x8188 , 0x8182 , 0x8191 , 0x6ed5 , 0x81a3 , 0x81aa , 0x81cc , 0x6726 , 0x81ca , 0x81bb , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x81c1 , 0x81a6 , 0x6b24 , 0x6b37 , 0x6b39 , 0x6b43 , 0x6b46 , 0x6b59 , 0x98d1 , 0x98d2 , 0x98d3 , 0x98d5 , 0x98d9 , 0x98da , 0x6bb3 , 0x5f40 , 0x6bc2 , 0x89f3 , 0x6590 , 0x9f51 , 0x6593 , 0x65bc , 0x65c6 , 0x65c4 , 0x65c3 , 0x65cc , 0x65ce , 0x65d2 , 0x65d6 , 0x7080 , 0x709c , 0x7096 , 0x709d , 0x70bb , 0x70c0 , 0x70b7 , 0x70ab , 0x70b1 , 0x70e8 , 0x70ca , 0x7110 , 0x7113 , 0x7116 , 0x712f , 0x7131 , 0x7173 , 0x715c , 0x7168 , 0x7145 , 0x7172 , 0x714a , 0x7178 , 0x717a , 0x7198 , 0x71b3 , 0x71b5 , 0x71a8 , 0x71a0 , 0x71e0 , 0x71d4 , 0x71e7 , 0x71f9 , 0x721d , 0x7228 , 0x706c , 0x7118 , 0x7166 , 0x71b9 , 0x623e , 0x623d , 0x6243 , 0x6248 , 0x6249 , 0x793b , 0x7940 , 0x7946 , 0x7949 , 0x795b , 0x795c , 0x7953 , 0x795a , 0x7962 , 0x7957 , 0x7960 , 0x796f , 0x7967 , 0x797a , 0x7985 , 0x798a , 0x799a , 0x79a7 , 0x79b3 , 0x5fd1 , 0x5fd0 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x603c , 0x605d , 0x605a , 0x6067 , 0x6041 , 0x6059 , 0x6063 , 0x60ab , 0x6106 , 0x610d , 0x615d , 0x61a9 , 0x619d , 0x61cb , 0x61d1 , 0x6206 , 0x8080 , 0x807f , 0x6c93 , 0x6cf6 , 0x6dfc , 0x77f6 , 0x77f8 , 0x7800 , 0x7809 , 0x7817 , 0x7818 , 0x7811 , 0x65ab , 0x782d , 0x781c , 0x781d , 0x7839 , 0x783a , 0x783b , 0x781f , 0x783c , 0x7825 , 0x782c , 0x7823 , 0x7829 , 0x784e , 0x786d , 0x7856 , 0x7857 , 0x7826 , 0x7850 , 0x7847 , 0x784c , 0x786a , 0x789b , 0x7893 , 0x789a , 0x7887 , 0x789c , 0x78a1 , 0x78a3 , 0x78b2 , 0x78b9 , 0x78a5 , 0x78d4 , 0x78d9 , 0x78c9 , 0x78ec , 0x78f2 , 0x7905 , 0x78f4 , 0x7913 , 0x7924 , 0x791e , 0x7934 , 0x9f9b , 0x9ef9 , 0x9efb , 0x9efc , 0x76f1 , 0x7704 , 0x770d , 0x76f9 , 0x7707 , 0x7708 , 0x771a , 0x7722 , 0x7719 , 0x772d , 0x7726 , 0x7735 , 0x7738 , 0x7750 , 0x7751 , 0x7747 , 0x7743 , 0x775a , 0x7768 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7762 , 0x7765 , 0x777f , 0x778d , 0x777d , 0x7780 , 0x778c , 0x7791 , 0x779f , 0x77a0 , 0x77b0 , 0x77b5 , 0x77bd , 0x753a , 0x7540 , 0x754e , 0x754b , 0x7548 , 0x755b , 0x7572 , 0x7579 , 0x7583 , 0x7f58 , 0x7f61 , 0x7f5f , 0x8a48 , 0x7f68 , 0x7f74 , 0x7f71 , 0x7f79 , 0x7f81 , 0x7f7e , 0x76cd , 0x76e5 , 0x8832 , 0x9485 , 0x9486 , 0x9487 , 0x948b , 0x948a , 0x948c , 0x948d , 0x948f , 0x9490 , 0x9494 , 0x9497 , 0x9495 , 0x949a , 0x949b , 0x949c , 0x94a3 , 0x94a4 , 0x94ab , 0x94aa , 0x94ad , 0x94ac , 0x94af , 0x94b0 , 0x94b2 , 0x94b4 , 0x94b6 , 0x94b7 , 0x94b8 , 0x94b9 , 0x94ba , 0x94bc , 0x94bd , 0x94bf , 0x94c4 , 0x94c8 , 0x94c9 , 0x94ca , 0x94cb , 0x94cc , 0x94cd , 0x94ce , 0x94d0 , 0x94d1 , 0x94d2 , 0x94d5 , 0x94d6 , 0x94d7 , 0x94d9 , 0x94d8 , 0x94db , 0x94de , 0x94df , 0x94e0 , 0x94e2 , 0x94e4 , 0x94e5 , 0x94e7 , 0x94e8 , 0x94ea , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x94e9 , 0x94eb , 0x94ee , 0x94ef , 0x94f3 , 0x94f4 , 0x94f5 , 0x94f7 , 0x94f9 , 0x94fc , 0x94fd , 0x94ff , 0x9503 , 0x9502 , 0x9506 , 0x9507 , 0x9509 , 0x950a , 0x950d , 0x950e , 0x950f , 0x9512 , 0x9513 , 0x9514 , 0x9515 , 0x9516 , 0x9518 , 0x951b , 0x951d , 0x951e , 0x951f , 0x9522 , 0x952a , 0x952b , 0x9529 , 0x952c , 0x9531 , 0x9532 , 0x9534 , 0x9536 , 0x9537 , 0x9538 , 0x953c , 0x953e , 0x953f , 0x9542 , 0x9535 , 0x9544 , 0x9545 , 0x9546 , 0x9549 , 0x954c , 0x954e , 0x954f , 0x9552 , 0x9553 , 0x9554 , 0x9556 , 0x9557 , 0x9558 , 0x9559 , 0x955b , 0x955e , 0x955f , 0x955d , 0x9561 , 0x9562 , 0x9564 , 0x9565 , 0x9566 , 0x9567 , 0x9568 , 0x9569 , 0x956a , 0x956b , 0x956c , 0x956f , 0x9571 , 0x9572 , 0x9573 , 0x953a , 0x77e7 , 0x77ec , 0x96c9 , 0x79d5 , 0x79ed , 0x79e3 , 0x79eb , 0x7a06 , 0x5d47 , 0x7a03 , 0x7a02 , 0x7a1e , 0x7a14 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7a39 , 0x7a37 , 0x7a51 , 0x9ecf , 0x99a5 , 0x7a70 , 0x7688 , 0x768e , 0x7693 , 0x7699 , 0x76a4 , 0x74de , 0x74e0 , 0x752c , 0x9e20 , 0x9e22 , 0x9e28 , 0x9e29 , 0x9e2a , 0x9e2b , 0x9e2c , 0x9e32 , 0x9e31 , 0x9e36 , 0x9e38 , 0x9e37 , 0x9e39 , 0x9e3a , 0x9e3e , 0x9e41 , 0x9e42 , 0x9e44 , 0x9e46 , 0x9e47 , 0x9e48 , 0x9e49 , 0x9e4b , 0x9e4c , 0x9e4e , 0x9e51 , 0x9e55 , 0x9e57 , 0x9e5a , 0x9e5b , 0x9e5c , 0x9e5e , 0x9e63 , 0x9e66 , 0x9e67 , 0x9e68 , 0x9e69 , 0x9e6a , 0x9e6b , 0x9e6c , 0x9e71 , 0x9e6d , 0x9e73 , 0x7592 , 0x7594 , 0x7596 , 0x75a0 , 0x759d , 0x75ac , 0x75a3 , 0x75b3 , 0x75b4 , 0x75b8 , 0x75c4 , 0x75b1 , 0x75b0 , 0x75c3 , 0x75c2 , 0x75d6 , 0x75cd , 0x75e3 , 0x75e8 , 0x75e6 , 0x75e4 , 0x75eb , 0x75e7 , 0x7603 , 0x75f1 , 0x75fc , 0x75ff , 0x7610 , 0x7600 , 0x7605 , 0x760c , 0x7617 , 0x760a , 0x7625 , 0x7618 , 0x7615 , 0x7619 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x761b , 0x763c , 0x7622 , 0x7620 , 0x7640 , 0x762d , 0x7630 , 0x763f , 0x7635 , 0x7643 , 0x763e , 0x7633 , 0x764d , 0x765e , 0x7654 , 0x765c , 0x7656 , 0x766b , 0x766f , 0x7fca , 0x7ae6 , 0x7a78 , 0x7a79 , 0x7a80 , 0x7a86 , 0x7a88 , 0x7a95 , 0x7aa6 , 0x7aa0 , 0x7aac , 0x7aa8 , 0x7aad , 0x7ab3 , 0x8864 , 0x8869 , 0x8872 , 0x887d , 0x887f , 0x8882 , 0x88a2 , 0x88c6 , 0x88b7 , 0x88bc , 0x88c9 , 0x88e2 , 0x88ce , 0x88e3 , 0x88e5 , 0x88f1 , 0x891a , 0x88fc , 0x88e8 , 0x88fe , 0x88f0 , 0x8921 , 0x8919 , 0x8913 , 0x891b , 0x890a , 0x8934 , 0x892b , 0x8936 , 0x8941 , 0x8966 , 0x897b , 0x758b , 0x80e5 , 0x76b2 , 0x76b4 , 0x77dc , 0x8012 , 0x8014 , 0x8016 , 0x801c , 0x8020 , 0x8022 , 0x8025 , 0x8026 , 0x8027 , 0x8029 , 0x8028 , 0x8031 , 0x800b , 0x8035 , 0x8043 , 0x8046 , 0x804d , 0x8052 , 0x8069 , 0x8071 , 0x8983 , 0x9878 , 0x9880 , 0x9883 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9889 , 0x988c , 0x988d , 0x988f , 0x9894 , 0x989a , 0x989b , 0x989e , 0x989f , 0x98a1 , 0x98a2 , 0x98a5 , 0x98a6 , 0x864d , 0x8654 , 0x866c , 0x866e , 0x867f , 0x867a , 0x867c , 0x867b , 0x86a8 , 0x868d , 0x868b , 0x86ac , 0x869d , 0x86a7 , 0x86a3 , 0x86aa , 0x8693 , 0x86a9 , 0x86b6 , 0x86c4 , 0x86b5 , 0x86ce , 0x86b0 , 0x86ba , 0x86b1 , 0x86af , 0x86c9 , 0x86cf , 0x86b4 , 0x86e9 , 0x86f1 , 0x86f2 , 0x86ed , 0x86f3 , 0x86d0 , 0x8713 , 0x86de , 0x86f4 , 0x86df , 0x86d8 , 0x86d1 , 0x8703 , 0x8707 , 0x86f8 , 0x8708 , 0x870a , 0x870d , 0x8709 , 0x8723 , 0x873b , 0x871e , 0x8725 , 0x872e , 0x871a , 0x873e , 0x8748 , 0x8734 , 0x8731 , 0x8729 , 0x8737 , 0x873f , 0x8782 , 0x8722 , 0x877d , 0x877e , 0x877b , 0x8760 , 0x8770 , 0x874c , 0x876e , 0x878b , 0x8753 , 0x8763 , 0x877c , 0x8764 , 0x8759 , 0x8765 , 0x8793 , 0x87af , 0x87a8 , 0x87d2 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x87c6 , 0x8788 , 0x8785 , 0x87ad , 0x8797 , 0x8783 , 0x87ab , 0x87e5 , 0x87ac , 0x87b5 , 0x87b3 , 0x87cb , 0x87d3 , 0x87bd , 0x87d1 , 0x87c0 , 0x87ca , 0x87db , 0x87ea , 0x87e0 , 0x87ee , 0x8816 , 0x8813 , 0x87fe , 0x880a , 0x881b , 0x8821 , 0x8839 , 0x883c , 0x7f36 , 0x7f42 , 0x7f44 , 0x7f45 , 0x8210 , 0x7afa , 0x7afd , 0x7b08 , 0x7b03 , 0x7b04 , 0x7b15 , 0x7b0a , 0x7b2b , 0x7b0f , 0x7b47 , 0x7b38 , 0x7b2a , 0x7b19 , 0x7b2e , 0x7b31 , 0x7b20 , 0x7b25 , 0x7b24 , 0x7b33 , 0x7b3e , 0x7b1e , 0x7b58 , 0x7b5a , 0x7b45 , 0x7b75 , 0x7b4c , 0x7b5d , 0x7b60 , 0x7b6e , 0x7b7b , 0x7b62 , 0x7b72 , 0x7b71 , 0x7b90 , 0x7ba6 , 0x7ba7 , 0x7bb8 , 0x7bac , 0x7b9d , 0x7ba8 , 0x7b85 , 0x7baa , 0x7b9c , 0x7ba2 , 0x7bab , 0x7bb4 , 0x7bd1 , 0x7bc1 , 0x7bcc , 0x7bdd , 0x7bda , 0x7be5 , 0x7be6 , 0x7bea , 0x7c0c , 0x7bfe , 0x7bfc , 0x7c0f , 0x7c16 , 0x7c0b , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x7c1f , 0x7c2a , 0x7c26 , 0x7c38 , 0x7c41 , 0x7c40 , 0x81fe , 0x8201 , 0x8202 , 0x8204 , 0x81ec , 0x8844 , 0x8221 , 0x8222 , 0x8223 , 0x822d , 0x822f , 0x8228 , 0x822b , 0x8238 , 0x823b , 0x8233 , 0x8234 , 0x823e , 0x8244 , 0x8249 , 0x824b , 0x824f , 0x825a , 0x825f , 0x8268 , 0x887e , 0x8885 , 0x8888 , 0x88d8 , 0x88df , 0x895e , 0x7f9d , 0x7f9f , 0x7fa7 , 0x7faf , 0x7fb0 , 0x7fb2 , 0x7c7c , 0x6549 , 0x7c91 , 0x7c9d , 0x7c9c , 0x7c9e , 0x7ca2 , 0x7cb2 , 0x7cbc , 0x7cbd , 0x7cc1 , 0x7cc7 , 0x7ccc , 0x7ccd , 0x7cc8 , 0x7cc5 , 0x7cd7 , 0x7ce8 , 0x826e , 0x66a8 , 0x7fbf , 0x7fce , 0x7fd5 , 0x7fe5 , 0x7fe1 , 0x7fe6 , 0x7fe9 , 0x7fee , 0x7ff3 , 0x7cf8 , 0x7d77 , 0x7da6 , 0x7dae , 0x7e47 , 0x7e9b , 0x9eb8 , 0x9eb4 , 0x8d73 , 0x8d84 , 0x8d94 , 0x8d91 , 0x8db1 , 0x8d67 , 0x8d6d , 0x8c47 , 0x8c49 , 0x914a , 0x9150 , 0x914e , 0x914f , 0x9164 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9162 , 0x9161 , 0x9170 , 0x9169 , 0x916f , 0x917d , 0x917e , 0x9172 , 0x9174 , 0x9179 , 0x918c , 0x9185 , 0x9190 , 0x918d , 0x9191 , 0x91a2 , 0x91a3 , 0x91aa , 0x91ad , 0x91ae , 0x91af , 0x91b5 , 0x91b4 , 0x91ba , 0x8c55 , 0x9e7e , 0x8db8 , 0x8deb , 0x8e05 , 0x8e59 , 0x8e69 , 0x8db5 , 0x8dbf , 0x8dbc , 0x8dba , 0x8dc4 , 0x8dd6 , 0x8dd7 , 0x8dda , 0x8dde , 0x8dce , 0x8dcf , 0x8ddb , 0x8dc6 , 0x8dec , 0x8df7 , 0x8df8 , 0x8de3 , 0x8df9 , 0x8dfb , 0x8de4 , 0x8e09 , 0x8dfd , 0x8e14 , 0x8e1d , 0x8e1f , 0x8e2c , 0x8e2e , 0x8e23 , 0x8e2f , 0x8e3a , 0x8e40 , 0x8e39 , 0x8e35 , 0x8e3d , 0x8e31 , 0x8e49 , 0x8e41 , 0x8e42 , 0x8e51 , 0x8e52 , 0x8e4a , 0x8e70 , 0x8e76 , 0x8e7c , 0x8e6f , 0x8e74 , 0x8e85 , 0x8e8f , 0x8e94 , 0x8e90 , 0x8e9c , 0x8e9e , 0x8c78 , 0x8c82 , 0x8c8a , 0x8c85 , 0x8c98 , 0x8c94 , 0x659b , 0x89d6 , 0x89de , 0x89da , 0x89dc , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x89e5 , 0x89eb , 0x89ef , 0x8a3e , 0x8b26 , 0x9753 , 0x96e9 , 0x96f3 , 0x96ef , 0x9706 , 0x9701 , 0x9708 , 0x970f , 0x970e , 0x972a , 0x972d , 0x9730 , 0x973e , 0x9f80 , 0x9f83 , 0x9f85 , 0x9f86 , 0x9f87 , 0x9f88 , 0x9f89 , 0x9f8a , 0x9f8c , 0x9efe , 0x9f0b , 0x9f0d , 0x96b9 , 0x96bc , 0x96bd , 0x96ce , 0x96d2 , 0x77bf , 0x96e0 , 0x928e , 0x92ae , 0x92c8 , 0x933e , 0x936a , 0x93ca , 0x938f , 0x943e , 0x946b , 0x9c7f , 0x9c82 , 0x9c85 , 0x9c86 , 0x9c87 , 0x9c88 , 0x7a23 , 0x9c8b , 0x9c8e , 0x9c90 , 0x9c91 , 0x9c92 , 0x9c94 , 0x9c95 , 0x9c9a , 0x9c9b , 0x9c9e , 0x9c9f , 0x9ca0 , 0x9ca1 , 0x9ca2 , 0x9ca3 , 0x9ca5 , 0x9ca6 , 0x9ca7 , 0x9ca8 , 0x9ca9 , 0x9cab , 0x9cad , 0x9cae , 0x9cb0 , 0x9cb1 , 0x9cb2 , 0x9cb3 , 0x9cb4 , 0x9cb5 , 0x9cb6 , 0x9cb7 , 0x9cba , 0x9cbb , 0x9cbc , 0x9cbd , 0x9cc4 , 0x9cc5 , 0x9cc6 , 0x9cc7 , 0x9cca , 0x9ccb , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0x9ccc , 0x9ccd , 0x9cce , 0x9ccf , 0x9cd0 , 0x9cd3 , 0x9cd4 , 0x9cd5 , 0x9cd7 , 0x9cd8 , 0x9cd9 , 0x9cdc , 0x9cdd , 0x9cdf , 0x9ce2 , 0x977c , 0x9785 , 0x9791 , 0x9792 , 0x9794 , 0x97af , 0x97ab , 0x97a3 , 0x97b2 , 0x97b4 , 0x9ab1 , 0x9ab0 , 0x9ab7 , 0x9e58 , 0x9ab6 , 0x9aba , 0x9abc , 0x9ac1 , 0x9ac0 , 0x9ac5 , 0x9ac2 , 0x9acb , 0x9acc , 0x9ad1 , 0x9b45 , 0x9b43 , 0x9b47 , 0x9b49 , 0x9b48 , 0x9b4d , 0x9b51 , 0x98e8 , 0x990d , 0x992e , 0x9955 , 0x9954 , 0x9adf , 0x9ae1 , 0x9ae6 , 0x9aef , 0x9aeb , 0x9afb , 0x9aed , 0x9af9 , 0x9b08 , 0x9b0f , 0x9b13 , 0x9b1f , 0x9b23 , 0x9ebd , 0x9ebe , 0x7e3b , 0x9e82 , 0x9e87 , 0x9e88 , 0x9e8b , 0x9e92 , 0x93d6 , 0x9e9d , 0x9e9f , 0x9edb , 0x9edc , 0x9edd , 0x9ee0 , 0x9edf , 0x9ee2 , 0x9ee9 , 0x9ee7 , 0x9ee5 , 0x9eea , 0x9eef , 0x9f22 , 0x9f2c , 0x9f2f , 0x9f39 , 0x9f37 , 0x9f3d , 0x9f3e , 0x9f44 }; static tb_uint16_t g_charset_ucs4_to_gb2312_table_data[][2] = { // ucs4, gb2312 {0x00a4, 0xa1e8}, /* '¤' -> 164 */ {0x00a7, 0xa1ec}, /* '§' -> 167 */ {0x00a8, 0xa1a7}, /* '¨' -> 168 */ {0x00b0, 0xa1e3}, /* '°' -> 176 */ {0x00b1, 0xa1c0}, /* '±' -> 177 */ {0x00d7, 0xa1c1}, /* '×' -> 215 */ {0x00e0, 0xa8a4}, /* 'à' -> 224 */ {0x00e1, 0xa8a2}, /* 'á' -> 225 */ {0x00e8, 0xa8a8}, /* 'è' -> 232 */ {0x00e9, 0xa8a6}, /* 'é' -> 233 */ {0x00ea, 0xa8ba}, /* 'ê' -> 234 */ {0x00ec, 0xa8ac}, /* 'ì' -> 236 */ {0x00ed, 0xa8aa}, /* 'í' -> 237 */ {0x00f2, 0xa8b0}, /* 'ò' -> 242 */ {0x00f3, 0xa8ae}, /* 'ó' -> 243 */ {0x00f7, 0xa1c2}, /* '÷' -> 247 */ {0x00f9, 0xa8b4}, /* 'ù' -> 249 */ {0x00fa, 0xa8b2}, /* 'ú' -> 250 */ {0x00fc, 0xa8b9}, /* 'ü' -> 252 */ {0x0101, 0xa8a1}, /* 'ā' -> 257 */ {0x0113, 0xa8a5}, /* 'ē' -> 275 */ {0x011b, 0xa8a7}, /* 'ě' -> 283 */ {0x012b, 0xa8a9}, /* 'ī' -> 299 */ {0x014d, 0xa8ad}, /* 'ō' -> 333 */ {0x016b, 0xa8b1}, /* 'ū' -> 363 */ {0x01ce, 0xa8a3}, /* 'ǎ' -> 462 */ {0x01d0, 0xa8ab}, /* 'ǐ' -> 464 */ {0x01d2, 0xa8af}, /* 'ǒ' -> 466 */ {0x01d4, 0xa8b3}, /* 'ǔ' -> 468 */ {0x01d6, 0xa8b5}, /* 'ǖ' -> 470 */ {0x01d8, 0xa8b6}, /* 'ǘ' -> 472 */ {0x01da, 0xa8b7}, /* 'ǚ' -> 474 */ {0x01dc, 0xa8b8}, /* 'ǜ' -> 476 */ {0x02c7, 0xa1a6}, /* 'ˇ' -> 711 */ {0x02c9, 0xa1a5}, /* 'ˉ' -> 713 */ {0x0391, 0xa6a1}, /* 'α' -> 913 */ {0x0392, 0xa6a2}, /* 'β' -> 914 */ {0x0393, 0xa6a3}, /* 'γ' -> 915 */ {0x0394, 0xa6a4}, /* 'δ' -> 916 */ {0x0395, 0xa6a5}, /* 'ε' -> 917 */ {0x0396, 0xa6a6}, /* 'ζ' -> 918 */ {0x0397, 0xa6a7}, /* 'η' -> 919 */ {0x0398, 0xa6a8}, /* 'θ' -> 920 */ {0x0399, 0xa6a9}, /* 'ι' -> 921 */ {0x039a, 0xa6aa}, /* 'κ' -> 922 */ {0x039b, 0xa6ab}, /* 'λ' -> 923 */ {0x039c, 0xa6ac}, /* 'μ' -> 924 */ {0x039d, 0xa6ad}, /* 'ν' -> 925 */ {0x039e, 0xa6ae}, /* 'ξ' -> 926 */ {0x039f, 0xa6af}, /* 'ο' -> 927 */ {0x03a0, 0xa6b0}, /* 'π' -> 928 */ {0x03a1, 0xa6b1}, /* 'ρ' -> 929 */ {0x03a3, 0xa6b2}, /* 'σ' -> 931 */ {0x03a4, 0xa6b3}, /* 'τ' -> 932 */ {0x03a5, 0xa6b4}, /* 'υ' -> 933 */ {0x03a6, 0xa6b5}, /* 'φ' -> 934 */ {0x03a7, 0xa6b6}, /* 'χ' -> 935 */ {0x03a8, 0xa6b7}, /* 'ψ' -> 936 */ {0x03a9, 0xa6b8}, /* 'ω' -> 937 */ {0x03b1, 0xa6c1}, /* 'α' -> 945 */ {0x03b2, 0xa6c2}, /* 'β' -> 946 */ {0x03b3, 0xa6c3}, /* 'γ' -> 947 */ {0x03b4, 0xa6c4}, /* 'δ' -> 948 */ {0x03b5, 0xa6c5}, /* 'ε' -> 949 */ {0x03b6, 0xa6c6}, /* 'ζ' -> 950 */ {0x03b7, 0xa6c7}, /* 'η' -> 951 */ {0x03b8, 0xa6c8}, /* 'θ' -> 952 */ {0x03b9, 0xa6c9}, /* 'ι' -> 953 */ {0x03ba, 0xa6ca}, /* 'κ' -> 954 */ {0x03bb, 0xa6cb}, /* 'λ' -> 955 */ {0x03bc, 0xa6cc}, /* 'μ' -> 956 */ {0x03bd, 0xa6cd}, /* 'ν' -> 957 */ {0x03be, 0xa6ce}, /* 'ξ' -> 958 */ {0x03bf, 0xa6cf}, /* 'ο' -> 959 */ {0x03c0, 0xa6d0}, /* 'π' -> 960 */ {0x03c1, 0xa6d1}, /* 'ρ' -> 961 */ {0x03c3, 0xa6d2}, /* 'σ' -> 963 */ {0x03c4, 0xa6d3}, /* 'τ' -> 964 */ {0x03c5, 0xa6d4}, /* 'υ' -> 965 */ {0x03c6, 0xa6d5}, /* 'φ' -> 966 */ {0x03c7, 0xa6d6}, /* 'χ' -> 967 */ {0x03c8, 0xa6d7}, /* 'ψ' -> 968 */ {0x03c9, 0xa6d8}, /* 'ω' -> 969 */ {0x0401, 0xa7a7}, /* 'ё' -> 1025 */ {0x0410, 0xa7a1}, /* 'а' -> 1040 */ {0x0411, 0xa7a2}, /* 'б' -> 1041 */ {0x0412, 0xa7a3}, /* 'в' -> 1042 */ {0x0413, 0xa7a4}, /* 'г' -> 1043 */ {0x0414, 0xa7a5}, /* 'д' -> 1044 */ {0x0415, 0xa7a6}, /* 'е' -> 1045 */ {0x0416, 0xa7a8}, /* 'ж' -> 1046 */ {0x0417, 0xa7a9}, /* 'з' -> 1047 */ {0x0418, 0xa7aa}, /* 'и' -> 1048 */ {0x0419, 0xa7ab}, /* 'й' -> 1049 */ {0x041a, 0xa7ac}, /* 'к' -> 1050 */ {0x041b, 0xa7ad}, /* 'л' -> 1051 */ {0x041c, 0xa7ae}, /* 'м' -> 1052 */ {0x041d, 0xa7af}, /* 'н' -> 1053 */ {0x041e, 0xa7b0}, /* 'о' -> 1054 */ {0x041f, 0xa7b1}, /* 'п' -> 1055 */ {0x0420, 0xa7b2}, /* 'р' -> 1056 */ {0x0421, 0xa7b3}, /* 'с' -> 1057 */ {0x0422, 0xa7b4}, /* 'т' -> 1058 */ {0x0423, 0xa7b5}, /* 'у' -> 1059 */ {0x0424, 0xa7b6}, /* 'ф' -> 1060 */ {0x0425, 0xa7b7}, /* 'х' -> 1061 */ {0x0426, 0xa7b8}, /* 'ц' -> 1062 */ {0x0427, 0xa7b9}, /* 'ч' -> 1063 */ {0x0428, 0xa7ba}, /* 'ш' -> 1064 */ {0x0429, 0xa7bb}, /* 'щ' -> 1065 */ {0x042a, 0xa7bc}, /* 'ъ' -> 1066 */ {0x042b, 0xa7bd}, /* 'ы' -> 1067 */ {0x042c, 0xa7be}, /* 'ь' -> 1068 */ {0x042d, 0xa7bf}, /* 'э' -> 1069 */ {0x042e, 0xa7c0}, /* 'ю' -> 1070 */ {0x042f, 0xa7c1}, /* 'я' -> 1071 */ {0x0430, 0xa7d1}, /* 'а' -> 1072 */ {0x0431, 0xa7d2}, /* 'б' -> 1073 */ {0x0432, 0xa7d3}, /* 'в' -> 1074 */ {0x0433, 0xa7d4}, /* 'г' -> 1075 */ {0x0434, 0xa7d5}, /* 'д' -> 1076 */ {0x0435, 0xa7d6}, /* 'е' -> 1077 */ {0x0436, 0xa7d8}, /* 'ж' -> 1078 */ {0x0437, 0xa7d9}, /* 'з' -> 1079 */ {0x0438, 0xa7da}, /* 'и' -> 1080 */ {0x0439, 0xa7db}, /* 'й' -> 1081 */ {0x043a, 0xa7dc}, /* 'к' -> 1082 */ {0x043b, 0xa7dd}, /* 'л' -> 1083 */ {0x043c, 0xa7de}, /* 'м' -> 1084 */ {0x043d, 0xa7df}, /* 'н' -> 1085 */ {0x043e, 0xa7e0}, /* 'о' -> 1086 */ {0x043f, 0xa7e1}, /* 'п' -> 1087 */ {0x0440, 0xa7e2}, /* 'р' -> 1088 */ {0x0441, 0xa7e3}, /* 'с' -> 1089 */ {0x0442, 0xa7e4}, /* 'т' -> 1090 */ {0x0443, 0xa7e5}, /* 'у' -> 1091 */ {0x0444, 0xa7e6}, /* 'ф' -> 1092 */ {0x0445, 0xa7e7}, /* 'х' -> 1093 */ {0x0446, 0xa7e8}, /* 'ц' -> 1094 */ {0x0447, 0xa7e9}, /* 'ч' -> 1095 */ {0x0448, 0xa7ea}, /* 'ш' -> 1096 */ {0x0449, 0xa7eb}, /* 'щ' -> 1097 */ {0x044a, 0xa7ec}, /* 'ъ' -> 1098 */ {0x044b, 0xa7ed}, /* 'ы' -> 1099 */ {0x044c, 0xa7ee}, /* 'ь' -> 1100 */ {0x044d, 0xa7ef}, /* 'э' -> 1101 */ {0x044e, 0xa7f0}, /* 'ю' -> 1102 */ {0x044f, 0xa7f1}, /* 'я' -> 1103 */ {0x0451, 0xa7d7}, /* 'ё' -> 1105 */ {0x2015, 0xa1aa}, /* '―' -> 8213 */ {0x2016, 0xa1ac}, /* '‖' -> 8214 */ {0x2018, 0xa1ae}, /* '‘' -> 8216 */ {0x2019, 0xa1af}, /* '’' -> 8217 */ {0x201c, 0xa1b0}, /* '“' -> 8220 */ {0x201d, 0xa1b1}, /* '”' -> 8221 */ {0x2026, 0xa1ad}, /* '…' -> 8230 */ {0x2030, 0xa1eb}, /* '‰' -> 8240 */ {0x2032, 0xa1e4}, /* '′' -> 8242 */ {0x2033, 0xa1e5}, /* '″' -> 8243 */ {0x203b, 0xa1f9}, /* '※' -> 8251 */ {0x2103, 0xa1e6}, /* '℃' -> 8451 */ {0x2116, 0xa1ed}, /* '№' -> 8470 */ {0x2160, 0xa2f1}, /* 'ⅰ' -> 8544 */ {0x2161, 0xa2f2}, /* 'ⅱ' -> 8545 */ {0x2162, 0xa2f3}, /* 'ⅲ' -> 8546 */ {0x2163, 0xa2f4}, /* 'ⅳ' -> 8547 */ {0x2164, 0xa2f5}, /* 'ⅴ' -> 8548 */ {0x2165, 0xa2f6}, /* 'ⅵ' -> 8549 */ {0x2166, 0xa2f7}, /* 'ⅶ' -> 8550 */ {0x2167, 0xa2f8}, /* 'ⅷ' -> 8551 */ {0x2168, 0xa2f9}, /* 'ⅸ' -> 8552 */ {0x2169, 0xa2fa}, /* 'ⅹ' -> 8553 */ {0x216a, 0xa2fb}, /* 'ⅺ' -> 8554 */ {0x216b, 0xa2fc}, /* 'ⅻ' -> 8555 */ {0x2190, 0xa1fb}, /* '←' -> 8592 */ {0x2191, 0xa1fc}, /* '↑' -> 8593 */ {0x2192, 0xa1fa}, /* '→' -> 8594 */ {0x2193, 0xa1fd}, /* '↓' -> 8595 */ {0x2208, 0xa1ca}, /* '∈' -> 8712 */ {0x220f, 0xa1c7}, /* '∏' -> 8719 */ {0x2211, 0xa1c6}, /* '∑' -> 8721 */ {0x221a, 0xa1cc}, /* '√' -> 8730 */ {0x221d, 0xa1d8}, /* '∝' -> 8733 */ {0x221e, 0xa1de}, /* '∞' -> 8734 */ {0x2220, 0xa1cf}, /* '∠' -> 8736 */ {0x2225, 0xa1ce}, /* '∥' -> 8741 */ {0x2227, 0xa1c4}, /* '∧' -> 8743 */ {0x2228, 0xa1c5}, /* '∨' -> 8744 */ {0x2229, 0xa1c9}, /* '∩' -> 8745 */ {0x222a, 0xa1c8}, /* '∪' -> 8746 */ {0x222b, 0xa1d2}, /* '∫' -> 8747 */ {0x222e, 0xa1d3}, /* '∮' -> 8750 */ {0x2234, 0xa1e0}, /* '∴' -> 8756 */ {0x2235, 0xa1df}, /* '∵' -> 8757 */ {0x2236, 0xa1c3}, /* '∶' -> 8758 */ {0x2237, 0xa1cb}, /* '∷' -> 8759 */ {0x223d, 0xa1d7}, /* '∽' -> 8765 */ {0x2248, 0xa1d6}, /* '≈' -> 8776 */ {0x224c, 0xa1d5}, /* '≌' -> 8780 */ {0x2260, 0xa1d9}, /* '≠' -> 8800 */ {0x2261, 0xa1d4}, /* '≡' -> 8801 */ {0x2264, 0xa1dc}, /* '≤' -> 8804 */ {0x2265, 0xa1dd}, /* '≥' -> 8805 */ {0x226e, 0xa1da}, /* '≮' -> 8814 */ {0x226f, 0xa1db}, /* '≯' -> 8815 */ {0x2299, 0xa1d1}, /* '⊙' -> 8857 */ {0x22a5, 0xa1cd}, /* '⊥' -> 8869 */ {0x2312, 0xa1d0}, /* '⌒' -> 8978 */ {0x2460, 0xa2d9}, /* '①' -> 9312 */ {0x2461, 0xa2da}, /* '②' -> 9313 */ {0x2462, 0xa2db}, /* '③' -> 9314 */ {0x2463, 0xa2dc}, /* '④' -> 9315 */ {0x2464, 0xa2dd}, /* '⑤' -> 9316 */ {0x2465, 0xa2de}, /* '⑥' -> 9317 */ {0x2466, 0xa2df}, /* '⑦' -> 9318 */ {0x2467, 0xa2e0}, /* '⑧' -> 9319 */ {0x2468, 0xa2e1}, /* '⑨' -> 9320 */ {0x2469, 0xa2e2}, /* '⑩' -> 9321 */ {0x2474, 0xa2c5}, /* '⑴' -> 9332 */ {0x2475, 0xa2c6}, /* '⑵' -> 9333 */ {0x2476, 0xa2c7}, /* '⑶' -> 9334 */ {0x2477, 0xa2c8}, /* '⑷' -> 9335 */ {0x2478, 0xa2c9}, /* '⑸' -> 9336 */ {0x2479, 0xa2ca}, /* '⑹' -> 9337 */ {0x247a, 0xa2cb}, /* '⑺' -> 9338 */ {0x247b, 0xa2cc}, /* '⑻' -> 9339 */ {0x247c, 0xa2cd}, /* '⑼' -> 9340 */ {0x247d, 0xa2ce}, /* '⑽' -> 9341 */ {0x247e, 0xa2cf}, /* '⑾' -> 9342 */ {0x247f, 0xa2d0}, /* '⑿' -> 9343 */ {0x2480, 0xa2d1}, /* '⒀' -> 9344 */ {0x2481, 0xa2d2}, /* '⒁' -> 9345 */ {0x2482, 0xa2d3}, /* '⒂' -> 9346 */ {0x2483, 0xa2d4}, /* '⒃' -> 9347 */ {0x2484, 0xa2d5}, /* '⒄' -> 9348 */ {0x2485, 0xa2d6}, /* '⒅' -> 9349 */ {0x2486, 0xa2d7}, /* '⒆' -> 9350 */ {0x2487, 0xa2d8}, /* '⒇' -> 9351 */ {0x2488, 0xa2b1}, /* '⒈' -> 9352 */ {0x2489, 0xa2b2}, /* '⒉' -> 9353 */ {0x248a, 0xa2b3}, /* '⒊' -> 9354 */ {0x248b, 0xa2b4}, /* '⒋' -> 9355 */ {0x248c, 0xa2b5}, /* '⒌' -> 9356 */ {0x248d, 0xa2b6}, /* '⒍' -> 9357 */ {0x248e, 0xa2b7}, /* '⒎' -> 9358 */ {0x248f, 0xa2b8}, /* '⒏' -> 9359 */ {0x2490, 0xa2b9}, /* '⒐' -> 9360 */ {0x2491, 0xa2ba}, /* '⒑' -> 9361 */ {0x2492, 0xa2bb}, /* '⒒' -> 9362 */ {0x2493, 0xa2bc}, /* '⒓' -> 9363 */ {0x2494, 0xa2bd}, /* '⒔' -> 9364 */ {0x2495, 0xa2be}, /* '⒕' -> 9365 */ {0x2496, 0xa2bf}, /* '⒖' -> 9366 */ {0x2497, 0xa2c0}, /* '⒗' -> 9367 */ {0x2498, 0xa2c1}, /* '⒘' -> 9368 */ {0x2499, 0xa2c2}, /* '⒙' -> 9369 */ {0x249a, 0xa2c3}, /* '⒚' -> 9370 */ {0x249b, 0xa2c4}, /* '⒛' -> 9371 */ {0x2500, 0xa9a4}, /* '─' -> 9472 */ {0x2501, 0xa9a5}, /* '━' -> 9473 */ {0x2502, 0xa9a6}, /* '│' -> 9474 */ {0x2503, 0xa9a7}, /* '┃' -> 9475 */ {0x2504, 0xa9a8}, /* '┄' -> 9476 */ {0x2505, 0xa9a9}, /* '┅' -> 9477 */ {0x2506, 0xa9aa}, /* '┆' -> 9478 */ {0x2507, 0xa9ab}, /* '┇' -> 9479 */ {0x2508, 0xa9ac}, /* '┈' -> 9480 */ {0x2509, 0xa9ad}, /* '┉' -> 9481 */ {0x250a, 0xa9ae}, /* '┊' -> 9482 */ {0x250b, 0xa9af}, /* '┋' -> 9483 */ {0x250c, 0xa9b0}, /* '┌' -> 9484 */ {0x250d, 0xa9b1}, /* '┍' -> 9485 */ {0x250e, 0xa9b2}, /* '┎' -> 9486 */ {0x250f, 0xa9b3}, /* '┏' -> 9487 */ {0x2510, 0xa9b4}, /* '┐' -> 9488 */ {0x2511, 0xa9b5}, /* '┑' -> 9489 */ {0x2512, 0xa9b6}, /* '┒' -> 9490 */ {0x2513, 0xa9b7}, /* '┓' -> 9491 */ {0x2514, 0xa9b8}, /* '└' -> 9492 */ {0x2515, 0xa9b9}, /* '┕' -> 9493 */ {0x2516, 0xa9ba}, /* '┖' -> 9494 */ {0x2517, 0xa9bb}, /* '┗' -> 9495 */ {0x2518, 0xa9bc}, /* '┘' -> 9496 */ {0x2519, 0xa9bd}, /* '┙' -> 9497 */ {0x251a, 0xa9be}, /* '┚' -> 9498 */ {0x251b, 0xa9bf}, /* '┛' -> 9499 */ {0x251c, 0xa9c0}, /* '├' -> 9500 */ {0x251d, 0xa9c1}, /* '┝' -> 9501 */ {0x251e, 0xa9c2}, /* '┞' -> 9502 */ {0x251f, 0xa9c3}, /* '┟' -> 9503 */ {0x2520, 0xa9c4}, /* '┠' -> 9504 */ {0x2521, 0xa9c5}, /* '┡' -> 9505 */ {0x2522, 0xa9c6}, /* '┢' -> 9506 */ {0x2523, 0xa9c7}, /* '┣' -> 9507 */ {0x2524, 0xa9c8}, /* '┤' -> 9508 */ {0x2525, 0xa9c9}, /* '┥' -> 9509 */ {0x2526, 0xa9ca}, /* '┦' -> 9510 */ {0x2527, 0xa9cb}, /* '┧' -> 9511 */ {0x2528, 0xa9cc}, /* '┨' -> 9512 */ {0x2529, 0xa9cd}, /* '┩' -> 9513 */ {0x252a, 0xa9ce}, /* '┪' -> 9514 */ {0x252b, 0xa9cf}, /* '┫' -> 9515 */ {0x252c, 0xa9d0}, /* '┬' -> 9516 */ {0x252d, 0xa9d1}, /* '┭' -> 9517 */ {0x252e, 0xa9d2}, /* '┮' -> 9518 */ {0x252f, 0xa9d3}, /* '┯' -> 9519 */ {0x2530, 0xa9d4}, /* '┰' -> 9520 */ {0x2531, 0xa9d5}, /* '┱' -> 9521 */ {0x2532, 0xa9d6}, /* '┲' -> 9522 */ {0x2533, 0xa9d7}, /* '┳' -> 9523 */ {0x2534, 0xa9d8}, /* '┴' -> 9524 */ {0x2535, 0xa9d9}, /* '┵' -> 9525 */ {0x2536, 0xa9da}, /* '┶' -> 9526 */ {0x2537, 0xa9db}, /* '┷' -> 9527 */ {0x2538, 0xa9dc}, /* '┸' -> 9528 */ {0x2539, 0xa9dd}, /* '┹' -> 9529 */ {0x253a, 0xa9de}, /* '┺' -> 9530 */ {0x253b, 0xa9df}, /* '┻' -> 9531 */ {0x253c, 0xa9e0}, /* '┼' -> 9532 */ {0x253d, 0xa9e1}, /* '┽' -> 9533 */ {0x253e, 0xa9e2}, /* '┾' -> 9534 */ {0x253f, 0xa9e3}, /* '┿' -> 9535 */ {0x2540, 0xa9e4}, /* '╀' -> 9536 */ {0x2541, 0xa9e5}, /* '╁' -> 9537 */ {0x2542, 0xa9e6}, /* '╂' -> 9538 */ {0x2543, 0xa9e7}, /* '╃' -> 9539 */ {0x2544, 0xa9e8}, /* '╄' -> 9540 */ {0x2545, 0xa9e9}, /* '╅' -> 9541 */ {0x2546, 0xa9ea}, /* '╆' -> 9542 */ {0x2547, 0xa9eb}, /* '╇' -> 9543 */ {0x2548, 0xa9ec}, /* '╈' -> 9544 */ {0x2549, 0xa9ed}, /* '╉' -> 9545 */ {0x254a, 0xa9ee}, /* '╊' -> 9546 */ {0x254b, 0xa9ef}, /* '╋' -> 9547 */ {0x25a0, 0xa1f6}, /* '■' -> 9632 */ {0x25a1, 0xa1f5}, /* '□' -> 9633 */ {0x25b2, 0xa1f8}, /* '▲' -> 9650 */ {0x25b3, 0xa1f7}, /* '△' -> 9651 */ {0x25c6, 0xa1f4}, /* '◆' -> 9670 */ {0x25c7, 0xa1f3}, /* '◇' -> 9671 */ {0x25cb, 0xa1f0}, /* '○' -> 9675 */ {0x25ce, 0xa1f2}, /* '◎' -> 9678 */ {0x25cf, 0xa1f1}, /* '●' -> 9679 */ {0x2605, 0xa1ef}, /* '★' -> 9733 */ {0x2606, 0xa1ee}, /* '☆' -> 9734 */ {0x2640, 0xa1e2}, /* '♀' -> 9792 */ {0x2642, 0xa1e1}, /* '♂' -> 9794 */ {0x3000, 0xa1a1}, /* ' ' -> 12288 */ {0x3001, 0xa1a2}, /* '、' -> 12289 */ {0x3002, 0xa1a3}, /* '。' -> 12290 */ {0x3003, 0xa1a8}, /* '〃' -> 12291 */ {0x3005, 0xa1a9}, /* '々' -> 12293 */ {0x3008, 0xa1b4}, /* '〈' -> 12296 */ {0x3009, 0xa1b5}, /* '〉' -> 12297 */ {0x300a, 0xa1b6}, /* '《' -> 12298 */ {0x300b, 0xa1b7}, /* '》' -> 12299 */ {0x300c, 0xa1b8}, /* '「' -> 12300 */ {0x300d, 0xa1b9}, /* '」' -> 12301 */ {0x300e, 0xa1ba}, /* '『' -> 12302 */ {0x300f, 0xa1bb}, /* '』' -> 12303 */ {0x3010, 0xa1be}, /* '【' -> 12304 */ {0x3011, 0xa1bf}, /* '】' -> 12305 */ {0x3013, 0xa1fe}, /* '〓' -> 12307 */ {0x3014, 0xa1b2}, /* '〔' -> 12308 */ {0x3015, 0xa1b3}, /* '〕' -> 12309 */ {0x3016, 0xa1bc}, /* '〖' -> 12310 */ {0x3017, 0xa1bd}, /* '〗' -> 12311 */ {0x3041, 0xa4a1}, /* 'ぁ' -> 12353 */ {0x3042, 0xa4a2}, /* 'あ' -> 12354 */ {0x3043, 0xa4a3}, /* 'ぃ' -> 12355 */ {0x3044, 0xa4a4}, /* 'い' -> 12356 */ {0x3045, 0xa4a5}, /* 'ぅ' -> 12357 */ {0x3046, 0xa4a6}, /* 'う' -> 12358 */ {0x3047, 0xa4a7}, /* 'ぇ' -> 12359 */ {0x3048, 0xa4a8}, /* 'え' -> 12360 */ {0x3049, 0xa4a9}, /* 'ぉ' -> 12361 */ {0x304a, 0xa4aa}, /* 'お' -> 12362 */ {0x304b, 0xa4ab}, /* 'か' -> 12363 */ {0x304c, 0xa4ac}, /* 'が' -> 12364 */ {0x304d, 0xa4ad}, /* 'き' -> 12365 */ {0x304e, 0xa4ae}, /* 'ぎ' -> 12366 */ {0x304f, 0xa4af}, /* 'く' -> 12367 */ {0x3050, 0xa4b0}, /* 'ぐ' -> 12368 */ {0x3051, 0xa4b1}, /* 'け' -> 12369 */ {0x3052, 0xa4b2}, /* 'げ' -> 12370 */ {0x3053, 0xa4b3}, /* 'こ' -> 12371 */ {0x3054, 0xa4b4}, /* 'ご' -> 12372 */ {0x3055, 0xa4b5}, /* 'さ' -> 12373 */ {0x3056, 0xa4b6}, /* 'ざ' -> 12374 */ {0x3057, 0xa4b7}, /* 'し' -> 12375 */ {0x3058, 0xa4b8}, /* 'じ' -> 12376 */ {0x3059, 0xa4b9}, /* 'す' -> 12377 */ {0x305a, 0xa4ba}, /* 'ず' -> 12378 */ {0x305b, 0xa4bb}, /* 'せ' -> 12379 */ {0x305c, 0xa4bc}, /* 'ぜ' -> 12380 */ {0x305d, 0xa4bd}, /* 'そ' -> 12381 */ {0x305e, 0xa4be}, /* 'ぞ' -> 12382 */ {0x305f, 0xa4bf}, /* 'た' -> 12383 */ {0x3060, 0xa4c0}, /* 'だ' -> 12384 */ {0x3061, 0xa4c1}, /* 'ち' -> 12385 */ {0x3062, 0xa4c2}, /* 'ぢ' -> 12386 */ {0x3063, 0xa4c3}, /* 'っ' -> 12387 */ {0x3064, 0xa4c4}, /* 'つ' -> 12388 */ {0x3065, 0xa4c5}, /* 'づ' -> 12389 */ {0x3066, 0xa4c6}, /* 'て' -> 12390 */ {0x3067, 0xa4c7}, /* 'で' -> 12391 */ {0x3068, 0xa4c8}, /* 'と' -> 12392 */ {0x3069, 0xa4c9}, /* 'ど' -> 12393 */ {0x306a, 0xa4ca}, /* 'な' -> 12394 */ {0x306b, 0xa4cb}, /* 'に' -> 12395 */ {0x306c, 0xa4cc}, /* 'ぬ' -> 12396 */ {0x306d, 0xa4cd}, /* 'ね' -> 12397 */ {0x306e, 0xa4ce}, /* 'の' -> 12398 */ {0x306f, 0xa4cf}, /* 'は' -> 12399 */ {0x3070, 0xa4d0}, /* 'ば' -> 12400 */ {0x3071, 0xa4d1}, /* 'ぱ' -> 12401 */ {0x3072, 0xa4d2}, /* 'ひ' -> 12402 */ {0x3073, 0xa4d3}, /* 'び' -> 12403 */ {0x3074, 0xa4d4}, /* 'ぴ' -> 12404 */ {0x3075, 0xa4d5}, /* 'ふ' -> 12405 */ {0x3076, 0xa4d6}, /* 'ぶ' -> 12406 */ {0x3077, 0xa4d7}, /* 'ぷ' -> 12407 */ {0x3078, 0xa4d8}, /* 'へ' -> 12408 */ {0x3079, 0xa4d9}, /* 'べ' -> 12409 */ {0x307a, 0xa4da}, /* 'ぺ' -> 12410 */ {0x307b, 0xa4db}, /* 'ほ' -> 12411 */ {0x307c, 0xa4dc}, /* 'ぼ' -> 12412 */ {0x307d, 0xa4dd}, /* 'ぽ' -> 12413 */ {0x307e, 0xa4de}, /* 'ま' -> 12414 */ {0x307f, 0xa4df}, /* 'み' -> 12415 */ {0x3080, 0xa4e0}, /* 'む' -> 12416 */ {0x3081, 0xa4e1}, /* 'め' -> 12417 */ {0x3082, 0xa4e2}, /* 'も' -> 12418 */ {0x3083, 0xa4e3}, /* 'ゃ' -> 12419 */ {0x3084, 0xa4e4}, /* 'や' -> 12420 */ {0x3085, 0xa4e5}, /* 'ゅ' -> 12421 */ {0x3086, 0xa4e6}, /* 'ゆ' -> 12422 */ {0x3087, 0xa4e7}, /* 'ょ' -> 12423 */ {0x3088, 0xa4e8}, /* 'よ' -> 12424 */ {0x3089, 0xa4e9}, /* 'ら' -> 12425 */ {0x308a, 0xa4ea}, /* 'り' -> 12426 */ {0x308b, 0xa4eb}, /* 'る' -> 12427 */ {0x308c, 0xa4ec}, /* 'れ' -> 12428 */ {0x308d, 0xa4ed}, /* 'ろ' -> 12429 */ {0x308e, 0xa4ee}, /* 'ゎ' -> 12430 */ {0x308f, 0xa4ef}, /* 'わ' -> 12431 */ {0x3090, 0xa4f0}, /* 'ゐ' -> 12432 */ {0x3091, 0xa4f1}, /* 'ゑ' -> 12433 */ {0x3092, 0xa4f2}, /* 'を' -> 12434 */ {0x3093, 0xa4f3}, /* 'ん' -> 12435 */ {0x30a1, 0xa5a1}, /* 'ァ' -> 12449 */ {0x30a2, 0xa5a2}, /* 'ア' -> 12450 */ {0x30a3, 0xa5a3}, /* 'ィ' -> 12451 */ {0x30a4, 0xa5a4}, /* 'イ' -> 12452 */ {0x30a5, 0xa5a5}, /* 'ゥ' -> 12453 */ {0x30a6, 0xa5a6}, /* 'ウ' -> 12454 */ {0x30a7, 0xa5a7}, /* 'ェ' -> 12455 */ {0x30a8, 0xa5a8}, /* 'エ' -> 12456 */ {0x30a9, 0xa5a9}, /* 'ォ' -> 12457 */ {0x30aa, 0xa5aa}, /* 'オ' -> 12458 */ {0x30ab, 0xa5ab}, /* 'カ' -> 12459 */ {0x30ac, 0xa5ac}, /* 'ガ' -> 12460 */ {0x30ad, 0xa5ad}, /* 'キ' -> 12461 */ {0x30ae, 0xa5ae}, /* 'ギ' -> 12462 */ {0x30af, 0xa5af}, /* 'ク' -> 12463 */ {0x30b0, 0xa5b0}, /* 'グ' -> 12464 */ {0x30b1, 0xa5b1}, /* 'ケ' -> 12465 */ {0x30b2, 0xa5b2}, /* 'ゲ' -> 12466 */ {0x30b3, 0xa5b3}, /* 'コ' -> 12467 */ {0x30b4, 0xa5b4}, /* 'ゴ' -> 12468 */ {0x30b5, 0xa5b5}, /* 'サ' -> 12469 */ {0x30b6, 0xa5b6}, /* 'ザ' -> 12470 */ {0x30b7, 0xa5b7}, /* 'シ' -> 12471 */ {0x30b8, 0xa5b8}, /* 'ジ' -> 12472 */ {0x30b9, 0xa5b9}, /* 'ス' -> 12473 */ {0x30ba, 0xa5ba}, /* 'ズ' -> 12474 */ {0x30bb, 0xa5bb}, /* 'セ' -> 12475 */ {0x30bc, 0xa5bc}, /* 'ゼ' -> 12476 */ {0x30bd, 0xa5bd}, /* 'ソ' -> 12477 */ {0x30be, 0xa5be}, /* 'ゾ' -> 12478 */ {0x30bf, 0xa5bf}, /* 'タ' -> 12479 */ {0x30c0, 0xa5c0}, /* 'ダ' -> 12480 */ {0x30c1, 0xa5c1}, /* 'チ' -> 12481 */ {0x30c2, 0xa5c2}, /* 'ヂ' -> 12482 */ {0x30c3, 0xa5c3}, /* 'ッ' -> 12483 */ {0x30c4, 0xa5c4}, /* 'ツ' -> 12484 */ {0x30c5, 0xa5c5}, /* 'ヅ' -> 12485 */ {0x30c6, 0xa5c6}, /* 'テ' -> 12486 */ {0x30c7, 0xa5c7}, /* 'デ' -> 12487 */ {0x30c8, 0xa5c8}, /* 'ト' -> 12488 */ {0x30c9, 0xa5c9}, /* 'ド' -> 12489 */ {0x30ca, 0xa5ca}, /* 'ナ' -> 12490 */ {0x30cb, 0xa5cb}, /* 'ニ' -> 12491 */ {0x30cc, 0xa5cc}, /* 'ヌ' -> 12492 */ {0x30cd, 0xa5cd}, /* 'ネ' -> 12493 */ {0x30ce, 0xa5ce}, /* 'ノ' -> 12494 */ {0x30cf, 0xa5cf}, /* 'ハ' -> 12495 */ {0x30d0, 0xa5d0}, /* 'バ' -> 12496 */ {0x30d1, 0xa5d1}, /* 'パ' -> 12497 */ {0x30d2, 0xa5d2}, /* 'ヒ' -> 12498 */ {0x30d3, 0xa5d3}, /* 'ビ' -> 12499 */ {0x30d4, 0xa5d4}, /* 'ピ' -> 12500 */ {0x30d5, 0xa5d5}, /* 'フ' -> 12501 */ {0x30d6, 0xa5d6}, /* 'ブ' -> 12502 */ {0x30d7, 0xa5d7}, /* 'プ' -> 12503 */ {0x30d8, 0xa5d8}, /* 'ヘ' -> 12504 */ {0x30d9, 0xa5d9}, /* 'ベ' -> 12505 */ {0x30da, 0xa5da}, /* 'ペ' -> 12506 */ {0x30db, 0xa5db}, /* 'ホ' -> 12507 */ {0x30dc, 0xa5dc}, /* 'ボ' -> 12508 */ {0x30dd, 0xa5dd}, /* 'ポ' -> 12509 */ {0x30de, 0xa5de}, /* 'マ' -> 12510 */ {0x30df, 0xa5df}, /* 'ミ' -> 12511 */ {0x30e0, 0xa5e0}, /* 'ム' -> 12512 */ {0x30e1, 0xa5e1}, /* 'メ' -> 12513 */ {0x30e2, 0xa5e2}, /* 'モ' -> 12514 */ {0x30e3, 0xa5e3}, /* 'ャ' -> 12515 */ {0x30e4, 0xa5e4}, /* 'ヤ' -> 12516 */ {0x30e5, 0xa5e5}, /* 'ュ' -> 12517 */ {0x30e6, 0xa5e6}, /* 'ユ' -> 12518 */ {0x30e7, 0xa5e7}, /* 'ョ' -> 12519 */ {0x30e8, 0xa5e8}, /* 'ヨ' -> 12520 */ {0x30e9, 0xa5e9}, /* 'ラ' -> 12521 */ {0x30ea, 0xa5ea}, /* 'リ' -> 12522 */ {0x30eb, 0xa5eb}, /* 'ル' -> 12523 */ {0x30ec, 0xa5ec}, /* 'レ' -> 12524 */ {0x30ed, 0xa5ed}, /* 'ロ' -> 12525 */ {0x30ee, 0xa5ee}, /* 'ヮ' -> 12526 */ {0x30ef, 0xa5ef}, /* 'ワ' -> 12527 */ {0x30f0, 0xa5f0}, /* 'ヰ' -> 12528 */ {0x30f1, 0xa5f1}, /* 'ヱ' -> 12529 */ {0x30f2, 0xa5f2}, /* 'ヲ' -> 12530 */ {0x30f3, 0xa5f3}, /* 'ン' -> 12531 */ {0x30f4, 0xa5f4}, /* 'ヴ' -> 12532 */ {0x30f5, 0xa5f5}, /* 'ヵ' -> 12533 */ {0x30f6, 0xa5f6}, /* 'ヶ' -> 12534 */ {0x30fb, 0xa1a4}, /* '・' -> 12539 */ {0x3105, 0xa8c5}, /* 'ㄅ' -> 12549 */ {0x3106, 0xa8c6}, /* 'ㄆ' -> 12550 */ {0x3107, 0xa8c7}, /* 'ㄇ' -> 12551 */ {0x3108, 0xa8c8}, /* 'ㄈ' -> 12552 */ {0x3109, 0xa8c9}, /* 'ㄉ' -> 12553 */ {0x310a, 0xa8ca}, /* 'ㄊ' -> 12554 */ {0x310b, 0xa8cb}, /* 'ㄋ' -> 12555 */ {0x310c, 0xa8cc}, /* 'ㄌ' -> 12556 */ {0x310d, 0xa8cd}, /* 'ㄍ' -> 12557 */ {0x310e, 0xa8ce}, /* 'ㄎ' -> 12558 */ {0x310f, 0xa8cf}, /* 'ㄏ' -> 12559 */ {0x3110, 0xa8d0}, /* 'ㄐ' -> 12560 */ {0x3111, 0xa8d1}, /* 'ㄑ' -> 12561 */ {0x3112, 0xa8d2}, /* 'ㄒ' -> 12562 */ {0x3113, 0xa8d3}, /* 'ㄓ' -> 12563 */ {0x3114, 0xa8d4}, /* 'ㄔ' -> 12564 */ {0x3115, 0xa8d5}, /* 'ㄕ' -> 12565 */ {0x3116, 0xa8d6}, /* 'ㄖ' -> 12566 */ {0x3117, 0xa8d7}, /* 'ㄗ' -> 12567 */ {0x3118, 0xa8d8}, /* 'ㄘ' -> 12568 */ {0x3119, 0xa8d9}, /* 'ㄙ' -> 12569 */ {0x311a, 0xa8da}, /* 'ㄚ' -> 12570 */ {0x311b, 0xa8db}, /* 'ㄛ' -> 12571 */ {0x311c, 0xa8dc}, /* 'ㄜ' -> 12572 */ {0x311d, 0xa8dd}, /* 'ㄝ' -> 12573 */ {0x311e, 0xa8de}, /* 'ㄞ' -> 12574 */ {0x311f, 0xa8df}, /* 'ㄟ' -> 12575 */ {0x3120, 0xa8e0}, /* 'ㄠ' -> 12576 */ {0x3121, 0xa8e1}, /* 'ㄡ' -> 12577 */ {0x3122, 0xa8e2}, /* 'ㄢ' -> 12578 */ {0x3123, 0xa8e3}, /* 'ㄣ' -> 12579 */ {0x3124, 0xa8e4}, /* 'ㄤ' -> 12580 */ {0x3125, 0xa8e5}, /* 'ㄥ' -> 12581 */ {0x3126, 0xa8e6}, /* 'ㄦ' -> 12582 */ {0x3127, 0xa8e7}, /* 'ㄧ' -> 12583 */ {0x3128, 0xa8e8}, /* 'ㄨ' -> 12584 */ {0x3129, 0xa8e9}, /* 'ㄩ' -> 12585 */ {0x3220, 0xa2e5}, /* '㈠' -> 12832 */ {0x3221, 0xa2e6}, /* '㈡' -> 12833 */ {0x3222, 0xa2e7}, /* '㈢' -> 12834 */ {0x3223, 0xa2e8}, /* '㈣' -> 12835 */ {0x3224, 0xa2e9}, /* '㈤' -> 12836 */ {0x3225, 0xa2ea}, /* '㈥' -> 12837 */ {0x3226, 0xa2eb}, /* '㈦' -> 12838 */ {0x3227, 0xa2ec}, /* '㈧' -> 12839 */ {0x3228, 0xa2ed}, /* '㈨' -> 12840 */ {0x3229, 0xa2ee}, /* '㈩' -> 12841 */ {0x4e00, 0xd2bb}, /* '一' -> 19968 */ {0x4e01, 0xb6a1}, /* '丁' -> 19969 */ {0x4e03, 0xc6df}, /* '七' -> 19971 */ {0x4e07, 0xcdf2}, /* '万' -> 19975 */ {0x4e08, 0xd5c9}, /* '丈' -> 19976 */ {0x4e09, 0xc8fd}, /* '三' -> 19977 */ {0x4e0a, 0xc9cf}, /* '上' -> 19978 */ {0x4e0b, 0xcfc2}, /* '下' -> 19979 */ {0x4e0c, 0xd8a2}, /* '丌' -> 19980 */ {0x4e0d, 0xb2bb}, /* '不' -> 19981 */ {0x4e0e, 0xd3eb}, /* '与' -> 19982 */ {0x4e10, 0xd8a4}, /* '丐' -> 19984 */ {0x4e11, 0xb3f3}, /* '丑' -> 19985 */ {0x4e13, 0xd7a8}, /* '专' -> 19987 */ {0x4e14, 0xc7d2}, /* '且' -> 19988 */ {0x4e15, 0xd8a7}, /* '丕' -> 19989 */ {0x4e16, 0xcac0}, /* '世' -> 19990 */ {0x4e18, 0xc7f0}, /* '丘' -> 19992 */ {0x4e19, 0xb1fb}, /* '丙' -> 19993 */ {0x4e1a, 0xd2b5}, /* '业' -> 19994 */ {0x4e1b, 0xb4d4}, /* '丛' -> 19995 */ {0x4e1c, 0xb6ab}, /* '东' -> 19996 */ {0x4e1d, 0xcbbf}, /* '丝' -> 19997 */ {0x4e1e, 0xd8a9}, /* '丞' -> 19998 */ {0x4e22, 0xb6aa}, /* '丢' -> 20002 */ {0x4e24, 0xc1bd}, /* '两' -> 20004 */ {0x4e25, 0xd1cf}, /* '严' -> 20005 */ {0x4e27, 0xc9a5}, /* '丧' -> 20007 */ {0x4e28, 0xd8ad}, /* '丨' -> 20008 */ {0x4e2a, 0xb8f6}, /* '个' -> 20010 */ {0x4e2b, 0xd1be}, /* '丫' -> 20011 */ {0x4e2c, 0xe3dc}, /* '丬' -> 20012 */ {0x4e2d, 0xd6d0}, /* '中' -> 20013 */ {0x4e30, 0xb7e1}, /* '丰' -> 20016 */ {0x4e32, 0xb4ae}, /* '串' -> 20018 */ {0x4e34, 0xc1d9}, /* '临' -> 20020 */ {0x4e36, 0xd8bc}, /* '丶' -> 20022 */ {0x4e38, 0xcde8}, /* '丸' -> 20024 */ {0x4e39, 0xb5a4}, /* '丹' -> 20025 */ {0x4e3a, 0xceaa}, /* '为' -> 20026 */ {0x4e3b, 0xd6f7}, /* '主' -> 20027 */ {0x4e3d, 0xc0f6}, /* '丽' -> 20029 */ {0x4e3e, 0xbed9}, /* '举' -> 20030 */ {0x4e3f, 0xd8af}, /* '丿' -> 20031 */ {0x4e43, 0xc4cb}, /* '乃' -> 20035 */ {0x4e45, 0xbec3}, /* '久' -> 20037 */ {0x4e47, 0xd8b1}, /* '乇' -> 20039 */ {0x4e48, 0xc3b4}, /* '么' -> 20040 */ {0x4e49, 0xd2e5}, /* '义' -> 20041 */ {0x4e4b, 0xd6ae}, /* '之' -> 20043 */ {0x4e4c, 0xceda}, /* '乌' -> 20044 */ {0x4e4d, 0xd5a7}, /* '乍' -> 20045 */ {0x4e4e, 0xbaf5}, /* '乎' -> 20046 */ {0x4e4f, 0xb7a6}, /* '乏' -> 20047 */ {0x4e50, 0xc0d6}, /* '乐' -> 20048 */ {0x4e52, 0xc6b9}, /* '乒' -> 20050 */ {0x4e53, 0xc5d2}, /* '乓' -> 20051 */ {0x4e54, 0xc7c7}, /* '乔' -> 20052 */ {0x4e56, 0xb9d4}, /* '乖' -> 20054 */ {0x4e58, 0xb3cb}, /* '乘' -> 20056 */ {0x4e59, 0xd2d2}, /* '乙' -> 20057 */ {0x4e5c, 0xd8bf}, /* '乜' -> 20060 */ {0x4e5d, 0xbec5}, /* '九' -> 20061 */ {0x4e5e, 0xc6f2}, /* '乞' -> 20062 */ {0x4e5f, 0xd2b2}, /* '也' -> 20063 */ {0x4e60, 0xcfb0}, /* '习' -> 20064 */ {0x4e61, 0xcfe7}, /* '乡' -> 20065 */ {0x4e66, 0xcae9}, /* '书' -> 20070 */ {0x4e69, 0xd8c0}, /* '乩' -> 20073 */ {0x4e70, 0xc2f2}, /* '买' -> 20080 */ {0x4e71, 0xc2d2}, /* '乱' -> 20081 */ {0x4e73, 0xc8e9}, /* '乳' -> 20083 */ {0x4e7e, 0xc7ac}, /* '乾' -> 20094 */ {0x4e86, 0xc1cb}, /* '了' -> 20102 */ {0x4e88, 0xd3e8}, /* '予' -> 20104 */ {0x4e89, 0xd5f9}, /* '争' -> 20105 */ {0x4e8b, 0xcac2}, /* '事' -> 20107 */ {0x4e8c, 0xb6fe}, /* '二' -> 20108 */ {0x4e8d, 0xd8a1}, /* '亍' -> 20109 */ {0x4e8e, 0xd3da}, /* '于' -> 20110 */ {0x4e8f, 0xbff7}, /* '亏' -> 20111 */ {0x4e91, 0xd4c6}, /* '云' -> 20113 */ {0x4e92, 0xbba5}, /* '互' -> 20114 */ {0x4e93, 0xd8c1}, /* '亓' -> 20115 */ {0x4e94, 0xcee5}, /* '五' -> 20116 */ {0x4e95, 0xbeae}, /* '井' -> 20117 */ {0x4e98, 0xd8a8}, /* '亘' -> 20120 */ {0x4e9a, 0xd1c7}, /* '亚' -> 20122 */ {0x4e9b, 0xd0a9}, /* '些' -> 20123 */ {0x4e9f, 0xd8bd}, /* '亟' -> 20127 */ {0x4ea0, 0xd9ef}, /* '亠' -> 20128 */ {0x4ea1, 0xcdf6}, /* '亡' -> 20129 */ {0x4ea2, 0xbfba}, /* '亢' -> 20130 */ {0x4ea4, 0xbdbb}, /* '交' -> 20132 */ {0x4ea5, 0xbaa5}, /* '亥' -> 20133 */ {0x4ea6, 0xd2e0}, /* '亦' -> 20134 */ {0x4ea7, 0xb2fa}, /* '产' -> 20135 */ {0x4ea8, 0xbae0}, /* '亨' -> 20136 */ {0x4ea9, 0xc4b6}, /* '亩' -> 20137 */ {0x4eab, 0xcfed}, /* '享' -> 20139 */ {0x4eac, 0xbea9}, /* '京' -> 20140 */ {0x4ead, 0xcda4}, /* '亭' -> 20141 */ {0x4eae, 0xc1c1}, /* '亮' -> 20142 */ {0x4eb2, 0xc7d7}, /* '亲' -> 20146 */ {0x4eb3, 0xd9f1}, /* '亳' -> 20147 */ {0x4eb5, 0xd9f4}, /* '亵' -> 20149 */ {0x4eba, 0xc8cb}, /* '人' -> 20154 */ {0x4ebb, 0xd8e9}, /* '亻' -> 20155 */ {0x4ebf, 0xd2da}, /* '亿' -> 20159 */ {0x4ec0, 0xcab2}, /* '什' -> 20160 */ {0x4ec1, 0xc8ca}, /* '仁' -> 20161 */ {0x4ec2, 0xd8ec}, /* '仂' -> 20162 */ {0x4ec3, 0xd8ea}, /* '仃' -> 20163 */ {0x4ec4, 0xd8c6}, /* '仄' -> 20164 */ {0x4ec5, 0xbdf6}, /* '仅' -> 20165 */ {0x4ec6, 0xc6cd}, /* '仆' -> 20166 */ {0x4ec7, 0xb3f0}, /* '仇' -> 20167 */ {0x4ec9, 0xd8eb}, /* '仉' -> 20169 */ {0x4eca, 0xbdf1}, /* '今' -> 20170 */ {0x4ecb, 0xbde9}, /* '介' -> 20171 */ {0x4ecd, 0xc8d4}, /* '仍' -> 20173 */ {0x4ece, 0xb4d3}, /* '从' -> 20174 */ {0x4ed1, 0xc2d8}, /* '仑' -> 20177 */ {0x4ed3, 0xb2d6}, /* '仓' -> 20179 */ {0x4ed4, 0xd7d0}, /* '仔' -> 20180 */ {0x4ed5, 0xcacb}, /* '仕' -> 20181 */ {0x4ed6, 0xcbfb}, /* '他' -> 20182 */ {0x4ed7, 0xd5cc}, /* '仗' -> 20183 */ {0x4ed8, 0xb8b6}, /* '付' -> 20184 */ {0x4ed9, 0xcfc9}, /* '仙' -> 20185 */ {0x4edd, 0xd9da}, /* '仝' -> 20189 */ {0x4ede, 0xd8f0}, /* '仞' -> 20190 */ {0x4edf, 0xc7aa}, /* '仟' -> 20191 */ {0x4ee1, 0xd8ee}, /* '仡' -> 20193 */ {0x4ee3, 0xb4fa}, /* '代' -> 20195 */ {0x4ee4, 0xc1ee}, /* '令' -> 20196 */ {0x4ee5, 0xd2d4}, /* '以' -> 20197 */ {0x4ee8, 0xd8ed}, /* '仨' -> 20200 */ {0x4eea, 0xd2c7}, /* '仪' -> 20202 */ {0x4eeb, 0xd8ef}, /* '仫' -> 20203 */ {0x4eec, 0xc3c7}, /* '们' -> 20204 */ {0x4ef0, 0xd1f6}, /* '仰' -> 20208 */ {0x4ef2, 0xd6d9}, /* '仲' -> 20210 */ {0x4ef3, 0xd8f2}, /* '仳' -> 20211 */ {0x4ef5, 0xd8f5}, /* '仵' -> 20213 */ {0x4ef6, 0xbcfe}, /* '件' -> 20214 */ {0x4ef7, 0xbcdb}, /* '价' -> 20215 */ {0x4efb, 0xc8ce}, /* '任' -> 20219 */ {0x4efd, 0xb7dd}, /* '份' -> 20221 */ {0x4eff, 0xb7c2}, /* '仿' -> 20223 */ {0x4f01, 0xc6f3}, /* '企' -> 20225 */ {0x4f09, 0xd8f8}, /* '伉' -> 20233 */ {0x4f0a, 0xd2c1}, /* '伊' -> 20234 */ {0x4f0d, 0xcee9}, /* '伍' -> 20237 */ {0x4f0e, 0xbcbf}, /* '伎' -> 20238 */ {0x4f0f, 0xb7fc}, /* '伏' -> 20239 */ {0x4f10, 0xb7a5}, /* '伐' -> 20240 */ {0x4f11, 0xd0dd}, /* '休' -> 20241 */ {0x4f17, 0xd6da}, /* '众' -> 20247 */ {0x4f18, 0xd3c5}, /* '优' -> 20248 */ {0x4f19, 0xbbef}, /* '伙' -> 20249 */ {0x4f1a, 0xbbe1}, /* '会' -> 20250 */ {0x4f1b, 0xd8f1}, /* '伛' -> 20251 */ {0x4f1e, 0xc9a1}, /* '伞' -> 20254 */ {0x4f1f, 0xceb0}, /* '伟' -> 20255 */ {0x4f20, 0xb4ab}, /* '传' -> 20256 */ {0x4f22, 0xd8f3}, /* '伢' -> 20258 */ {0x4f24, 0xc9cb}, /* '伤' -> 20260 */ {0x4f25, 0xd8f6}, /* '伥' -> 20261 */ {0x4f26, 0xc2d7}, /* '伦' -> 20262 */ {0x4f27, 0xd8f7}, /* '伧' -> 20263 */ {0x4f2a, 0xceb1}, /* '伪' -> 20266 */ {0x4f2b, 0xd8f9}, /* '伫' -> 20267 */ {0x4f2f, 0xb2ae}, /* '伯' -> 20271 */ {0x4f30, 0xb9c0}, /* '估' -> 20272 */ {0x4f32, 0xd9a3}, /* '伲' -> 20274 */ {0x4f34, 0xb0e9}, /* '伴' -> 20276 */ {0x4f36, 0xc1e6}, /* '伶' -> 20278 */ {0x4f38, 0xc9ec}, /* '伸' -> 20280 */ {0x4f3a, 0xcbc5}, /* '伺' -> 20282 */ {0x4f3c, 0xcbc6}, /* '似' -> 20284 */ {0x4f3d, 0xd9a4}, /* '伽' -> 20285 */ {0x4f43, 0xb5e8}, /* '佃' -> 20291 */ {0x4f46, 0xb5ab}, /* '但' -> 20294 */ {0x4f4d, 0xcebb}, /* '位' -> 20301 */ {0x4f4e, 0xb5cd}, /* '低' -> 20302 */ {0x4f4f, 0xd7a1}, /* '住' -> 20303 */ {0x4f50, 0xd7f4}, /* '佐' -> 20304 */ {0x4f51, 0xd3d3}, /* '佑' -> 20305 */ {0x4f53, 0xcce5}, /* '体' -> 20307 */ {0x4f55, 0xbace}, /* '何' -> 20309 */ {0x4f57, 0xd9a2}, /* '佗' -> 20311 */ {0x4f58, 0xd9dc}, /* '佘' -> 20312 */ {0x4f59, 0xd3e0}, /* '余' -> 20313 */ {0x4f5a, 0xd8fd}, /* '佚' -> 20314 */ {0x4f5b, 0xb7f0}, /* '佛' -> 20315 */ {0x4f5c, 0xd7f7}, /* '作' -> 20316 */ {0x4f5d, 0xd8fe}, /* '佝' -> 20317 */ {0x4f5e, 0xd8fa}, /* '佞' -> 20318 */ {0x4f5f, 0xd9a1}, /* '佟' -> 20319 */ {0x4f60, 0xc4e3}, /* '你' -> 20320 */ {0x4f63, 0xd3b6}, /* '佣' -> 20323 */ {0x4f64, 0xd8f4}, /* '佤' -> 20324 */ {0x4f65, 0xd9dd}, /* '佥' -> 20325 */ {0x4f67, 0xd8fb}, /* '佧' -> 20327 */ {0x4f69, 0xc5e5}, /* '佩' -> 20329 */ {0x4f6c, 0xc0d0}, /* '佬' -> 20332 */ {0x4f6f, 0xd1f0}, /* '佯' -> 20335 */ {0x4f70, 0xb0db}, /* '佰' -> 20336 */ {0x4f73, 0xbcd1}, /* '佳' -> 20339 */ {0x4f74, 0xd9a6}, /* '佴' -> 20340 */ {0x4f76, 0xd9a5}, /* '佶' -> 20342 */ {0x4f7b, 0xd9ac}, /* '佻' -> 20347 */ {0x4f7c, 0xd9ae}, /* '佼' -> 20348 */ {0x4f7e, 0xd9ab}, /* '佾' -> 20350 */ {0x4f7f, 0xcab9}, /* '使' -> 20351 */ {0x4f83, 0xd9a9}, /* '侃' -> 20355 */ {0x4f84, 0xd6b6}, /* '侄' -> 20356 */ {0x4f88, 0xb3de}, /* '侈' -> 20360 */ {0x4f89, 0xd9a8}, /* '侉' -> 20361 */ {0x4f8b, 0xc0fd}, /* '例' -> 20363 */ {0x4f8d, 0xcacc}, /* '侍' -> 20365 */ {0x4f8f, 0xd9aa}, /* '侏' -> 20367 */ {0x4f91, 0xd9a7}, /* '侑' -> 20369 */ {0x4f94, 0xd9b0}, /* '侔' -> 20372 */ {0x4f97, 0xb6b1}, /* '侗' -> 20375 */ {0x4f9b, 0xb9a9}, /* '供' -> 20379 */ {0x4f9d, 0xd2c0}, /* '依' -> 20381 */ {0x4fa0, 0xcfc0}, /* '侠' -> 20384 */ {0x4fa3, 0xc2c2}, /* '侣' -> 20387 */ {0x4fa5, 0xbdc4}, /* '侥' -> 20389 */ {0x4fa6, 0xd5ec}, /* '侦' -> 20390 */ {0x4fa7, 0xb2e0}, /* '侧' -> 20391 */ {0x4fa8, 0xc7c8}, /* '侨' -> 20392 */ {0x4fa9, 0xbfeb}, /* '侩' -> 20393 */ {0x4faa, 0xd9ad}, /* '侪' -> 20394 */ {0x4fac, 0xd9af}, /* '侬' -> 20396 */ {0x4fae, 0xceea}, /* '侮' -> 20398 */ {0x4faf, 0xbaee}, /* '侯' -> 20399 */ {0x4fb5, 0xc7d6}, /* '侵' -> 20405 */ {0x4fbf, 0xb1e3}, /* '便' -> 20415 */ {0x4fc3, 0xb4d9}, /* '促' -> 20419 */ {0x4fc4, 0xb6ed}, /* '俄' -> 20420 */ {0x4fc5, 0xd9b4}, /* '俅' -> 20421 */ {0x4fca, 0xbfa1}, /* '俊' -> 20426 */ {0x4fce, 0xd9de}, /* '俎' -> 20430 */ {0x4fcf, 0xc7ce}, /* '俏' -> 20431 */ {0x4fd0, 0xc0fe}, /* '俐' -> 20432 */ {0x4fd1, 0xd9b8}, /* '俑' -> 20433 */ {0x4fd7, 0xcbd7}, /* '俗' -> 20439 */ {0x4fd8, 0xb7fd}, /* '俘' -> 20440 */ {0x4fda, 0xd9b5}, /* '俚' -> 20442 */ {0x4fdc, 0xd9b7}, /* '俜' -> 20444 */ {0x4fdd, 0xb1a3}, /* '保' -> 20445 */ {0x4fde, 0xd3e1}, /* '俞' -> 20446 */ {0x4fdf, 0xd9b9}, /* '俟' -> 20447 */ {0x4fe1, 0xd0c5}, /* '信' -> 20449 */ {0x4fe3, 0xd9b6}, /* '俣' -> 20451 */ {0x4fe6, 0xd9b1}, /* '俦' -> 20454 */ {0x4fe8, 0xd9b2}, /* '俨' -> 20456 */ {0x4fe9, 0xc1a9}, /* '俩' -> 20457 */ {0x4fea, 0xd9b3}, /* '俪' -> 20458 */ {0x4fed, 0xbcf3}, /* '俭' -> 20461 */ {0x4fee, 0xd0de}, /* '修' -> 20462 */ {0x4fef, 0xb8a9}, /* '俯' -> 20463 */ {0x4ff1, 0xbee3}, /* '俱' -> 20465 */ {0x4ff3, 0xd9bd}, /* '俳' -> 20467 */ {0x4ff8, 0xd9ba}, /* '俸' -> 20472 */ {0x4ffa, 0xb0b3}, /* '俺' -> 20474 */ {0x4ffe, 0xd9c2}, /* '俾' -> 20478 */ {0x500c, 0xd9c4}, /* '倌' -> 20492 */ {0x500d, 0xb1b6}, /* '倍' -> 20493 */ {0x500f, 0xd9bf}, /* '倏' -> 20495 */ {0x5012, 0xb5b9}, /* '倒' -> 20498 */ {0x5014, 0xbef3}, /* '倔' -> 20500 */ {0x5018, 0xccc8}, /* '倘' -> 20504 */ {0x5019, 0xbaf2}, /* '候' -> 20505 */ {0x501a, 0xd2d0}, /* '倚' -> 20506 */ {0x501c, 0xd9c3}, /* '倜' -> 20508 */ {0x501f, 0xbde8}, /* '借' -> 20511 */ {0x5021, 0xb3ab}, /* '倡' -> 20513 */ {0x5025, 0xd9c5}, /* '倥' -> 20517 */ {0x5026, 0xbeeb}, /* '倦' -> 20518 */ {0x5028, 0xd9c6}, /* '倨' -> 20520 */ {0x5029, 0xd9bb}, /* '倩' -> 20521 */ {0x502a, 0xc4df}, /* '倪' -> 20522 */ {0x502c, 0xd9be}, /* '倬' -> 20524 */ {0x502d, 0xd9c1}, /* '倭' -> 20525 */ {0x502e, 0xd9c0}, /* '倮' -> 20526 */ {0x503a, 0xd5ae}, /* '债' -> 20538 */ {0x503c, 0xd6b5}, /* '值' -> 20540 */ {0x503e, 0xc7e3}, /* '倾' -> 20542 */ {0x5043, 0xd9c8}, /* '偃' -> 20547 */ {0x5047, 0xbcd9}, /* '假' -> 20551 */ {0x5048, 0xd9ca}, /* '偈' -> 20552 */ {0x504c, 0xd9bc}, /* '偌' -> 20556 */ {0x504e, 0xd9cb}, /* '偎' -> 20558 */ {0x504f, 0xc6ab}, /* '偏' -> 20559 */ {0x5055, 0xd9c9}, /* '偕' -> 20565 */ {0x505a, 0xd7f6}, /* '做' -> 20570 */ {0x505c, 0xcda3}, /* '停' -> 20572 */ {0x5065, 0xbda1}, /* '健' -> 20581 */ {0x506c, 0xd9cc}, /* '偬' -> 20588 */ {0x5076, 0xc5bc}, /* '偶' -> 20598 */ {0x5077, 0xcdb5}, /* '偷' -> 20599 */ {0x507b, 0xd9cd}, /* '偻' -> 20603 */ {0x507e, 0xd9c7}, /* '偾' -> 20606 */ {0x507f, 0xb3a5}, /* '偿' -> 20607 */ {0x5080, 0xbffe}, /* '傀' -> 20608 */ {0x5085, 0xb8b5}, /* '傅' -> 20613 */ {0x5088, 0xc0fc}, /* '傈' -> 20616 */ {0x508d, 0xb0f8}, /* '傍' -> 20621 */ {0x50a3, 0xb4f6}, /* '傣' -> 20643 */ {0x50a5, 0xd9ce}, /* '傥' -> 20645 */ {0x50a7, 0xd9cf}, /* '傧' -> 20647 */ {0x50a8, 0xb4a2}, /* '储' -> 20648 */ {0x50a9, 0xd9d0}, /* '傩' -> 20649 */ {0x50ac, 0xb4df}, /* '催' -> 20652 */ {0x50b2, 0xb0c1}, /* '傲' -> 20658 */ {0x50ba, 0xd9d1}, /* '傺' -> 20666 */ {0x50bb, 0xc9b5}, /* '傻' -> 20667 */ {0x50cf, 0xcff1}, /* '像' -> 20687 */ {0x50d6, 0xd9d2}, /* '僖' -> 20694 */ {0x50da, 0xc1c5}, /* '僚' -> 20698 */ {0x50e6, 0xd9d6}, /* '僦' -> 20710 */ {0x50e7, 0xc9ae}, /* '僧' -> 20711 */ {0x50ec, 0xd9d5}, /* '僬' -> 20716 */ {0x50ed, 0xd9d4}, /* '僭' -> 20717 */ {0x50ee, 0xd9d7}, /* '僮' -> 20718 */ {0x50f3, 0xcbdb}, /* '僳' -> 20723 */ {0x50f5, 0xbda9}, /* '僵' -> 20725 */ {0x50fb, 0xc6a7}, /* '僻' -> 20731 */ {0x5106, 0xd9d3}, /* '儆' -> 20742 */ {0x5107, 0xd9d8}, /* '儇' -> 20743 */ {0x510b, 0xd9d9}, /* '儋' -> 20747 */ {0x5112, 0xc8e5}, /* '儒' -> 20754 */ {0x5121, 0xc0dc}, /* '儡' -> 20769 */ {0x513f, 0xb6f9}, /* '儿' -> 20799 */ {0x5140, 0xd8a3}, /* '兀' -> 20800 */ {0x5141, 0xd4ca}, /* '允' -> 20801 */ {0x5143, 0xd4aa}, /* '元' -> 20803 */ {0x5144, 0xd0d6}, /* '兄' -> 20804 */ {0x5145, 0xb3e4}, /* '充' -> 20805 */ {0x5146, 0xd5d7}, /* '兆' -> 20806 */ {0x5148, 0xcfc8}, /* '先' -> 20808 */ {0x5149, 0xb9e2}, /* '光' -> 20809 */ {0x514b, 0xbfcb}, /* '克' -> 20811 */ {0x514d, 0xc3e2}, /* '免' -> 20813 */ {0x5151, 0xb6d2}, /* '兑' -> 20817 */ {0x5154, 0xcdc3}, /* '兔' -> 20820 */ {0x5155, 0xd9ee}, /* '兕' -> 20821 */ {0x5156, 0xd9f0}, /* '兖' -> 20822 */ {0x515a, 0xb5b3}, /* '党' -> 20826 */ {0x515c, 0xb6b5}, /* '兜' -> 20828 */ {0x5162, 0xbea4}, /* '兢' -> 20834 */ {0x5165, 0xc8eb}, /* '入' -> 20837 */ {0x5168, 0xc8ab}, /* '全' -> 20840 */ {0x516b, 0xb0cb}, /* '八' -> 20843 */ {0x516c, 0xb9ab}, /* '公' -> 20844 */ {0x516d, 0xc1f9}, /* '六' -> 20845 */ {0x516e, 0xd9e2}, /* '兮' -> 20846 */ {0x5170, 0xc0bc}, /* '兰' -> 20848 */ {0x5171, 0xb9b2}, /* '共' -> 20849 */ {0x5173, 0xb9d8}, /* '关' -> 20851 */ {0x5174, 0xd0cb}, /* '兴' -> 20852 */ {0x5175, 0xb1f8}, /* '兵' -> 20853 */ {0x5176, 0xc6e4}, /* '其' -> 20854 */ {0x5177, 0xbedf}, /* '具' -> 20855 */ {0x5178, 0xb5e4}, /* '典' -> 20856 */ {0x5179, 0xd7c8}, /* '兹' -> 20857 */ {0x517b, 0xd1f8}, /* '养' -> 20859 */ {0x517c, 0xbce6}, /* '兼' -> 20860 */ {0x517d, 0xcade}, /* '兽' -> 20861 */ {0x5180, 0xbcbd}, /* '冀' -> 20864 */ {0x5181, 0xd9e6}, /* '冁' -> 20865 */ {0x5182, 0xd8e7}, /* '冂' -> 20866 */ {0x5185, 0xc4da}, /* '内' -> 20869 */ {0x5188, 0xb8d4}, /* '冈' -> 20872 */ {0x5189, 0xc8bd}, /* '冉' -> 20873 */ {0x518c, 0xb2e1}, /* '册' -> 20876 */ {0x518d, 0xd4d9}, /* '再' -> 20877 */ {0x5192, 0xc3b0}, /* '冒' -> 20882 */ {0x5195, 0xc3e1}, /* '冕' -> 20885 */ {0x5196, 0xdaa2}, /* '冖' -> 20886 */ {0x5197, 0xc8df}, /* '冗' -> 20887 */ {0x5199, 0xd0b4}, /* '写' -> 20889 */ {0x519b, 0xbefc}, /* '军' -> 20891 */ {0x519c, 0xc5a9}, /* '农' -> 20892 */ {0x51a0, 0xb9da}, /* '冠' -> 20896 */ {0x51a2, 0xdaa3}, /* '冢' -> 20898 */ {0x51a4, 0xd4a9}, /* '冤' -> 20900 */ {0x51a5, 0xdaa4}, /* '冥' -> 20901 */ {0x51ab, 0xd9fb}, /* '冫' -> 20907 */ {0x51ac, 0xb6ac}, /* '冬' -> 20908 */ {0x51af, 0xb7eb}, /* '冯' -> 20911 */ {0x51b0, 0xb1f9}, /* '冰' -> 20912 */ {0x51b1, 0xd9fc}, /* '冱' -> 20913 */ {0x51b2, 0xb3e5}, /* '冲' -> 20914 */ {0x51b3, 0xbef6}, /* '决' -> 20915 */ {0x51b5, 0xbff6}, /* '况' -> 20917 */ {0x51b6, 0xd2b1}, /* '冶' -> 20918 */ {0x51b7, 0xc0e4}, /* '冷' -> 20919 */ {0x51bb, 0xb6b3}, /* '冻' -> 20923 */ {0x51bc, 0xd9fe}, /* '冼' -> 20924 */ {0x51bd, 0xd9fd}, /* '冽' -> 20925 */ {0x51c0, 0xbebb}, /* '净' -> 20928 */ {0x51c4, 0xc6e0}, /* '凄' -> 20932 */ {0x51c6, 0xd7bc}, /* '准' -> 20934 */ {0x51c7, 0xdaa1}, /* '凇' -> 20935 */ {0x51c9, 0xc1b9}, /* '凉' -> 20937 */ {0x51cb, 0xb5f2}, /* '凋' -> 20939 */ {0x51cc, 0xc1e8}, /* '凌' -> 20940 */ {0x51cf, 0xbcf5}, /* '减' -> 20943 */ {0x51d1, 0xb4d5}, /* '凑' -> 20945 */ {0x51db, 0xc1dd}, /* '凛' -> 20955 */ {0x51dd, 0xc4fd}, /* '凝' -> 20957 */ {0x51e0, 0xbcb8}, /* '几' -> 20960 */ {0x51e1, 0xb7b2}, /* '凡' -> 20961 */ {0x51e4, 0xb7ef}, /* '凤' -> 20964 */ {0x51eb, 0xd9ec}, /* '凫' -> 20971 */ {0x51ed, 0xc6be}, /* '凭' -> 20973 */ {0x51ef, 0xbfad}, /* '凯' -> 20975 */ {0x51f0, 0xbbcb}, /* '凰' -> 20976 */ {0x51f3, 0xb5ca}, /* '凳' -> 20979 */ {0x51f5, 0xdbc9}, /* '凵' -> 20981 */ {0x51f6, 0xd0d7}, /* '凶' -> 20982 */ {0x51f8, 0xcdb9}, /* '凸' -> 20984 */ {0x51f9, 0xb0bc}, /* '凹' -> 20985 */ {0x51fa, 0xb3f6}, /* '出' -> 20986 */ {0x51fb, 0xbbf7}, /* '击' -> 20987 */ {0x51fc, 0xdbca}, /* '凼' -> 20988 */ {0x51fd, 0xbaaf}, /* '函' -> 20989 */ {0x51ff, 0xd4e4}, /* '凿' -> 20991 */ {0x5200, 0xb5b6}, /* '刀' -> 20992 */ {0x5201, 0xb5f3}, /* '刁' -> 20993 */ {0x5202, 0xd8d6}, /* '刂' -> 20994 */ {0x5203, 0xc8d0}, /* '刃' -> 20995 */ {0x5206, 0xb7d6}, /* '分' -> 20998 */ {0x5207, 0xc7d0}, /* '切' -> 20999 */ {0x5208, 0xd8d7}, /* '刈' -> 21000 */ {0x520a, 0xbfaf}, /* '刊' -> 21002 */ {0x520d, 0xdbbb}, /* '刍' -> 21005 */ {0x520e, 0xd8d8}, /* '刎' -> 21006 */ {0x5211, 0xd0cc}, /* '刑' -> 21009 */ {0x5212, 0xbbae}, /* '划' -> 21010 */ {0x5216, 0xebbe}, /* '刖' -> 21014 */ {0x5217, 0xc1d0}, /* '列' -> 21015 */ {0x5218, 0xc1f5}, /* '刘' -> 21016 */ {0x5219, 0xd4f2}, /* '则' -> 21017 */ {0x521a, 0xb8d5}, /* '刚' -> 21018 */ {0x521b, 0xb4b4}, /* '创' -> 21019 */ {0x521d, 0xb3f5}, /* '初' -> 21021 */ {0x5220, 0xc9be}, /* '删' -> 21024 */ {0x5224, 0xc5d0}, /* '判' -> 21028 */ {0x5228, 0xc5d9}, /* '刨' -> 21032 */ {0x5229, 0xc0fb}, /* '利' -> 21033 */ {0x522b, 0xb1f0}, /* '别' -> 21035 */ {0x522d, 0xd8d9}, /* '刭' -> 21037 */ {0x522e, 0xb9ce}, /* '刮' -> 21038 */ {0x5230, 0xb5bd}, /* '到' -> 21040 */ {0x5233, 0xd8da}, /* '刳' -> 21043 */ {0x5236, 0xd6c6}, /* '制' -> 21046 */ {0x5237, 0xcba2}, /* '刷' -> 21047 */ {0x5238, 0xc8af}, /* '券' -> 21048 */ {0x5239, 0xc9b2}, /* '刹' -> 21049 */ {0x523a, 0xb4cc}, /* '刺' -> 21050 */ {0x523b, 0xbfcc}, /* '刻' -> 21051 */ {0x523d, 0xb9f4}, /* '刽' -> 21053 */ {0x523f, 0xd8db}, /* '刿' -> 21055 */ {0x5240, 0xd8dc}, /* '剀' -> 21056 */ {0x5241, 0xb6e7}, /* '剁' -> 21057 */ {0x5242, 0xbcc1}, /* '剂' -> 21058 */ {0x5243, 0xccea}, /* '剃' -> 21059 */ {0x524a, 0xcff7}, /* '削' -> 21066 */ {0x524c, 0xd8dd}, /* '剌' -> 21068 */ {0x524d, 0xc7b0}, /* '前' -> 21069 */ {0x5250, 0xb9d0}, /* '剐' -> 21072 */ {0x5251, 0xbda3}, /* '剑' -> 21073 */ {0x5254, 0xccde}, /* '剔' -> 21076 */ {0x5256, 0xc6ca}, /* '剖' -> 21078 */ {0x525c, 0xd8e0}, /* '剜' -> 21084 */ {0x525e, 0xd8de}, /* '剞' -> 21086 */ {0x5261, 0xd8df}, /* '剡' -> 21089 */ {0x5265, 0xb0fe}, /* '剥' -> 21093 */ {0x5267, 0xbee7}, /* '剧' -> 21095 */ {0x5269, 0xcaa3}, /* '剩' -> 21097 */ {0x526a, 0xbcf4}, /* '剪' -> 21098 */ {0x526f, 0xb8b1}, /* '副' -> 21103 */ {0x5272, 0xb8ee}, /* '割' -> 21106 */ {0x527d, 0xd8e2}, /* '剽' -> 21117 */ {0x527f, 0xbdcb}, /* '剿' -> 21119 */ {0x5281, 0xd8e4}, /* '劁' -> 21121 */ {0x5282, 0xd8e3}, /* '劂' -> 21122 */ {0x5288, 0xc5fc}, /* '劈' -> 21128 */ {0x5290, 0xd8e5}, /* '劐' -> 21136 */ {0x5293, 0xd8e6}, /* '劓' -> 21139 */ {0x529b, 0xc1a6}, /* '力' -> 21147 */ {0x529d, 0xc8b0}, /* '劝' -> 21149 */ {0x529e, 0xb0ec}, /* '办' -> 21150 */ {0x529f, 0xb9a6}, /* '功' -> 21151 */ {0x52a0, 0xbcd3}, /* '加' -> 21152 */ {0x52a1, 0xcef1}, /* '务' -> 21153 */ {0x52a2, 0xdbbd}, /* '劢' -> 21154 */ {0x52a3, 0xc1d3}, /* '劣' -> 21155 */ {0x52a8, 0xb6af}, /* '动' -> 21160 */ {0x52a9, 0xd6fa}, /* '助' -> 21161 */ {0x52aa, 0xc5ac}, /* '努' -> 21162 */ {0x52ab, 0xbdd9}, /* '劫' -> 21163 */ {0x52ac, 0xdbbe}, /* '劬' -> 21164 */ {0x52ad, 0xdbbf}, /* '劭' -> 21165 */ {0x52b1, 0xc0f8}, /* '励' -> 21169 */ {0x52b2, 0xbea2}, /* '劲' -> 21170 */ {0x52b3, 0xc0cd}, /* '劳' -> 21171 */ {0x52be, 0xdbc0}, /* '劾' -> 21182 */ {0x52bf, 0xcac6}, /* '势' -> 21183 */ {0x52c3, 0xb2aa}, /* '勃' -> 21187 */ {0x52c7, 0xd3c2}, /* '勇' -> 21191 */ {0x52c9, 0xc3e3}, /* '勉' -> 21193 */ {0x52cb, 0xd1ab}, /* '勋' -> 21195 */ {0x52d0, 0xdbc2}, /* '勐' -> 21200 */ {0x52d2, 0xc0d5}, /* '勒' -> 21202 */ {0x52d6, 0xdbc3}, /* '勖' -> 21206 */ {0x52d8, 0xbfb1}, /* '勘' -> 21208 */ {0x52df, 0xc4bc}, /* '募' -> 21215 */ {0x52e4, 0xc7da}, /* '勤' -> 21220 */ {0x52f0, 0xdbc4}, /* '勰' -> 21232 */ {0x52f9, 0xd9e8}, /* '勹' -> 21241 */ {0x52fa, 0xc9d7}, /* '勺' -> 21242 */ {0x52fe, 0xb9b4}, /* '勾' -> 21246 */ {0x52ff, 0xcef0}, /* '勿' -> 21247 */ {0x5300, 0xd4c8}, /* '匀' -> 21248 */ {0x5305, 0xb0fc}, /* '包' -> 21253 */ {0x5306, 0xb4d2}, /* '匆' -> 21254 */ {0x5308, 0xd0d9}, /* '匈' -> 21256 */ {0x530d, 0xd9e9}, /* '匍' -> 21261 */ {0x530f, 0xdecb}, /* '匏' -> 21263 */ {0x5310, 0xd9eb}, /* '匐' -> 21264 */ {0x5315, 0xd8b0}, /* '匕' -> 21269 */ {0x5316, 0xbbaf}, /* '化' -> 21270 */ {0x5317, 0xb1b1}, /* '北' -> 21271 */ {0x5319, 0xb3d7}, /* '匙' -> 21273 */ {0x531a, 0xd8ce}, /* '匚' -> 21274 */ {0x531d, 0xd4d1}, /* '匝' -> 21277 */ {0x5320, 0xbdb3}, /* '匠' -> 21280 */ {0x5321, 0xbfef}, /* '匡' -> 21281 */ {0x5323, 0xcfbb}, /* '匣' -> 21283 */ {0x5326, 0xd8d0}, /* '匦' -> 21286 */ {0x532a, 0xb7cb}, /* '匪' -> 21290 */ {0x532e, 0xd8d1}, /* '匮' -> 21294 */ {0x5339, 0xc6a5}, /* '匹' -> 21305 */ {0x533a, 0xc7f8}, /* '区' -> 21306 */ {0x533b, 0xd2bd}, /* '医' -> 21307 */ {0x533e, 0xd8d2}, /* '匾' -> 21310 */ {0x533f, 0xc4e4}, /* '匿' -> 21311 */ {0x5341, 0xcaae}, /* '十' -> 21313 */ {0x5343, 0xc7a7}, /* '千' -> 21315 */ {0x5345, 0xd8a6}, /* '卅' -> 21317 */ {0x5347, 0xc9fd}, /* '升' -> 21319 */ {0x5348, 0xcee7}, /* '午' -> 21320 */ {0x5349, 0xbbdc}, /* '卉' -> 21321 */ {0x534a, 0xb0eb}, /* '半' -> 21322 */ {0x534e, 0xbbaa}, /* '华' -> 21326 */ {0x534f, 0xd0ad}, /* '协' -> 21327 */ {0x5351, 0xb1b0}, /* '卑' -> 21329 */ {0x5352, 0xd7e4}, /* '卒' -> 21330 */ {0x5353, 0xd7bf}, /* '卓' -> 21331 */ {0x5355, 0xb5a5}, /* '单' -> 21333 */ {0x5356, 0xc2f4}, /* '卖' -> 21334 */ {0x5357, 0xc4cf}, /* '南' -> 21335 */ {0x535a, 0xb2a9}, /* '博' -> 21338 */ {0x535c, 0xb2b7}, /* '卜' -> 21340 */ {0x535e, 0xb1e5}, /* '卞' -> 21342 */ {0x535f, 0xdfb2}, /* '卟' -> 21343 */ {0x5360, 0xd5bc}, /* '占' -> 21344 */ {0x5361, 0xbfa8}, /* '卡' -> 21345 */ {0x5362, 0xc2ac}, /* '卢' -> 21346 */ {0x5363, 0xd8d5}, /* '卣' -> 21347 */ {0x5364, 0xc2b1}, /* '卤' -> 21348 */ {0x5366, 0xd8d4}, /* '卦' -> 21350 */ {0x5367, 0xced4}, /* '卧' -> 21351 */ {0x5369, 0xdae0}, /* '卩' -> 21353 */ {0x536b, 0xcec0}, /* '卫' -> 21355 */ {0x536e, 0xd8b4}, /* '卮' -> 21358 */ {0x536f, 0xc3ae}, /* '卯' -> 21359 */ {0x5370, 0xd3a1}, /* '印' -> 21360 */ {0x5371, 0xcea3}, /* '危' -> 21361 */ {0x5373, 0xbcb4}, /* '即' -> 21363 */ {0x5374, 0xc8b4}, /* '却' -> 21364 */ {0x5375, 0xc2d1}, /* '卵' -> 21365 */ {0x5377, 0xbeed}, /* '卷' -> 21367 */ {0x5378, 0xd0b6}, /* '卸' -> 21368 */ {0x537a, 0xdae1}, /* '卺' -> 21370 */ {0x537f, 0xc7e4}, /* '卿' -> 21375 */ {0x5382, 0xb3a7}, /* '厂' -> 21378 */ {0x5384, 0xb6f2}, /* '厄' -> 21380 */ {0x5385, 0xccfc}, /* '厅' -> 21381 */ {0x5386, 0xc0fa}, /* '历' -> 21382 */ {0x5389, 0xc0f7}, /* '厉' -> 21385 */ {0x538b, 0xd1b9}, /* '压' -> 21387 */ {0x538c, 0xd1e1}, /* '厌' -> 21388 */ {0x538d, 0xd8c7}, /* '厍' -> 21389 */ {0x5395, 0xb2de}, /* '厕' -> 21397 */ {0x5398, 0xc0e5}, /* '厘' -> 21400 */ {0x539a, 0xbaf1}, /* '厚' -> 21402 */ {0x539d, 0xd8c8}, /* '厝' -> 21405 */ {0x539f, 0xd4ad}, /* '原' -> 21407 */ {0x53a2, 0xcfe1}, /* '厢' -> 21410 */ {0x53a3, 0xd8c9}, /* '厣' -> 21411 */ {0x53a5, 0xd8ca}, /* '厥' -> 21413 */ {0x53a6, 0xcfc3}, /* '厦' -> 21414 */ {0x53a8, 0xb3f8}, /* '厨' -> 21416 */ {0x53a9, 0xbec7}, /* '厩' -> 21417 */ {0x53ae, 0xd8cb}, /* '厮' -> 21422 */ {0x53b6, 0xdbcc}, /* '厶' -> 21430 */ {0x53bb, 0xc8a5}, /* '去' -> 21435 */ {0x53bf, 0xcfd8}, /* '县' -> 21439 */ {0x53c1, 0xc8fe}, /* '叁' -> 21441 */ {0x53c2, 0xb2ce}, /* '参' -> 21442 */ {0x53c8, 0xd3d6}, /* '又' -> 21448 */ {0x53c9, 0xb2e6}, /* '叉' -> 21449 */ {0x53ca, 0xbcb0}, /* '及' -> 21450 */ {0x53cb, 0xd3d1}, /* '友' -> 21451 */ {0x53cc, 0xcbab}, /* '双' -> 21452 */ {0x53cd, 0xb7b4}, /* '反' -> 21453 */ {0x53d1, 0xb7a2}, /* '发' -> 21457 */ {0x53d4, 0xcae5}, /* '叔' -> 21460 */ {0x53d6, 0xc8a1}, /* '取' -> 21462 */ {0x53d7, 0xcadc}, /* '受' -> 21463 */ {0x53d8, 0xb1e4}, /* '变' -> 21464 */ {0x53d9, 0xd0f0}, /* '叙' -> 21465 */ {0x53db, 0xc5d1}, /* '叛' -> 21467 */ {0x53df, 0xdbc5}, /* '叟' -> 21471 */ {0x53e0, 0xb5fe}, /* '叠' -> 21472 */ {0x53e3, 0xbfda}, /* '口' -> 21475 */ {0x53e4, 0xb9c5}, /* '古' -> 21476 */ {0x53e5, 0xbee4}, /* '句' -> 21477 */ {0x53e6, 0xc1ed}, /* '另' -> 21478 */ {0x53e8, 0xdfb6}, /* '叨' -> 21480 */ {0x53e9, 0xdfb5}, /* '叩' -> 21481 */ {0x53ea, 0xd6bb}, /* '只' -> 21482 */ {0x53eb, 0xbdd0}, /* '叫' -> 21483 */ {0x53ec, 0xd5d9}, /* '召' -> 21484 */ {0x53ed, 0xb0c8}, /* '叭' -> 21485 */ {0x53ee, 0xb6a3}, /* '叮' -> 21486 */ {0x53ef, 0xbfc9}, /* '可' -> 21487 */ {0x53f0, 0xcca8}, /* '台' -> 21488 */ {0x53f1, 0xdfb3}, /* '叱' -> 21489 */ {0x53f2, 0xcab7}, /* '史' -> 21490 */ {0x53f3, 0xd3d2}, /* '右' -> 21491 */ {0x53f5, 0xd8cf}, /* '叵' -> 21493 */ {0x53f6, 0xd2b6}, /* '叶' -> 21494 */ {0x53f7, 0xbac5}, /* '号' -> 21495 */ {0x53f8, 0xcbbe}, /* '司' -> 21496 */ {0x53f9, 0xccbe}, /* '叹' -> 21497 */ {0x53fb, 0xdfb7}, /* '叻' -> 21499 */ {0x53fc, 0xb5f0}, /* '叼' -> 21500 */ {0x53fd, 0xdfb4}, /* '叽' -> 21501 */ {0x5401, 0xd3f5}, /* '吁' -> 21505 */ {0x5403, 0xb3d4}, /* '吃' -> 21507 */ {0x5404, 0xb8f7}, /* '各' -> 21508 */ {0x5406, 0xdfba}, /* '吆' -> 21510 */ {0x5408, 0xbacf}, /* '合' -> 21512 */ {0x5409, 0xbcaa}, /* '吉' -> 21513 */ {0x540a, 0xb5f5}, /* '吊' -> 21514 */ {0x540c, 0xcdac}, /* '同' -> 21516 */ {0x540d, 0xc3fb}, /* '名' -> 21517 */ {0x540e, 0xbaf3}, /* '后' -> 21518 */ {0x540f, 0xc0f4}, /* '吏' -> 21519 */ {0x5410, 0xcdc2}, /* '吐' -> 21520 */ {0x5411, 0xcff2}, /* '向' -> 21521 */ {0x5412, 0xdfb8}, /* '吒' -> 21522 */ {0x5413, 0xcfc5}, /* '吓' -> 21523 */ {0x5415, 0xc2c0}, /* '吕' -> 21525 */ {0x5416, 0xdfb9}, /* '吖' -> 21526 */ {0x5417, 0xc2f0}, /* '吗' -> 21527 */ {0x541b, 0xbefd}, /* '君' -> 21531 */ {0x541d, 0xc1df}, /* '吝' -> 21533 */ {0x541e, 0xcdcc}, /* '吞' -> 21534 */ {0x541f, 0xd2f7}, /* '吟' -> 21535 */ {0x5420, 0xb7cd}, /* '吠' -> 21536 */ {0x5421, 0xdfc1}, /* '吡' -> 21537 */ {0x5423, 0xdfc4}, /* '吣' -> 21539 */ {0x5426, 0xb7f1}, /* '否' -> 21542 */ {0x5427, 0xb0c9}, /* '吧' -> 21543 */ {0x5428, 0xb6d6}, /* '吨' -> 21544 */ {0x5429, 0xb7d4}, /* '吩' -> 21545 */ {0x542b, 0xbaac}, /* '含' -> 21547 */ {0x542c, 0xccfd}, /* '听' -> 21548 */ {0x542d, 0xbfd4}, /* '吭' -> 21549 */ {0x542e, 0xcbb1}, /* '吮' -> 21550 */ {0x542f, 0xc6f4}, /* '启' -> 21551 */ {0x5431, 0xd6a8}, /* '吱' -> 21553 */ {0x5432, 0xdfc5}, /* '吲' -> 21554 */ {0x5434, 0xcee2}, /* '吴' -> 21556 */ {0x5435, 0xb3b3}, /* '吵' -> 21557 */ {0x5438, 0xcefc}, /* '吸' -> 21560 */ {0x5439, 0xb4b5}, /* '吹' -> 21561 */ {0x543b, 0xcec7}, /* '吻' -> 21563 */ {0x543c, 0xbaf0}, /* '吼' -> 21564 */ {0x543e, 0xcee1}, /* '吾' -> 21566 */ {0x5440, 0xd1bd}, /* '呀' -> 21568 */ {0x5443, 0xdfc0}, /* '呃' -> 21571 */ {0x5446, 0xb4f4}, /* '呆' -> 21574 */ {0x5448, 0xb3ca}, /* '呈' -> 21576 */ {0x544a, 0xb8e6}, /* '告' -> 21578 */ {0x544b, 0xdfbb}, /* '呋' -> 21579 */ {0x5450, 0xc4c5}, /* '呐' -> 21584 */ {0x5452, 0xdfbc}, /* '呒' -> 21586 */ {0x5453, 0xdfbd}, /* '呓' -> 21587 */ {0x5454, 0xdfbe}, /* '呔' -> 21588 */ {0x5455, 0xc5bb}, /* '呕' -> 21589 */ {0x5456, 0xdfbf}, /* '呖' -> 21590 */ {0x5457, 0xdfc2}, /* '呗' -> 21591 */ {0x5458, 0xd4b1}, /* '员' -> 21592 */ {0x5459, 0xdfc3}, /* '呙' -> 21593 */ {0x545b, 0xc7ba}, /* '呛' -> 21595 */ {0x545c, 0xced8}, /* '呜' -> 21596 */ {0x5462, 0xc4d8}, /* '呢' -> 21602 */ {0x5464, 0xdfca}, /* '呤' -> 21604 */ {0x5466, 0xdfcf}, /* '呦' -> 21606 */ {0x5468, 0xd6dc}, /* '周' -> 21608 */ {0x5471, 0xdfc9}, /* '呱' -> 21617 */ {0x5472, 0xdfda}, /* '呲' -> 21618 */ {0x5473, 0xceb6}, /* '味' -> 21619 */ {0x5475, 0xbac7}, /* '呵' -> 21621 */ {0x5476, 0xdfce}, /* '呶' -> 21622 */ {0x5477, 0xdfc8}, /* '呷' -> 21623 */ {0x5478, 0xc5de}, /* '呸' -> 21624 */ {0x547b, 0xc9eb}, /* '呻' -> 21627 */ {0x547c, 0xbaf4}, /* '呼' -> 21628 */ {0x547d, 0xc3fc}, /* '命' -> 21629 */ {0x5480, 0xbed7}, /* '咀' -> 21632 */ {0x5482, 0xdfc6}, /* '咂' -> 21634 */ {0x5484, 0xdfcd}, /* '咄' -> 21636 */ {0x5486, 0xc5d8}, /* '咆' -> 21638 */ {0x548b, 0xd5a6}, /* '咋' -> 21643 */ {0x548c, 0xbacd}, /* '和' -> 21644 */ {0x548e, 0xbecc}, /* '咎' -> 21646 */ {0x548f, 0xd3bd}, /* '咏' -> 21647 */ {0x5490, 0xb8c0}, /* '咐' -> 21648 */ {0x5492, 0xd6e4}, /* '咒' -> 21650 */ {0x5494, 0xdfc7}, /* '咔' -> 21652 */ {0x5495, 0xb9be}, /* '咕' -> 21653 */ {0x5496, 0xbfa7}, /* '咖' -> 21654 */ {0x5499, 0xc1fc}, /* '咙' -> 21657 */ {0x549a, 0xdfcb}, /* '咚' -> 21658 */ {0x549b, 0xdfcc}, /* '咛' -> 21659 */ {0x549d, 0xdfd0}, /* '咝' -> 21661 */ {0x54a3, 0xdfdb}, /* '咣' -> 21667 */ {0x54a4, 0xdfe5}, /* '咤' -> 21668 */ {0x54a6, 0xdfd7}, /* '咦' -> 21670 */ {0x54a7, 0xdfd6}, /* '咧' -> 21671 */ {0x54a8, 0xd7c9}, /* '咨' -> 21672 */ {0x54a9, 0xdfe3}, /* '咩' -> 21673 */ {0x54aa, 0xdfe4}, /* '咪' -> 21674 */ {0x54ab, 0xe5eb}, /* '咫' -> 21675 */ {0x54ac, 0xd2a7}, /* '咬' -> 21676 */ {0x54ad, 0xdfd2}, /* '咭' -> 21677 */ {0x54af, 0xbfa9}, /* '咯' -> 21679 */ {0x54b1, 0xd4db}, /* '咱' -> 21681 */ {0x54b3, 0xbfc8}, /* '咳' -> 21683 */ {0x54b4, 0xdfd4}, /* '咴' -> 21684 */ {0x54b8, 0xcfcc}, /* '咸' -> 21688 */ {0x54bb, 0xdfdd}, /* '咻' -> 21691 */ {0x54bd, 0xd1ca}, /* '咽' -> 21693 */ {0x54bf, 0xdfde}, /* '咿' -> 21695 */ {0x54c0, 0xb0a7}, /* '哀' -> 21696 */ {0x54c1, 0xc6b7}, /* '品' -> 21697 */ {0x54c2, 0xdfd3}, /* '哂' -> 21698 */ {0x54c4, 0xbae5}, /* '哄' -> 21700 */ {0x54c6, 0xb6df}, /* '哆' -> 21702 */ {0x54c7, 0xcddb}, /* '哇' -> 21703 */ {0x54c8, 0xb9fe}, /* '哈' -> 21704 */ {0x54c9, 0xd4d5}, /* '哉' -> 21705 */ {0x54cc, 0xdfdf}, /* '哌' -> 21708 */ {0x54cd, 0xcfec}, /* '响' -> 21709 */ {0x54ce, 0xb0a5}, /* '哎' -> 21710 */ {0x54cf, 0xdfe7}, /* '哏' -> 21711 */ {0x54d0, 0xdfd1}, /* '哐' -> 21712 */ {0x54d1, 0xd1c6}, /* '哑' -> 21713 */ {0x54d2, 0xdfd5}, /* '哒' -> 21714 */ {0x54d3, 0xdfd8}, /* '哓' -> 21715 */ {0x54d4, 0xdfd9}, /* '哔' -> 21716 */ {0x54d5, 0xdfdc}, /* '哕' -> 21717 */ {0x54d7, 0xbba9}, /* '哗' -> 21719 */ {0x54d9, 0xdfe0}, /* '哙' -> 21721 */ {0x54da, 0xdfe1}, /* '哚' -> 21722 */ {0x54dc, 0xdfe2}, /* '哜' -> 21724 */ {0x54dd, 0xdfe6}, /* '哝' -> 21725 */ {0x54de, 0xdfe8}, /* '哞' -> 21726 */ {0x54df, 0xd3b4}, /* '哟' -> 21727 */ {0x54e5, 0xb8e7}, /* '哥' -> 21733 */ {0x54e6, 0xc5b6}, /* '哦' -> 21734 */ {0x54e7, 0xdfea}, /* '哧' -> 21735 */ {0x54e8, 0xc9da}, /* '哨' -> 21736 */ {0x54e9, 0xc1a8}, /* '哩' -> 21737 */ {0x54ea, 0xc4c4}, /* '哪' -> 21738 */ {0x54ed, 0xbfde}, /* '哭' -> 21741 */ {0x54ee, 0xcff8}, /* '哮' -> 21742 */ {0x54f2, 0xd5dc}, /* '哲' -> 21746 */ {0x54f3, 0xdfee}, /* '哳' -> 21747 */ {0x54fa, 0xb2b8}, /* '哺' -> 21754 */ {0x54fc, 0xbadf}, /* '哼' -> 21756 */ {0x54fd, 0xdfec}, /* '哽' -> 21757 */ {0x54ff, 0xdbc1}, /* '哿' -> 21759 */ {0x5501, 0xd1e4}, /* '唁' -> 21761 */ {0x5506, 0xcbf4}, /* '唆' -> 21766 */ {0x5507, 0xb4bd}, /* '唇' -> 21767 */ {0x5509, 0xb0a6}, /* '唉' -> 21769 */ {0x550f, 0xdff1}, /* '唏' -> 21775 */ {0x5510, 0xccc6}, /* '唐' -> 21776 */ {0x5511, 0xdff2}, /* '唑' -> 21777 */ {0x5514, 0xdfed}, /* '唔' -> 21780 */ {0x551b, 0xdfe9}, /* '唛' -> 21787 */ {0x5520, 0xdfeb}, /* '唠' -> 21792 */ {0x5522, 0xdfef}, /* '唢' -> 21794 */ {0x5523, 0xdff0}, /* '唣' -> 21795 */ {0x5524, 0xbbbd}, /* '唤' -> 21796 */ {0x5527, 0xdff3}, /* '唧' -> 21799 */ {0x552a, 0xdff4}, /* '唪' -> 21802 */ {0x552c, 0xbba3}, /* '唬' -> 21804 */ {0x552e, 0xcadb}, /* '售' -> 21806 */ {0x552f, 0xcea8}, /* '唯' -> 21807 */ {0x5530, 0xe0a7}, /* '唰' -> 21808 */ {0x5531, 0xb3aa}, /* '唱' -> 21809 */ {0x5533, 0xe0a6}, /* '唳' -> 21811 */ {0x5537, 0xe0a1}, /* '唷' -> 21815 */ {0x553c, 0xdffe}, /* '唼' -> 21820 */ {0x553e, 0xcdd9}, /* '唾' -> 21822 */ {0x553f, 0xdffc}, /* '唿' -> 21823 */ {0x5541, 0xdffa}, /* '啁' -> 21825 */ {0x5543, 0xbfd0}, /* '啃' -> 21827 */ {0x5544, 0xd7c4}, /* '啄' -> 21828 */ {0x5546, 0xc9cc}, /* '商' -> 21830 */ {0x5549, 0xdff8}, /* '啉' -> 21833 */ {0x554a, 0xb0a1}, /* '啊' -> 21834 */ {0x5550, 0xdffd}, /* '啐' -> 21840 */ {0x5555, 0xdffb}, /* '啕' -> 21845 */ {0x5556, 0xe0a2}, /* '啖' -> 21846 */ {0x555c, 0xe0a8}, /* '啜' -> 21852 */ {0x5561, 0xb7c8}, /* '啡' -> 21857 */ {0x5564, 0xc6a1}, /* '啤' -> 21860 */ {0x5565, 0xc9b6}, /* '啥' -> 21861 */ {0x5566, 0xc0b2}, /* '啦' -> 21862 */ {0x5567, 0xdff5}, /* '啧' -> 21863 */ {0x556a, 0xc5be}, /* '啪' -> 21866 */ {0x556c, 0xd8c4}, /* '啬' -> 21868 */ {0x556d, 0xdff9}, /* '啭' -> 21869 */ {0x556e, 0xc4f6}, /* '啮' -> 21870 */ {0x5575, 0xe0a3}, /* '啵' -> 21877 */ {0x5576, 0xe0a4}, /* '啶' -> 21878 */ {0x5577, 0xe0a5}, /* '啷' -> 21879 */ {0x5578, 0xd0a5}, /* '啸' -> 21880 */ {0x557b, 0xe0b4}, /* '啻' -> 21883 */ {0x557c, 0xcce4}, /* '啼' -> 21884 */ {0x557e, 0xe0b1}, /* '啾' -> 21886 */ {0x5580, 0xbfa6}, /* '喀' -> 21888 */ {0x5581, 0xe0af}, /* '喁' -> 21889 */ {0x5582, 0xceb9}, /* '喂' -> 21890 */ {0x5583, 0xe0ab}, /* '喃' -> 21891 */ {0x5584, 0xc9c6}, /* '善' -> 21892 */ {0x5587, 0xc0ae}, /* '喇' -> 21895 */ {0x5588, 0xe0ae}, /* '喈' -> 21896 */ {0x5589, 0xbaed}, /* '喉' -> 21897 */ {0x558a, 0xbab0}, /* '喊' -> 21898 */ {0x558b, 0xe0a9}, /* '喋' -> 21899 */ {0x558f, 0xdff6}, /* '喏' -> 21903 */ {0x5591, 0xe0b3}, /* '喑' -> 21905 */ {0x5594, 0xe0b8}, /* '喔' -> 21908 */ {0x5598, 0xb4ad}, /* '喘' -> 21912 */ {0x5599, 0xe0b9}, /* '喙' -> 21913 */ {0x559c, 0xcfb2}, /* '喜' -> 21916 */ {0x559d, 0xbac8}, /* '喝' -> 21917 */ {0x559f, 0xe0b0}, /* '喟' -> 21919 */ {0x55a7, 0xd0fa}, /* '喧' -> 21927 */ {0x55b1, 0xe0ac}, /* '喱' -> 21937 */ {0x55b3, 0xd4fb}, /* '喳' -> 21939 */ {0x55b5, 0xdff7}, /* '喵' -> 21941 */ {0x55b7, 0xc5e7}, /* '喷' -> 21943 */ {0x55b9, 0xe0ad}, /* '喹' -> 21945 */ {0x55bb, 0xd3f7}, /* '喻' -> 21947 */ {0x55bd, 0xe0b6}, /* '喽' -> 21949 */ {0x55be, 0xe0b7}, /* '喾' -> 21950 */ {0x55c4, 0xe0c4}, /* '嗄' -> 21956 */ {0x55c5, 0xd0e1}, /* '嗅' -> 21957 */ {0x55c9, 0xe0bc}, /* '嗉' -> 21961 */ {0x55cc, 0xe0c9}, /* '嗌' -> 21964 */ {0x55cd, 0xe0ca}, /* '嗍' -> 21965 */ {0x55d1, 0xe0be}, /* '嗑' -> 21969 */ {0x55d2, 0xe0aa}, /* '嗒' -> 21970 */ {0x55d3, 0xc9a4}, /* '嗓' -> 21971 */ {0x55d4, 0xe0c1}, /* '嗔' -> 21972 */ {0x55d6, 0xe0b2}, /* '嗖' -> 21974 */ {0x55dc, 0xcac8}, /* '嗜' -> 21980 */ {0x55dd, 0xe0c3}, /* '嗝' -> 21981 */ {0x55df, 0xe0b5}, /* '嗟' -> 21983 */ {0x55e1, 0xcecb}, /* '嗡' -> 21985 */ {0x55e3, 0xcbc3}, /* '嗣' -> 21987 */ {0x55e4, 0xe0cd}, /* '嗤' -> 21988 */ {0x55e5, 0xe0c6}, /* '嗥' -> 21989 */ {0x55e6, 0xe0c2}, /* '嗦' -> 21990 */ {0x55e8, 0xe0cb}, /* '嗨' -> 21992 */ {0x55ea, 0xe0ba}, /* '嗪' -> 21994 */ {0x55eb, 0xe0bf}, /* '嗫' -> 21995 */ {0x55ec, 0xe0c0}, /* '嗬' -> 21996 */ {0x55ef, 0xe0c5}, /* '嗯' -> 21999 */ {0x55f2, 0xe0c7}, /* '嗲' -> 22002 */ {0x55f3, 0xe0c8}, /* '嗳' -> 22003 */ {0x55f5, 0xe0cc}, /* '嗵' -> 22005 */ {0x55f7, 0xe0bb}, /* '嗷' -> 22007 */ {0x55fd, 0xcbd4}, /* '嗽' -> 22013 */ {0x55fe, 0xe0d5}, /* '嗾' -> 22014 */ {0x5600, 0xe0d6}, /* '嘀' -> 22016 */ {0x5601, 0xe0d2}, /* '嘁' -> 22017 */ {0x5608, 0xe0d0}, /* '嘈' -> 22024 */ {0x5609, 0xbcce}, /* '嘉' -> 22025 */ {0x560c, 0xe0d1}, /* '嘌' -> 22028 */ {0x560e, 0xb8c2}, /* '嘎' -> 22030 */ {0x560f, 0xd8c5}, /* '嘏' -> 22031 */ {0x5618, 0xd0ea}, /* '嘘' -> 22040 */ {0x561b, 0xc2ef}, /* '嘛' -> 22043 */ {0x561e, 0xe0cf}, /* '嘞' -> 22046 */ {0x561f, 0xe0bd}, /* '嘟' -> 22047 */ {0x5623, 0xe0d4}, /* '嘣' -> 22051 */ {0x5624, 0xe0d3}, /* '嘤' -> 22052 */ {0x5627, 0xe0d7}, /* '嘧' -> 22055 */ {0x562c, 0xe0dc}, /* '嘬' -> 22060 */ {0x562d, 0xe0d8}, /* '嘭' -> 22061 */ {0x5631, 0xd6f6}, /* '嘱' -> 22065 */ {0x5632, 0xb3b0}, /* '嘲' -> 22066 */ {0x5634, 0xd7ec}, /* '嘴' -> 22068 */ {0x5636, 0xcbbb}, /* '嘶' -> 22070 */ {0x5639, 0xe0da}, /* '嘹' -> 22073 */ {0x563b, 0xcefb}, /* '嘻' -> 22075 */ {0x563f, 0xbad9}, /* '嘿' -> 22079 */ {0x564c, 0xe0e1}, /* '噌' -> 22092 */ {0x564d, 0xe0dd}, /* '噍' -> 22093 */ {0x564e, 0xd2ad}, /* '噎' -> 22094 */ {0x5654, 0xe0e2}, /* '噔' -> 22100 */ {0x5657, 0xe0db}, /* '噗' -> 22103 */ {0x5658, 0xe0d9}, /* '噘' -> 22104 */ {0x5659, 0xe0df}, /* '噙' -> 22105 */ {0x565c, 0xe0e0}, /* '噜' -> 22108 */ {0x5662, 0xe0de}, /* '噢' -> 22114 */ {0x5664, 0xe0e4}, /* '噤' -> 22116 */ {0x5668, 0xc6f7}, /* '器' -> 22120 */ {0x5669, 0xd8ac}, /* '噩' -> 22121 */ {0x566a, 0xd4eb}, /* '噪' -> 22122 */ {0x566b, 0xe0e6}, /* '噫' -> 22123 */ {0x566c, 0xcac9}, /* '噬' -> 22124 */ {0x5671, 0xe0e5}, /* '噱' -> 22129 */ {0x5676, 0xb8c1}, /* '噶' -> 22134 */ {0x567b, 0xe0e7}, /* '噻' -> 22139 */ {0x567c, 0xe0e8}, /* '噼' -> 22140 */ {0x5685, 0xe0e9}, /* '嚅' -> 22149 */ {0x5686, 0xe0e3}, /* '嚆' -> 22150 */ {0x568e, 0xbabf}, /* '嚎' -> 22158 */ {0x568f, 0xcce7}, /* '嚏' -> 22159 */ {0x5693, 0xe0ea}, /* '嚓' -> 22163 */ {0x56a3, 0xcff9}, /* '嚣' -> 22179 */ {0x56af, 0xe0eb}, /* '嚯' -> 22191 */ {0x56b7, 0xc8c2}, /* '嚷' -> 22199 */ {0x56bc, 0xbdc0}, /* '嚼' -> 22204 */ {0x56ca, 0xc4d2}, /* '囊' -> 22218 */ {0x56d4, 0xe0ec}, /* '囔' -> 22228 */ {0x56d7, 0xe0ed}, /* '囗' -> 22231 */ {0x56da, 0xc7f4}, /* '囚' -> 22234 */ {0x56db, 0xcbc4}, /* '四' -> 22235 */ {0x56dd, 0xe0ee}, /* '囝' -> 22237 */ {0x56de, 0xbbd8}, /* '回' -> 22238 */ {0x56df, 0xd8b6}, /* '囟' -> 22239 */ {0x56e0, 0xd2f2}, /* '因' -> 22240 */ {0x56e1, 0xe0ef}, /* '囡' -> 22241 */ {0x56e2, 0xcdc5}, /* '团' -> 22242 */ {0x56e4, 0xb6da}, /* '囤' -> 22244 */ {0x56eb, 0xe0f1}, /* '囫' -> 22251 */ {0x56ed, 0xd4b0}, /* '园' -> 22253 */ {0x56f0, 0xc0a7}, /* '困' -> 22256 */ {0x56f1, 0xb4d1}, /* '囱' -> 22257 */ {0x56f4, 0xcea7}, /* '围' -> 22260 */ {0x56f5, 0xe0f0}, /* '囵' -> 22261 */ {0x56f9, 0xe0f2}, /* '囹' -> 22265 */ {0x56fa, 0xb9cc}, /* '固' -> 22266 */ {0x56fd, 0xb9fa}, /* '国' -> 22269 */ {0x56fe, 0xcdbc}, /* '图' -> 22270 */ {0x56ff, 0xe0f3}, /* '囿' -> 22271 */ {0x5703, 0xc6d4}, /* '圃' -> 22275 */ {0x5704, 0xe0f4}, /* '圄' -> 22276 */ {0x5706, 0xd4b2}, /* '圆' -> 22278 */ {0x5708, 0xc8a6}, /* '圈' -> 22280 */ {0x5709, 0xe0f6}, /* '圉' -> 22281 */ {0x570a, 0xe0f5}, /* '圊' -> 22282 */ {0x571c, 0xe0f7}, /* '圜' -> 22300 */ {0x571f, 0xcdc1}, /* '土' -> 22303 */ {0x5723, 0xcaa5}, /* '圣' -> 22307 */ {0x5728, 0xd4da}, /* '在' -> 22312 */ {0x5729, 0xdbd7}, /* '圩' -> 22313 */ {0x572a, 0xdbd9}, /* '圪' -> 22314 */ {0x572c, 0xdbd8}, /* '圬' -> 22316 */ {0x572d, 0xb9e7}, /* '圭' -> 22317 */ {0x572e, 0xdbdc}, /* '圮' -> 22318 */ {0x572f, 0xdbdd}, /* '圯' -> 22319 */ {0x5730, 0xb5d8}, /* '地' -> 22320 */ {0x5733, 0xdbda}, /* '圳' -> 22323 */ {0x5739, 0xdbdb}, /* '圹' -> 22329 */ {0x573a, 0xb3a1}, /* '场' -> 22330 */ {0x573b, 0xdbdf}, /* '圻' -> 22331 */ {0x573e, 0xbbf8}, /* '圾' -> 22334 */ {0x5740, 0xd6b7}, /* '址' -> 22336 */ {0x5742, 0xdbe0}, /* '坂' -> 22338 */ {0x5747, 0xbef9}, /* '均' -> 22343 */ {0x574a, 0xb7bb}, /* '坊' -> 22346 */ {0x574c, 0xdbd0}, /* '坌' -> 22348 */ {0x574d, 0xccae}, /* '坍' -> 22349 */ {0x574e, 0xbfb2}, /* '坎' -> 22350 */ {0x574f, 0xbbb5}, /* '坏' -> 22351 */ {0x5750, 0xd7f8}, /* '坐' -> 22352 */ {0x5751, 0xbfd3}, /* '坑' -> 22353 */ {0x5757, 0xbfe9}, /* '块' -> 22359 */ {0x575a, 0xbce1}, /* '坚' -> 22362 */ {0x575b, 0xccb3}, /* '坛' -> 22363 */ {0x575c, 0xdbde}, /* '坜' -> 22364 */ {0x575d, 0xb0d3}, /* '坝' -> 22365 */ {0x575e, 0xceeb}, /* '坞' -> 22366 */ {0x575f, 0xb7d8}, /* '坟' -> 22367 */ {0x5760, 0xd7b9}, /* '坠' -> 22368 */ {0x5761, 0xc6c2}, /* '坡' -> 22369 */ {0x5764, 0xc0a4}, /* '坤' -> 22372 */ {0x5766, 0xccb9}, /* '坦' -> 22374 */ {0x5768, 0xdbe7}, /* '坨' -> 22376 */ {0x5769, 0xdbe1}, /* '坩' -> 22377 */ {0x576a, 0xc6ba}, /* '坪' -> 22378 */ {0x576b, 0xdbe3}, /* '坫' -> 22379 */ {0x576d, 0xdbe8}, /* '坭' -> 22381 */ {0x576f, 0xc5f7}, /* '坯' -> 22383 */ {0x5773, 0xdbea}, /* '坳' -> 22387 */ {0x5776, 0xdbe9}, /* '坶' -> 22390 */ {0x5777, 0xbfc0}, /* '坷' -> 22391 */ {0x577b, 0xdbe6}, /* '坻' -> 22395 */ {0x577c, 0xdbe5}, /* '坼' -> 22396 */ {0x5782, 0xb4b9}, /* '垂' -> 22402 */ {0x5783, 0xc0ac}, /* '垃' -> 22403 */ {0x5784, 0xc2a2}, /* '垄' -> 22404 */ {0x5785, 0xdbe2}, /* '垅' -> 22405 */ {0x5786, 0xdbe4}, /* '垆' -> 22406 */ {0x578b, 0xd0cd}, /* '型' -> 22411 */ {0x578c, 0xdbed}, /* '垌' -> 22412 */ {0x5792, 0xc0dd}, /* '垒' -> 22418 */ {0x5793, 0xdbf2}, /* '垓' -> 22419 */ {0x579b, 0xb6e2}, /* '垛' -> 22427 */ {0x57a0, 0xdbf3}, /* '垠' -> 22432 */ {0x57a1, 0xdbd2}, /* '垡' -> 22433 */ {0x57a2, 0xb9b8}, /* '垢' -> 22434 */ {0x57a3, 0xd4ab}, /* '垣' -> 22435 */ {0x57a4, 0xdbec}, /* '垤' -> 22436 */ {0x57a6, 0xbfd1}, /* '垦' -> 22438 */ {0x57a7, 0xdbf0}, /* '垧' -> 22439 */ {0x57a9, 0xdbd1}, /* '垩' -> 22441 */ {0x57ab, 0xb5e6}, /* '垫' -> 22443 */ {0x57ad, 0xdbeb}, /* '垭' -> 22445 */ {0x57ae, 0xbfe5}, /* '垮' -> 22446 */ {0x57b2, 0xdbee}, /* '垲' -> 22450 */ {0x57b4, 0xdbf1}, /* '垴' -> 22452 */ {0x57b8, 0xdbf9}, /* '垸' -> 22456 */ {0x57c2, 0xb9a1}, /* '埂' -> 22466 */ {0x57c3, 0xb0a3}, /* '埃' -> 22467 */ {0x57cb, 0xc2f1}, /* '埋' -> 22475 */ {0x57ce, 0xb3c7}, /* '城' -> 22478 */ {0x57cf, 0xdbef}, /* '埏' -> 22479 */ {0x57d2, 0xdbf8}, /* '埒' -> 22482 */ {0x57d4, 0xc6d2}, /* '埔' -> 22484 */ {0x57d5, 0xdbf4}, /* '埕' -> 22485 */ {0x57d8, 0xdbf5}, /* '埘' -> 22488 */ {0x57d9, 0xdbf7}, /* '埙' -> 22489 */ {0x57da, 0xdbf6}, /* '埚' -> 22490 */ {0x57dd, 0xdbfe}, /* '埝' -> 22493 */ {0x57df, 0xd3f2}, /* '域' -> 22495 */ {0x57e0, 0xb2ba}, /* '埠' -> 22496 */ {0x57e4, 0xdbfd}, /* '埤' -> 22500 */ {0x57ed, 0xdca4}, /* '埭' -> 22509 */ {0x57ef, 0xdbfb}, /* '埯' -> 22511 */ {0x57f4, 0xdbfa}, /* '埴' -> 22516 */ {0x57f8, 0xdbfc}, /* '埸' -> 22520 */ {0x57f9, 0xc5e0}, /* '培' -> 22521 */ {0x57fa, 0xbbf9}, /* '基' -> 22522 */ {0x57fd, 0xdca3}, /* '埽' -> 22525 */ {0x5800, 0xdca5}, /* '堀' -> 22528 */ {0x5802, 0xccc3}, /* '堂' -> 22530 */ {0x5806, 0xb6d1}, /* '堆' -> 22534 */ {0x5807, 0xddc0}, /* '堇' -> 22535 */ {0x580b, 0xdca1}, /* '堋' -> 22539 */ {0x580d, 0xdca2}, /* '堍' -> 22541 */ {0x5811, 0xc7b5}, /* '堑' -> 22545 */ {0x5815, 0xb6e9}, /* '堕' -> 22549 */ {0x5819, 0xdca7}, /* '堙' -> 22553 */ {0x581e, 0xdca6}, /* '堞' -> 22558 */ {0x5820, 0xdca9}, /* '堠' -> 22560 */ {0x5821, 0xb1a4}, /* '堡' -> 22561 */ {0x5824, 0xb5cc}, /* '堤' -> 22564 */ {0x582a, 0xbfb0}, /* '堪' -> 22570 */ {0x5830, 0xd1df}, /* '堰' -> 22576 */ {0x5835, 0xb6c2}, /* '堵' -> 22581 */ {0x5844, 0xdca8}, /* '塄' -> 22596 */ {0x584c, 0xcbfa}, /* '塌' -> 22604 */ {0x584d, 0xebf3}, /* '塍' -> 22605 */ {0x5851, 0xcbdc}, /* '塑' -> 22609 */ {0x5854, 0xcbfe}, /* '塔' -> 22612 */ {0x5858, 0xccc1}, /* '塘' -> 22616 */ {0x585e, 0xc8fb}, /* '塞' -> 22622 */ {0x5865, 0xdcaa}, /* '塥' -> 22629 */ {0x586b, 0xccee}, /* '填' -> 22635 */ {0x586c, 0xdcab}, /* '塬' -> 22636 */ {0x587e, 0xdbd3}, /* '塾' -> 22654 */ {0x5880, 0xdcaf}, /* '墀' -> 22656 */ {0x5881, 0xdcac}, /* '墁' -> 22657 */ {0x5883, 0xbeb3}, /* '境' -> 22659 */ {0x5885, 0xcafb}, /* '墅' -> 22661 */ {0x5889, 0xdcad}, /* '墉' -> 22665 */ {0x5892, 0xc9ca}, /* '墒' -> 22674 */ {0x5893, 0xc4b9}, /* '墓' -> 22675 */ {0x5899, 0xc7bd}, /* '墙' -> 22681 */ {0x589a, 0xdcae}, /* '墚' -> 22682 */ {0x589e, 0xd4f6}, /* '增' -> 22686 */ {0x589f, 0xd0e6}, /* '墟' -> 22687 */ {0x58a8, 0xc4ab}, /* '墨' -> 22696 */ {0x58a9, 0xb6d5}, /* '墩' -> 22697 */ {0x58bc, 0xdbd4}, /* '墼' -> 22716 */ {0x58c1, 0xb1da}, /* '壁' -> 22721 */ {0x58c5, 0xdbd5}, /* '壅' -> 22725 */ {0x58d1, 0xdbd6}, /* '壑' -> 22737 */ {0x58d5, 0xbabe}, /* '壕' -> 22741 */ {0x58e4, 0xc8c0}, /* '壤' -> 22756 */ {0x58eb, 0xcabf}, /* '士' -> 22763 */ {0x58ec, 0xc8c9}, /* '壬' -> 22764 */ {0x58ee, 0xd7b3}, /* '壮' -> 22766 */ {0x58f0, 0xc9f9}, /* '声' -> 22768 */ {0x58f3, 0xbfc7}, /* '壳' -> 22771 */ {0x58f6, 0xbaf8}, /* '壶' -> 22774 */ {0x58f9, 0xd2bc}, /* '壹' -> 22777 */ {0x5902, 0xe2ba}, /* '夂' -> 22786 */ {0x5904, 0xb4a6}, /* '处' -> 22788 */ {0x5907, 0xb1b8}, /* '备' -> 22791 */ {0x590d, 0xb8b4}, /* '复' -> 22797 */ {0x590f, 0xcfc4}, /* '夏' -> 22799 */ {0x5914, 0xd9e7}, /* '夔' -> 22804 */ {0x5915, 0xcfa6}, /* '夕' -> 22805 */ {0x5916, 0xcde2}, /* '外' -> 22806 */ {0x5919, 0xd9ed}, /* '夙' -> 22809 */ {0x591a, 0xb6e0}, /* '多' -> 22810 */ {0x591c, 0xd2b9}, /* '夜' -> 22812 */ {0x591f, 0xb9bb}, /* '够' -> 22815 */ {0x5924, 0xe2b9}, /* '夤' -> 22820 */ {0x5925, 0xe2b7}, /* '夥' -> 22821 */ {0x5927, 0xb4f3}, /* '大' -> 22823 */ {0x5929, 0xccec}, /* '天' -> 22825 */ {0x592a, 0xccab}, /* '太' -> 22826 */ {0x592b, 0xb7f2}, /* '夫' -> 22827 */ {0x592d, 0xd8b2}, /* '夭' -> 22829 */ {0x592e, 0xd1eb}, /* '央' -> 22830 */ {0x592f, 0xbabb}, /* '夯' -> 22831 */ {0x5931, 0xcaa7}, /* '失' -> 22833 */ {0x5934, 0xcdb7}, /* '头' -> 22836 */ {0x5937, 0xd2c4}, /* '夷' -> 22839 */ {0x5938, 0xbfe4}, /* '夸' -> 22840 */ {0x5939, 0xbcd0}, /* '夹' -> 22841 */ {0x593a, 0xb6e1}, /* '夺' -> 22842 */ {0x593c, 0xdec5}, /* '夼' -> 22844 */ {0x5941, 0xdec6}, /* '奁' -> 22849 */ {0x5942, 0xdbbc}, /* '奂' -> 22850 */ {0x5944, 0xd1d9}, /* '奄' -> 22852 */ {0x5947, 0xc6e6}, /* '奇' -> 22855 */ {0x5948, 0xc4ce}, /* '奈' -> 22856 */ {0x5949, 0xb7ee}, /* '奉' -> 22857 */ {0x594b, 0xb7dc}, /* '奋' -> 22859 */ {0x594e, 0xbffc}, /* '奎' -> 22862 */ {0x594f, 0xd7e0}, /* '奏' -> 22863 */ {0x5951, 0xc6f5}, /* '契' -> 22865 */ {0x5954, 0xb1bc}, /* '奔' -> 22868 */ {0x5955, 0xdec8}, /* '奕' -> 22869 */ {0x5956, 0xbdb1}, /* '奖' -> 22870 */ {0x5957, 0xccd7}, /* '套' -> 22871 */ {0x5958, 0xdeca}, /* '奘' -> 22872 */ {0x595a, 0xdec9}, /* '奚' -> 22874 */ {0x5960, 0xb5ec}, /* '奠' -> 22880 */ {0x5962, 0xc9dd}, /* '奢' -> 22882 */ {0x5965, 0xb0c2}, /* '奥' -> 22885 */ {0x5973, 0xc5ae}, /* '女' -> 22899 */ {0x5974, 0xc5ab}, /* '奴' -> 22900 */ {0x5976, 0xc4cc}, /* '奶' -> 22902 */ {0x5978, 0xbce9}, /* '奸' -> 22904 */ {0x5979, 0xcbfd}, /* '她' -> 22905 */ {0x597d, 0xbac3}, /* '好' -> 22909 */ {0x5981, 0xe5f9}, /* '妁' -> 22913 */ {0x5982, 0xc8e7}, /* '如' -> 22914 */ {0x5983, 0xe5fa}, /* '妃' -> 22915 */ {0x5984, 0xcdfd}, /* '妄' -> 22916 */ {0x5986, 0xd7b1}, /* '妆' -> 22918 */ {0x5987, 0xb8be}, /* '妇' -> 22919 */ {0x5988, 0xc2e8}, /* '妈' -> 22920 */ {0x598a, 0xc8d1}, /* '妊' -> 22922 */ {0x598d, 0xe5fb}, /* '妍' -> 22925 */ {0x5992, 0xb6ca}, /* '妒' -> 22930 */ {0x5993, 0xbccb}, /* '妓' -> 22931 */ {0x5996, 0xd1fd}, /* '妖' -> 22934 */ {0x5997, 0xe6a1}, /* '妗' -> 22935 */ {0x5999, 0xc3ee}, /* '妙' -> 22937 */ {0x599e, 0xe6a4}, /* '妞' -> 22942 */ {0x59a3, 0xe5fe}, /* '妣' -> 22947 */ {0x59a4, 0xe6a5}, /* '妤' -> 22948 */ {0x59a5, 0xcdd7}, /* '妥' -> 22949 */ {0x59a8, 0xb7c1}, /* '妨' -> 22952 */ {0x59a9, 0xe5fc}, /* '妩' -> 22953 */ {0x59aa, 0xe5fd}, /* '妪' -> 22954 */ {0x59ab, 0xe6a3}, /* '妫' -> 22955 */ {0x59ae, 0xc4dd}, /* '妮' -> 22958 */ {0x59af, 0xe6a8}, /* '妯' -> 22959 */ {0x59b2, 0xe6a7}, /* '妲' -> 22962 */ {0x59b9, 0xc3c3}, /* '妹' -> 22969 */ {0x59bb, 0xc6de}, /* '妻' -> 22971 */ {0x59be, 0xe6aa}, /* '妾' -> 22974 */ {0x59c6, 0xc4b7}, /* '姆' -> 22982 */ {0x59ca, 0xe6a2}, /* '姊' -> 22986 */ {0x59cb, 0xcabc}, /* '始' -> 22987 */ {0x59d0, 0xbde3}, /* '姐' -> 22992 */ {0x59d1, 0xb9c3}, /* '姑' -> 22993 */ {0x59d2, 0xe6a6}, /* '姒' -> 22994 */ {0x59d3, 0xd0d5}, /* '姓' -> 22995 */ {0x59d4, 0xceaf}, /* '委' -> 22996 */ {0x59d7, 0xe6a9}, /* '姗' -> 22999 */ {0x59d8, 0xe6b0}, /* '姘' -> 23000 */ {0x59da, 0xd2a6}, /* '姚' -> 23002 */ {0x59dc, 0xbdaa}, /* '姜' -> 23004 */ {0x59dd, 0xe6ad}, /* '姝' -> 23005 */ {0x59e3, 0xe6af}, /* '姣' -> 23011 */ {0x59e5, 0xc0d1}, /* '姥' -> 23013 */ {0x59e8, 0xd2cc}, /* '姨' -> 23016 */ {0x59ec, 0xbca7}, /* '姬' -> 23020 */ {0x59f9, 0xe6b1}, /* '姹' -> 23033 */ {0x59fb, 0xd2f6}, /* '姻' -> 23035 */ {0x59ff, 0xd7cb}, /* '姿' -> 23039 */ {0x5a01, 0xcdfe}, /* '威' -> 23041 */ {0x5a03, 0xcdde}, /* '娃' -> 23043 */ {0x5a04, 0xc2a6}, /* '娄' -> 23044 */ {0x5a05, 0xe6ab}, /* '娅' -> 23045 */ {0x5a06, 0xe6ac}, /* '娆' -> 23046 */ {0x5a07, 0xbdbf}, /* '娇' -> 23047 */ {0x5a08, 0xe6ae}, /* '娈' -> 23048 */ {0x5a09, 0xe6b3}, /* '娉' -> 23049 */ {0x5a0c, 0xe6b2}, /* '娌' -> 23052 */ {0x5a11, 0xe6b6}, /* '娑' -> 23057 */ {0x5a13, 0xe6b8}, /* '娓' -> 23059 */ {0x5a18, 0xc4ef}, /* '娘' -> 23064 */ {0x5a1c, 0xc4c8}, /* '娜' -> 23068 */ {0x5a1f, 0xbeea}, /* '娟' -> 23071 */ {0x5a20, 0xc9ef}, /* '娠' -> 23072 */ {0x5a23, 0xe6b7}, /* '娣' -> 23075 */ {0x5a25, 0xb6f0}, /* '娥' -> 23077 */ {0x5a29, 0xc3e4}, /* '娩' -> 23081 */ {0x5a31, 0xd3e9}, /* '娱' -> 23089 */ {0x5a32, 0xe6b4}, /* '娲' -> 23090 */ {0x5a34, 0xe6b5}, /* '娴' -> 23092 */ {0x5a36, 0xc8a2}, /* '娶' -> 23094 */ {0x5a3c, 0xe6bd}, /* '娼' -> 23100 */ {0x5a40, 0xe6b9}, /* '婀' -> 23104 */ {0x5a46, 0xc6c5}, /* '婆' -> 23110 */ {0x5a49, 0xcdf1}, /* '婉' -> 23113 */ {0x5a4a, 0xe6bb}, /* '婊' -> 23114 */ {0x5a55, 0xe6bc}, /* '婕' -> 23125 */ {0x5a5a, 0xbbe9}, /* '婚' -> 23130 */ {0x5a62, 0xe6be}, /* '婢' -> 23138 */ {0x5a67, 0xe6ba}, /* '婧' -> 23143 */ {0x5a6a, 0xc0b7}, /* '婪' -> 23146 */ {0x5a74, 0xd3a4}, /* '婴' -> 23156 */ {0x5a75, 0xe6bf}, /* '婵' -> 23157 */ {0x5a76, 0xc9f4}, /* '婶' -> 23158 */ {0x5a77, 0xe6c3}, /* '婷' -> 23159 */ {0x5a7a, 0xe6c4}, /* '婺' -> 23162 */ {0x5a7f, 0xd0f6}, /* '婿' -> 23167 */ {0x5a92, 0xc3bd}, /* '媒' -> 23186 */ {0x5a9a, 0xc3c4}, /* '媚' -> 23194 */ {0x5a9b, 0xe6c2}, /* '媛' -> 23195 */ {0x5aaa, 0xe6c1}, /* '媪' -> 23210 */ {0x5ab2, 0xe6c7}, /* '媲' -> 23218 */ {0x5ab3, 0xcfb1}, /* '媳' -> 23219 */ {0x5ab5, 0xebf4}, /* '媵' -> 23221 */ {0x5ab8, 0xe6ca}, /* '媸' -> 23224 */ {0x5abe, 0xe6c5}, /* '媾' -> 23230 */ {0x5ac1, 0xbcde}, /* '嫁' -> 23233 */ {0x5ac2, 0xc9a9}, /* '嫂' -> 23234 */ {0x5ac9, 0xbcb5}, /* '嫉' -> 23241 */ {0x5acc, 0xcfd3}, /* '嫌' -> 23244 */ {0x5ad2, 0xe6c8}, /* '嫒' -> 23250 */ {0x5ad4, 0xe6c9}, /* '嫔' -> 23252 */ {0x5ad6, 0xe6ce}, /* '嫖' -> 23254 */ {0x5ad8, 0xe6d0}, /* '嫘' -> 23256 */ {0x5adc, 0xe6d1}, /* '嫜' -> 23260 */ {0x5ae0, 0xe6cb}, /* '嫠' -> 23264 */ {0x5ae1, 0xb5d5}, /* '嫡' -> 23265 */ {0x5ae3, 0xe6cc}, /* '嫣' -> 23267 */ {0x5ae6, 0xe6cf}, /* '嫦' -> 23270 */ {0x5ae9, 0xc4db}, /* '嫩' -> 23273 */ {0x5aeb, 0xe6c6}, /* '嫫' -> 23275 */ {0x5af1, 0xe6cd}, /* '嫱' -> 23281 */ {0x5b09, 0xe6d2}, /* '嬉' -> 23305 */ {0x5b16, 0xe6d4}, /* '嬖' -> 23318 */ {0x5b17, 0xe6d3}, /* '嬗' -> 23319 */ {0x5b32, 0xe6d5}, /* '嬲' -> 23346 */ {0x5b34, 0xd9f8}, /* '嬴' -> 23348 */ {0x5b37, 0xe6d6}, /* '嬷' -> 23351 */ {0x5b40, 0xe6d7}, /* '孀' -> 23360 */ {0x5b50, 0xd7d3}, /* '子' -> 23376 */ {0x5b51, 0xe6dd}, /* '孑' -> 23377 */ {0x5b53, 0xe6de}, /* '孓' -> 23379 */ {0x5b54, 0xbfd7}, /* '孔' -> 23380 */ {0x5b55, 0xd4d0}, /* '孕' -> 23381 */ {0x5b57, 0xd7d6}, /* '字' -> 23383 */ {0x5b58, 0xb4e6}, /* '存' -> 23384 */ {0x5b59, 0xcbef}, /* '孙' -> 23385 */ {0x5b5a, 0xe6da}, /* '孚' -> 23386 */ {0x5b5b, 0xd8c3}, /* '孛' -> 23387 */ {0x5b5c, 0xd7ce}, /* '孜' -> 23388 */ {0x5b5d, 0xd0a2}, /* '孝' -> 23389 */ {0x5b5f, 0xc3cf}, /* '孟' -> 23391 */ {0x5b62, 0xe6df}, /* '孢' -> 23394 */ {0x5b63, 0xbcbe}, /* '季' -> 23395 */ {0x5b64, 0xb9c2}, /* '孤' -> 23396 */ {0x5b65, 0xe6db}, /* '孥' -> 23397 */ {0x5b66, 0xd1a7}, /* '学' -> 23398 */ {0x5b69, 0xbaa2}, /* '孩' -> 23401 */ {0x5b6a, 0xc2cf}, /* '孪' -> 23402 */ {0x5b6c, 0xd8ab}, /* '孬' -> 23404 */ {0x5b70, 0xcaeb}, /* '孰' -> 23408 */ {0x5b71, 0xe5ee}, /* '孱' -> 23409 */ {0x5b73, 0xe6dc}, /* '孳' -> 23411 */ {0x5b75, 0xb7f5}, /* '孵' -> 23413 */ {0x5b7a, 0xc8e6}, /* '孺' -> 23418 */ {0x5b7d, 0xc4f5}, /* '孽' -> 23421 */ {0x5b80, 0xe5b2}, /* '宀' -> 23424 */ {0x5b81, 0xc4fe}, /* '宁' -> 23425 */ {0x5b83, 0xcbfc}, /* '它' -> 23427 */ {0x5b84, 0xe5b3}, /* '宄' -> 23428 */ {0x5b85, 0xd5ac}, /* '宅' -> 23429 */ {0x5b87, 0xd3ee}, /* '宇' -> 23431 */ {0x5b88, 0xcad8}, /* '守' -> 23432 */ {0x5b89, 0xb0b2}, /* '安' -> 23433 */ {0x5b8b, 0xcbce}, /* '宋' -> 23435 */ {0x5b8c, 0xcdea}, /* '完' -> 23436 */ {0x5b8f, 0xbaea}, /* '宏' -> 23439 */ {0x5b93, 0xe5b5}, /* '宓' -> 23443 */ {0x5b95, 0xe5b4}, /* '宕' -> 23445 */ {0x5b97, 0xd7da}, /* '宗' -> 23447 */ {0x5b98, 0xb9d9}, /* '官' -> 23448 */ {0x5b99, 0xd6e6}, /* '宙' -> 23449 */ {0x5b9a, 0xb6a8}, /* '定' -> 23450 */ {0x5b9b, 0xcdf0}, /* '宛' -> 23451 */ {0x5b9c, 0xd2cb}, /* '宜' -> 23452 */ {0x5b9d, 0xb1a6}, /* '宝' -> 23453 */ {0x5b9e, 0xcab5}, /* '实' -> 23454 */ {0x5ba0, 0xb3e8}, /* '宠' -> 23456 */ {0x5ba1, 0xc9f3}, /* '审' -> 23457 */ {0x5ba2, 0xbfcd}, /* '客' -> 23458 */ {0x5ba3, 0xd0fb}, /* '宣' -> 23459 */ {0x5ba4, 0xcad2}, /* '室' -> 23460 */ {0x5ba5, 0xe5b6}, /* '宥' -> 23461 */ {0x5ba6, 0xbbc2}, /* '宦' -> 23462 */ {0x5baa, 0xcfdc}, /* '宪' -> 23466 */ {0x5bab, 0xb9ac}, /* '宫' -> 23467 */ {0x5bb0, 0xd4d7}, /* '宰' -> 23472 */ {0x5bb3, 0xbaa6}, /* '害' -> 23475 */ {0x5bb4, 0xd1e7}, /* '宴' -> 23476 */ {0x5bb5, 0xcffc}, /* '宵' -> 23477 */ {0x5bb6, 0xbcd2}, /* '家' -> 23478 */ {0x5bb8, 0xe5b7}, /* '宸' -> 23480 */ {0x5bb9, 0xc8dd}, /* '容' -> 23481 */ {0x5bbd, 0xbfed}, /* '宽' -> 23485 */ {0x5bbe, 0xb1f6}, /* '宾' -> 23486 */ {0x5bbf, 0xcbde}, /* '宿' -> 23487 */ {0x5bc2, 0xbcc5}, /* '寂' -> 23490 */ {0x5bc4, 0xbcc4}, /* '寄' -> 23492 */ {0x5bc5, 0xd2fa}, /* '寅' -> 23493 */ {0x5bc6, 0xc3dc}, /* '密' -> 23494 */ {0x5bc7, 0xbfdc}, /* '寇' -> 23495 */ {0x5bcc, 0xb8bb}, /* '富' -> 23500 */ {0x5bd0, 0xc3c2}, /* '寐' -> 23504 */ {0x5bd2, 0xbaae}, /* '寒' -> 23506 */ {0x5bd3, 0xd4a2}, /* '寓' -> 23507 */ {0x5bdd, 0xc7de}, /* '寝' -> 23517 */ {0x5bde, 0xc4af}, /* '寞' -> 23518 */ {0x5bdf, 0xb2ec}, /* '察' -> 23519 */ {0x5be1, 0xb9d1}, /* '寡' -> 23521 */ {0x5be4, 0xe5bb}, /* '寤' -> 23524 */ {0x5be5, 0xc1c8}, /* '寥' -> 23525 */ {0x5be8, 0xd5af}, /* '寨' -> 23528 */ {0x5bee, 0xe5bc}, /* '寮' -> 23534 */ {0x5bf0, 0xe5be}, /* '寰' -> 23536 */ {0x5bf8, 0xb4e7}, /* '寸' -> 23544 */ {0x5bf9, 0xb6d4}, /* '对' -> 23545 */ {0x5bfa, 0xcbc2}, /* '寺' -> 23546 */ {0x5bfb, 0xd1b0}, /* '寻' -> 23547 */ {0x5bfc, 0xb5bc}, /* '导' -> 23548 */ {0x5bff, 0xcad9}, /* '寿' -> 23551 */ {0x5c01, 0xb7e2}, /* '封' -> 23553 */ {0x5c04, 0xc9e4}, /* '射' -> 23556 */ {0x5c06, 0xbdab}, /* '将' -> 23558 */ {0x5c09, 0xcebe}, /* '尉' -> 23561 */ {0x5c0a, 0xd7f0}, /* '尊' -> 23562 */ {0x5c0f, 0xd0a1}, /* '小' -> 23567 */ {0x5c11, 0xc9d9}, /* '少' -> 23569 */ {0x5c14, 0xb6fb}, /* '尔' -> 23572 */ {0x5c15, 0xe6d8}, /* '尕' -> 23573 */ {0x5c16, 0xbce2}, /* '尖' -> 23574 */ {0x5c18, 0xb3be}, /* '尘' -> 23576 */ {0x5c1a, 0xc9d0}, /* '尚' -> 23578 */ {0x5c1c, 0xe6d9}, /* '尜' -> 23580 */ {0x5c1d, 0xb3a2}, /* '尝' -> 23581 */ {0x5c22, 0xdecc}, /* '尢' -> 23586 */ {0x5c24, 0xd3c8}, /* '尤' -> 23588 */ {0x5c25, 0xdecd}, /* '尥' -> 23589 */ {0x5c27, 0xd2a2}, /* '尧' -> 23591 */ {0x5c2c, 0xdece}, /* '尬' -> 23596 */ {0x5c31, 0xbecd}, /* '就' -> 23601 */ {0x5c34, 0xdecf}, /* '尴' -> 23604 */ {0x5c38, 0xcaac}, /* '尸' -> 23608 */ {0x5c39, 0xd2fc}, /* '尹' -> 23609 */ {0x5c3a, 0xb3df}, /* '尺' -> 23610 */ {0x5c3b, 0xe5ea}, /* '尻' -> 23611 */ {0x5c3c, 0xc4e1}, /* '尼' -> 23612 */ {0x5c3d, 0xbea1}, /* '尽' -> 23613 */ {0x5c3e, 0xceb2}, /* '尾' -> 23614 */ {0x5c3f, 0xc4f2}, /* '尿' -> 23615 */ {0x5c40, 0xbed6}, /* '局' -> 23616 */ {0x5c41, 0xc6a8}, /* '屁' -> 23617 */ {0x5c42, 0xb2e3}, /* '层' -> 23618 */ {0x5c45, 0xbed3}, /* '居' -> 23621 */ {0x5c48, 0xc7fc}, /* '屈' -> 23624 */ {0x5c49, 0xcceb}, /* '屉' -> 23625 */ {0x5c4a, 0xbdec}, /* '届' -> 23626 */ {0x5c4b, 0xcedd}, /* '屋' -> 23627 */ {0x5c4e, 0xcaba}, /* '屎' -> 23630 */ {0x5c4f, 0xc6c1}, /* '屏' -> 23631 */ {0x5c50, 0xe5ec}, /* '屐' -> 23632 */ {0x5c51, 0xd0bc}, /* '屑' -> 23633 */ {0x5c55, 0xd5b9}, /* '展' -> 23637 */ {0x5c59, 0xe5ed}, /* '屙' -> 23641 */ {0x5c5e, 0xcaf4}, /* '属' -> 23646 */ {0x5c60, 0xcdc0}, /* '屠' -> 23648 */ {0x5c61, 0xc2c5}, /* '屡' -> 23649 */ {0x5c63, 0xe5ef}, /* '屣' -> 23651 */ {0x5c65, 0xc2c4}, /* '履' -> 23653 */ {0x5c66, 0xe5f0}, /* '屦' -> 23654 */ {0x5c6e, 0xe5f8}, /* '屮' -> 23662 */ {0x5c6f, 0xcdcd}, /* '屯' -> 23663 */ {0x5c71, 0xc9bd}, /* '山' -> 23665 */ {0x5c79, 0xd2d9}, /* '屹' -> 23673 */ {0x5c7a, 0xe1a8}, /* '屺' -> 23674 */ {0x5c7f, 0xd3ec}, /* '屿' -> 23679 */ {0x5c81, 0xcbea}, /* '岁' -> 23681 */ {0x5c82, 0xc6f1}, /* '岂' -> 23682 */ {0x5c88, 0xe1ac}, /* '岈' -> 23688 */ {0x5c8c, 0xe1a7}, /* '岌' -> 23692 */ {0x5c8d, 0xe1a9}, /* '岍' -> 23693 */ {0x5c90, 0xe1aa}, /* '岐' -> 23696 */ {0x5c91, 0xe1af}, /* '岑' -> 23697 */ {0x5c94, 0xb2ed}, /* '岔' -> 23700 */ {0x5c96, 0xe1ab}, /* '岖' -> 23702 */ {0x5c97, 0xb8da}, /* '岗' -> 23703 */ {0x5c98, 0xe1ad}, /* '岘' -> 23704 */ {0x5c99, 0xe1ae}, /* '岙' -> 23705 */ {0x5c9a, 0xe1b0}, /* '岚' -> 23706 */ {0x5c9b, 0xb5ba}, /* '岛' -> 23707 */ {0x5c9c, 0xe1b1}, /* '岜' -> 23708 */ {0x5ca2, 0xe1b3}, /* '岢' -> 23714 */ {0x5ca3, 0xe1b8}, /* '岣' -> 23715 */ {0x5ca9, 0xd1d2}, /* '岩' -> 23721 */ {0x5cab, 0xe1b6}, /* '岫' -> 23723 */ {0x5cac, 0xe1b5}, /* '岬' -> 23724 */ {0x5cad, 0xc1eb}, /* '岭' -> 23725 */ {0x5cb1, 0xe1b7}, /* '岱' -> 23729 */ {0x5cb3, 0xd4c0}, /* '岳' -> 23731 */ {0x5cb5, 0xe1b2}, /* '岵' -> 23733 */ {0x5cb7, 0xe1ba}, /* '岷' -> 23735 */ {0x5cb8, 0xb0b6}, /* '岸' -> 23736 */ {0x5cbd, 0xe1b4}, /* '岽' -> 23741 */ {0x5cbf, 0xbff9}, /* '岿' -> 23743 */ {0x5cc1, 0xe1b9}, /* '峁' -> 23745 */ {0x5cc4, 0xe1bb}, /* '峄' -> 23748 */ {0x5ccb, 0xe1be}, /* '峋' -> 23755 */ {0x5cd2, 0xe1bc}, /* '峒' -> 23762 */ {0x5cd9, 0xd6c5}, /* '峙' -> 23769 */ {0x5ce1, 0xcfbf}, /* '峡' -> 23777 */ {0x5ce4, 0xe1bd}, /* '峤' -> 23780 */ {0x5ce5, 0xe1bf}, /* '峥' -> 23781 */ {0x5ce6, 0xc2cd}, /* '峦' -> 23782 */ {0x5ce8, 0xb6eb}, /* '峨' -> 23784 */ {0x5cea, 0xd3f8}, /* '峪' -> 23786 */ {0x5ced, 0xc7cd}, /* '峭' -> 23789 */ {0x5cf0, 0xb7e5}, /* '峰' -> 23792 */ {0x5cfb, 0xbefe}, /* '峻' -> 23803 */ {0x5d02, 0xe1c0}, /* '崂' -> 23810 */ {0x5d03, 0xe1c1}, /* '崃' -> 23811 */ {0x5d06, 0xe1c7}, /* '崆' -> 23814 */ {0x5d07, 0xb3e7}, /* '崇' -> 23815 */ {0x5d0e, 0xc6e9}, /* '崎' -> 23822 */ {0x5d14, 0xb4de}, /* '崔' -> 23828 */ {0x5d16, 0xd1c2}, /* '崖' -> 23830 */ {0x5d1b, 0xe1c8}, /* '崛' -> 23835 */ {0x5d1e, 0xe1c6}, /* '崞' -> 23838 */ {0x5d24, 0xe1c5}, /* '崤' -> 23844 */ {0x5d26, 0xe1c3}, /* '崦' -> 23846 */ {0x5d27, 0xe1c2}, /* '崧' -> 23847 */ {0x5d29, 0xb1c0}, /* '崩' -> 23849 */ {0x5d2d, 0xd5b8}, /* '崭' -> 23853 */ {0x5d2e, 0xe1c4}, /* '崮' -> 23854 */ {0x5d34, 0xe1cb}, /* '崴' -> 23860 */ {0x5d3d, 0xe1cc}, /* '崽' -> 23869 */ {0x5d3e, 0xe1ca}, /* '崾' -> 23870 */ {0x5d47, 0xeffa}, /* '嵇' -> 23879 */ {0x5d4a, 0xe1d3}, /* '嵊' -> 23882 */ {0x5d4b, 0xe1d2}, /* '嵋' -> 23883 */ {0x5d4c, 0xc7b6}, /* '嵌' -> 23884 */ {0x5d58, 0xe1c9}, /* '嵘' -> 23896 */ {0x5d5b, 0xe1ce}, /* '嵛' -> 23899 */ {0x5d5d, 0xe1d0}, /* '嵝' -> 23901 */ {0x5d69, 0xe1d4}, /* '嵩' -> 23913 */ {0x5d6b, 0xe1d1}, /* '嵫' -> 23915 */ {0x5d6c, 0xe1cd}, /* '嵬' -> 23916 */ {0x5d6f, 0xe1cf}, /* '嵯' -> 23919 */ {0x5d74, 0xe1d5}, /* '嵴' -> 23924 */ {0x5d82, 0xe1d6}, /* '嶂' -> 23938 */ {0x5d99, 0xe1d7}, /* '嶙' -> 23961 */ {0x5d9d, 0xe1d8}, /* '嶝' -> 23965 */ {0x5db7, 0xe1da}, /* '嶷' -> 23991 */ {0x5dc5, 0xe1db}, /* '巅' -> 24005 */ {0x5dcd, 0xcea1}, /* '巍' -> 24013 */ {0x5ddb, 0xe7dd}, /* '巛' -> 24027 */ {0x5ddd, 0xb4a8}, /* '川' -> 24029 */ {0x5dde, 0xd6dd}, /* '州' -> 24030 */ {0x5de1, 0xd1b2}, /* '巡' -> 24033 */ {0x5de2, 0xb3b2}, /* '巢' -> 24034 */ {0x5de5, 0xb9a4}, /* '工' -> 24037 */ {0x5de6, 0xd7f3}, /* '左' -> 24038 */ {0x5de7, 0xc7c9}, /* '巧' -> 24039 */ {0x5de8, 0xbede}, /* '巨' -> 24040 */ {0x5de9, 0xb9ae}, /* '巩' -> 24041 */ {0x5deb, 0xced7}, /* '巫' -> 24043 */ {0x5dee, 0xb2ee}, /* '差' -> 24046 */ {0x5def, 0xdbcf}, /* '巯' -> 24047 */ {0x5df1, 0xbcba}, /* '己' -> 24049 */ {0x5df2, 0xd2d1}, /* '已' -> 24050 */ {0x5df3, 0xcbc8}, /* '巳' -> 24051 */ {0x5df4, 0xb0cd}, /* '巴' -> 24052 */ {0x5df7, 0xcfef}, /* '巷' -> 24055 */ {0x5dfd, 0xd9e3}, /* '巽' -> 24061 */ {0x5dfe, 0xbded}, /* '巾' -> 24062 */ {0x5e01, 0xb1d2}, /* '币' -> 24065 */ {0x5e02, 0xcad0}, /* '市' -> 24066 */ {0x5e03, 0xb2bc}, /* '布' -> 24067 */ {0x5e05, 0xcba7}, /* '帅' -> 24069 */ {0x5e06, 0xb7ab}, /* '帆' -> 24070 */ {0x5e08, 0xcaa6}, /* '师' -> 24072 */ {0x5e0c, 0xcfa3}, /* '希' -> 24076 */ {0x5e0f, 0xe0f8}, /* '帏' -> 24079 */ {0x5e10, 0xd5ca}, /* '帐' -> 24080 */ {0x5e11, 0xe0fb}, /* '帑' -> 24081 */ {0x5e14, 0xe0fa}, /* '帔' -> 24084 */ {0x5e15, 0xc5c1}, /* '帕' -> 24085 */ {0x5e16, 0xccfb}, /* '帖' -> 24086 */ {0x5e18, 0xc1b1}, /* '帘' -> 24088 */ {0x5e19, 0xe0f9}, /* '帙' -> 24089 */ {0x5e1a, 0xd6e3}, /* '帚' -> 24090 */ {0x5e1b, 0xb2af}, /* '帛' -> 24091 */ {0x5e1c, 0xd6c4}, /* '帜' -> 24092 */ {0x5e1d, 0xb5db}, /* '帝' -> 24093 */ {0x5e26, 0xb4f8}, /* '带' -> 24102 */ {0x5e27, 0xd6a1}, /* '帧' -> 24103 */ {0x5e2d, 0xcfaf}, /* '席' -> 24109 */ {0x5e2e, 0xb0ef}, /* '帮' -> 24110 */ {0x5e31, 0xe0fc}, /* '帱' -> 24113 */ {0x5e37, 0xe1a1}, /* '帷' -> 24119 */ {0x5e38, 0xb3a3}, /* '常' -> 24120 */ {0x5e3b, 0xe0fd}, /* '帻' -> 24123 */ {0x5e3c, 0xe0fe}, /* '帼' -> 24124 */ {0x5e3d, 0xc3b1}, /* '帽' -> 24125 */ {0x5e42, 0xc3dd}, /* '幂' -> 24130 */ {0x5e44, 0xe1a2}, /* '幄' -> 24132 */ {0x5e45, 0xb7f9}, /* '幅' -> 24133 */ {0x5e4c, 0xbbcf}, /* '幌' -> 24140 */ {0x5e54, 0xe1a3}, /* '幔' -> 24148 */ {0x5e55, 0xc4bb}, /* '幕' -> 24149 */ {0x5e5b, 0xe1a4}, /* '幛' -> 24155 */ {0x5e5e, 0xe1a5}, /* '幞' -> 24158 */ {0x5e61, 0xe1a6}, /* '幡' -> 24161 */ {0x5e62, 0xb4b1}, /* '幢' -> 24162 */ {0x5e72, 0xb8c9}, /* '干' -> 24178 */ {0x5e73, 0xc6bd}, /* '平' -> 24179 */ {0x5e74, 0xc4ea}, /* '年' -> 24180 */ {0x5e76, 0xb2a2}, /* '并' -> 24182 */ {0x5e78, 0xd0d2}, /* '幸' -> 24184 */ {0x5e7a, 0xe7db}, /* '幺' -> 24186 */ {0x5e7b, 0xbbc3}, /* '幻' -> 24187 */ {0x5e7c, 0xd3d7}, /* '幼' -> 24188 */ {0x5e7d, 0xd3c4}, /* '幽' -> 24189 */ {0x5e7f, 0xb9e3}, /* '广' -> 24191 */ {0x5e80, 0xe2cf}, /* '庀' -> 24192 */ {0x5e84, 0xd7af}, /* '庄' -> 24196 */ {0x5e86, 0xc7ec}, /* '庆' -> 24198 */ {0x5e87, 0xb1d3}, /* '庇' -> 24199 */ {0x5e8a, 0xb4b2}, /* '床' -> 24202 */ {0x5e8b, 0xe2d1}, /* '庋' -> 24203 */ {0x5e8f, 0xd0f2}, /* '序' -> 24207 */ {0x5e90, 0xc2ae}, /* '庐' -> 24208 */ {0x5e91, 0xe2d0}, /* '庑' -> 24209 */ {0x5e93, 0xbfe2}, /* '库' -> 24211 */ {0x5e94, 0xd3a6}, /* '应' -> 24212 */ {0x5e95, 0xb5d7}, /* '底' -> 24213 */ {0x5e96, 0xe2d2}, /* '庖' -> 24214 */ {0x5e97, 0xb5ea}, /* '店' -> 24215 */ {0x5e99, 0xc3ed}, /* '庙' -> 24217 */ {0x5e9a, 0xb8fd}, /* '庚' -> 24218 */ {0x5e9c, 0xb8ae}, /* '府' -> 24220 */ {0x5e9e, 0xc5d3}, /* '庞' -> 24222 */ {0x5e9f, 0xb7cf}, /* '废' -> 24223 */ {0x5ea0, 0xe2d4}, /* '庠' -> 24224 */ {0x5ea5, 0xe2d3}, /* '庥' -> 24229 */ {0x5ea6, 0xb6c8}, /* '度' -> 24230 */ {0x5ea7, 0xd7f9}, /* '座' -> 24231 */ {0x5ead, 0xcda5}, /* '庭' -> 24237 */ {0x5eb3, 0xe2d8}, /* '庳' -> 24243 */ {0x5eb5, 0xe2d6}, /* '庵' -> 24245 */ {0x5eb6, 0xcafc}, /* '庶' -> 24246 */ {0x5eb7, 0xbfb5}, /* '康' -> 24247 */ {0x5eb8, 0xd3b9}, /* '庸' -> 24248 */ {0x5eb9, 0xe2d5}, /* '庹' -> 24249 */ {0x5ebe, 0xe2d7}, /* '庾' -> 24254 */ {0x5ec9, 0xc1ae}, /* '廉' -> 24265 */ {0x5eca, 0xc0c8}, /* '廊' -> 24266 */ {0x5ed1, 0xe2db}, /* '廑' -> 24273 */ {0x5ed2, 0xe2da}, /* '廒' -> 24274 */ {0x5ed3, 0xc0aa}, /* '廓' -> 24275 */ {0x5ed6, 0xc1ce}, /* '廖' -> 24278 */ {0x5edb, 0xe2dc}, /* '廛' -> 24283 */ {0x5ee8, 0xe2dd}, /* '廨' -> 24296 */ {0x5eea, 0xe2de}, /* '廪' -> 24298 */ {0x5ef4, 0xdbc8}, /* '廴' -> 24308 */ {0x5ef6, 0xd1d3}, /* '延' -> 24310 */ {0x5ef7, 0xcda2}, /* '廷' -> 24311 */ {0x5efa, 0xbda8}, /* '建' -> 24314 */ {0x5efe, 0xdec3}, /* '廾' -> 24318 */ {0x5eff, 0xd8a5}, /* '廿' -> 24319 */ {0x5f00, 0xbfaa}, /* '开' -> 24320 */ {0x5f01, 0xdbcd}, /* '弁' -> 24321 */ {0x5f02, 0xd2ec}, /* '异' -> 24322 */ {0x5f03, 0xc6fa}, /* '弃' -> 24323 */ {0x5f04, 0xc5aa}, /* '弄' -> 24324 */ {0x5f08, 0xdec4}, /* '弈' -> 24328 */ {0x5f0a, 0xb1d7}, /* '弊' -> 24330 */ {0x5f0b, 0xdfae}, /* '弋' -> 24331 */ {0x5f0f, 0xcabd}, /* '式' -> 24335 */ {0x5f11, 0xdfb1}, /* '弑' -> 24337 */ {0x5f13, 0xb9ad}, /* '弓' -> 24339 */ {0x5f15, 0xd2fd}, /* '引' -> 24341 */ {0x5f17, 0xb8a5}, /* '弗' -> 24343 */ {0x5f18, 0xbaeb}, /* '弘' -> 24344 */ {0x5f1b, 0xb3da}, /* '弛' -> 24347 */ {0x5f1f, 0xb5dc}, /* '弟' -> 24351 */ {0x5f20, 0xd5c5}, /* '张' -> 24352 */ {0x5f25, 0xc3d6}, /* '弥' -> 24357 */ {0x5f26, 0xcfd2}, /* '弦' -> 24358 */ {0x5f27, 0xbba1}, /* '弧' -> 24359 */ {0x5f29, 0xe5f3}, /* '弩' -> 24361 */ {0x5f2a, 0xe5f2}, /* '弪' -> 24362 */ {0x5f2d, 0xe5f4}, /* '弭' -> 24365 */ {0x5f2f, 0xcde4}, /* '弯' -> 24367 */ {0x5f31, 0xc8f5}, /* '弱' -> 24369 */ {0x5f39, 0xb5af}, /* '弹' -> 24377 */ {0x5f3a, 0xc7bf}, /* '强' -> 24378 */ {0x5f3c, 0xe5f6}, /* '弼' -> 24380 */ {0x5f40, 0xecb0}, /* '彀' -> 24384 */ {0x5f50, 0xe5e6}, /* '彐' -> 24400 */ {0x5f52, 0xb9e9}, /* '归' -> 24402 */ {0x5f53, 0xb5b1}, /* '当' -> 24403 */ {0x5f55, 0xc2bc}, /* '录' -> 24405 */ {0x5f56, 0xe5e8}, /* '彖' -> 24406 */ {0x5f57, 0xe5e7}, /* '彗' -> 24407 */ {0x5f58, 0xe5e9}, /* '彘' -> 24408 */ {0x5f5d, 0xd2cd}, /* '彝' -> 24413 */ {0x5f61, 0xe1ea}, /* '彡' -> 24417 */ {0x5f62, 0xd0ce}, /* '形' -> 24418 */ {0x5f64, 0xcdae}, /* '彤' -> 24420 */ {0x5f66, 0xd1e5}, /* '彦' -> 24422 */ {0x5f69, 0xb2ca}, /* '彩' -> 24425 */ {0x5f6a, 0xb1eb}, /* '彪' -> 24426 */ {0x5f6c, 0xb1f2}, /* '彬' -> 24428 */ {0x5f6d, 0xc5ed}, /* '彭' -> 24429 */ {0x5f70, 0xd5c3}, /* '彰' -> 24432 */ {0x5f71, 0xd3b0}, /* '影' -> 24433 */ {0x5f73, 0xe1dc}, /* '彳' -> 24435 */ {0x5f77, 0xe1dd}, /* '彷' -> 24439 */ {0x5f79, 0xd2db}, /* '役' -> 24441 */ {0x5f7b, 0xb3b9}, /* '彻' -> 24443 */ {0x5f7c, 0xb1cb}, /* '彼' -> 24444 */ {0x5f80, 0xcdf9}, /* '往' -> 24448 */ {0x5f81, 0xd5f7}, /* '征' -> 24449 */ {0x5f82, 0xe1de}, /* '徂' -> 24450 */ {0x5f84, 0xbeb6}, /* '径' -> 24452 */ {0x5f85, 0xb4fd}, /* '待' -> 24453 */ {0x5f87, 0xe1df}, /* '徇' -> 24455 */ {0x5f88, 0xbadc}, /* '很' -> 24456 */ {0x5f89, 0xe1e0}, /* '徉' -> 24457 */ {0x5f8a, 0xbbb2}, /* '徊' -> 24458 */ {0x5f8b, 0xc2c9}, /* '律' -> 24459 */ {0x5f8c, 0xe1e1}, /* '後' -> 24460 */ {0x5f90, 0xd0ec}, /* '徐' -> 24464 */ {0x5f92, 0xcdbd}, /* '徒' -> 24466 */ {0x5f95, 0xe1e2}, /* '徕' -> 24469 */ {0x5f97, 0xb5c3}, /* '得' -> 24471 */ {0x5f98, 0xc5c7}, /* '徘' -> 24472 */ {0x5f99, 0xe1e3}, /* '徙' -> 24473 */ {0x5f9c, 0xe1e4}, /* '徜' -> 24476 */ {0x5fa1, 0xd3f9}, /* '御' -> 24481 */ {0x5fa8, 0xe1e5}, /* '徨' -> 24488 */ {0x5faa, 0xd1ad}, /* '循' -> 24490 */ {0x5fad, 0xe1e6}, /* '徭' -> 24493 */ {0x5fae, 0xcea2}, /* '微' -> 24494 */ {0x5fb5, 0xe1e7}, /* '徵' -> 24501 */ {0x5fb7, 0xb5c2}, /* '德' -> 24503 */ {0x5fbc, 0xe1e8}, /* '徼' -> 24508 */ {0x5fbd, 0xbbd5}, /* '徽' -> 24509 */ {0x5fc3, 0xd0c4}, /* '心' -> 24515 */ {0x5fc4, 0xe2e0}, /* '忄' -> 24516 */ {0x5fc5, 0xb1d8}, /* '必' -> 24517 */ {0x5fc6, 0xd2e4}, /* '忆' -> 24518 */ {0x5fc9, 0xe2e1}, /* '忉' -> 24521 */ {0x5fcc, 0xbcc9}, /* '忌' -> 24524 */ {0x5fcd, 0xc8cc}, /* '忍' -> 24525 */ {0x5fcf, 0xe2e3}, /* '忏' -> 24527 */ {0x5fd0, 0xecfe}, /* '忐' -> 24528 */ {0x5fd1, 0xecfd}, /* '忑' -> 24529 */ {0x5fd2, 0xdfaf}, /* '忒' -> 24530 */ {0x5fd6, 0xe2e2}, /* '忖' -> 24534 */ {0x5fd7, 0xd6be}, /* '志' -> 24535 */ {0x5fd8, 0xcdfc}, /* '忘' -> 24536 */ {0x5fd9, 0xc3a6}, /* '忙' -> 24537 */ {0x5fdd, 0xe3c3}, /* '忝' -> 24541 */ {0x5fe0, 0xd6d2}, /* '忠' -> 24544 */ {0x5fe1, 0xe2e7}, /* '忡' -> 24545 */ {0x5fe4, 0xe2e8}, /* '忤' -> 24548 */ {0x5fe7, 0xd3c7}, /* '忧' -> 24551 */ {0x5fea, 0xe2ec}, /* '忪' -> 24554 */ {0x5feb, 0xbfec}, /* '快' -> 24555 */ {0x5fed, 0xe2ed}, /* '忭' -> 24557 */ {0x5fee, 0xe2e5}, /* '忮' -> 24558 */ {0x5ff1, 0xb3c0}, /* '忱' -> 24561 */ {0x5ff5, 0xc4ee}, /* '念' -> 24565 */ {0x5ff8, 0xe2ee}, /* '忸' -> 24568 */ {0x5ffb, 0xd0c3}, /* '忻' -> 24571 */ {0x5ffd, 0xbaf6}, /* '忽' -> 24573 */ {0x5ffe, 0xe2e9}, /* '忾' -> 24574 */ {0x5fff, 0xb7de}, /* '忿' -> 24575 */ {0x6000, 0xbbb3}, /* '怀' -> 24576 */ {0x6001, 0xccac}, /* '态' -> 24577 */ {0x6002, 0xcbcb}, /* '怂' -> 24578 */ {0x6003, 0xe2e4}, /* '怃' -> 24579 */ {0x6004, 0xe2e6}, /* '怄' -> 24580 */ {0x6005, 0xe2ea}, /* '怅' -> 24581 */ {0x6006, 0xe2eb}, /* '怆' -> 24582 */ {0x600a, 0xe2f7}, /* '怊' -> 24586 */ {0x600d, 0xe2f4}, /* '怍' -> 24589 */ {0x600e, 0xd4f5}, /* '怎' -> 24590 */ {0x600f, 0xe2f3}, /* '怏' -> 24591 */ {0x6012, 0xc5ad}, /* '怒' -> 24594 */ {0x6014, 0xd5fa}, /* '怔' -> 24596 */ {0x6015, 0xc5c2}, /* '怕' -> 24597 */ {0x6016, 0xb2c0}, /* '怖' -> 24598 */ {0x6019, 0xe2ef}, /* '怙' -> 24601 */ {0x601b, 0xe2f2}, /* '怛' -> 24603 */ {0x601c, 0xc1af}, /* '怜' -> 24604 */ {0x601d, 0xcbbc}, /* '思' -> 24605 */ {0x6020, 0xb5a1}, /* '怠' -> 24608 */ {0x6021, 0xe2f9}, /* '怡' -> 24609 */ {0x6025, 0xbcb1}, /* '急' -> 24613 */ {0x6026, 0xe2f1}, /* '怦' -> 24614 */ {0x6027, 0xd0d4}, /* '性' -> 24615 */ {0x6028, 0xd4b9}, /* '怨' -> 24616 */ {0x6029, 0xe2f5}, /* '怩' -> 24617 */ {0x602a, 0xb9d6}, /* '怪' -> 24618 */ {0x602b, 0xe2f6}, /* '怫' -> 24619 */ {0x602f, 0xc7d3}, /* '怯' -> 24623 */ {0x6035, 0xe2f0}, /* '怵' -> 24629 */ {0x603b, 0xd7dc}, /* '总' -> 24635 */ {0x603c, 0xeda1}, /* '怼' -> 24636 */ {0x603f, 0xe2f8}, /* '怿' -> 24639 */ {0x6041, 0xeda5}, /* '恁' -> 24641 */ {0x6042, 0xe2fe}, /* '恂' -> 24642 */ {0x6043, 0xcad1}, /* '恃' -> 24643 */ {0x604b, 0xc1b5}, /* '恋' -> 24651 */ {0x604d, 0xbbd0}, /* '恍' -> 24653 */ {0x6050, 0xbfd6}, /* '恐' -> 24656 */ {0x6052, 0xbae3}, /* '恒' -> 24658 */ {0x6055, 0xcba1}, /* '恕' -> 24661 */ {0x6059, 0xeda6}, /* '恙' -> 24665 */ {0x605a, 0xeda3}, /* '恚' -> 24666 */ {0x605d, 0xeda2}, /* '恝' -> 24669 */ {0x6062, 0xbbd6}, /* '恢' -> 24674 */ {0x6063, 0xeda7}, /* '恣' -> 24675 */ {0x6064, 0xd0f4}, /* '恤' -> 24676 */ {0x6067, 0xeda4}, /* '恧' -> 24679 */ {0x6068, 0xbade}, /* '恨' -> 24680 */ {0x6069, 0xb6f7}, /* '恩' -> 24681 */ {0x606a, 0xe3a1}, /* '恪' -> 24682 */ {0x606b, 0xb6b2}, /* '恫' -> 24683 */ {0x606c, 0xccf1}, /* '恬' -> 24684 */ {0x606d, 0xb9a7}, /* '恭' -> 24685 */ {0x606f, 0xcfa2}, /* '息' -> 24687 */ {0x6070, 0xc7a1}, /* '恰' -> 24688 */ {0x6073, 0xbfd2}, /* '恳' -> 24691 */ {0x6076, 0xb6f1}, /* '恶' -> 24694 */ {0x6078, 0xe2fa}, /* '恸' -> 24696 */ {0x6079, 0xe2fb}, /* '恹' -> 24697 */ {0x607a, 0xe2fd}, /* '恺' -> 24698 */ {0x607b, 0xe2fc}, /* '恻' -> 24699 */ {0x607c, 0xc4d5}, /* '恼' -> 24700 */ {0x607d, 0xe3a2}, /* '恽' -> 24701 */ {0x607f, 0xd3c1}, /* '恿' -> 24703 */ {0x6083, 0xe3a7}, /* '悃' -> 24707 */ {0x6084, 0xc7c4}, /* '悄' -> 24708 */ {0x6089, 0xcfa4}, /* '悉' -> 24713 */ {0x608c, 0xe3a9}, /* '悌' -> 24716 */ {0x608d, 0xbab7}, /* '悍' -> 24717 */ {0x6092, 0xe3a8}, /* '悒' -> 24722 */ {0x6094, 0xbbda}, /* '悔' -> 24724 */ {0x6096, 0xe3a3}, /* '悖' -> 24726 */ {0x609a, 0xe3a4}, /* '悚' -> 24730 */ {0x609b, 0xe3aa}, /* '悛' -> 24731 */ {0x609d, 0xe3a6}, /* '悝' -> 24733 */ {0x609f, 0xcef2}, /* '悟' -> 24735 */ {0x60a0, 0xd3c6}, /* '悠' -> 24736 */ {0x60a3, 0xbbbc}, /* '患' -> 24739 */ {0x60a6, 0xd4c3}, /* '悦' -> 24742 */ {0x60a8, 0xc4fa}, /* '您' -> 24744 */ {0x60ab, 0xeda8}, /* '悫' -> 24747 */ {0x60ac, 0xd0fc}, /* '悬' -> 24748 */ {0x60ad, 0xe3a5}, /* '悭' -> 24749 */ {0x60af, 0xc3f5}, /* '悯' -> 24751 */ {0x60b1, 0xe3ad}, /* '悱' -> 24753 */ {0x60b2, 0xb1af}, /* '悲' -> 24754 */ {0x60b4, 0xe3b2}, /* '悴' -> 24756 */ {0x60b8, 0xbcc2}, /* '悸' -> 24760 */ {0x60bb, 0xe3ac}, /* '悻' -> 24763 */ {0x60bc, 0xb5bf}, /* '悼' -> 24764 */ {0x60c5, 0xc7e9}, /* '情' -> 24773 */ {0x60c6, 0xe3b0}, /* '惆' -> 24774 */ {0x60ca, 0xbeaa}, /* '惊' -> 24778 */ {0x60cb, 0xcdef}, /* '惋' -> 24779 */ {0x60d1, 0xbbf3}, /* '惑' -> 24785 */ {0x60d5, 0xcce8}, /* '惕' -> 24789 */ {0x60d8, 0xe3af}, /* '惘' -> 24792 */ {0x60da, 0xe3b1}, /* '惚' -> 24794 */ {0x60dc, 0xcfa7}, /* '惜' -> 24796 */ {0x60dd, 0xe3ae}, /* '惝' -> 24797 */ {0x60df, 0xcea9}, /* '惟' -> 24799 */ {0x60e0, 0xbbdd}, /* '惠' -> 24800 */ {0x60e6, 0xb5eb}, /* '惦' -> 24806 */ {0x60e7, 0xbee5}, /* '惧' -> 24807 */ {0x60e8, 0xb2d2}, /* '惨' -> 24808 */ {0x60e9, 0xb3cd}, /* '惩' -> 24809 */ {0x60eb, 0xb1b9}, /* '惫' -> 24811 */ {0x60ec, 0xe3ab}, /* '惬' -> 24812 */ {0x60ed, 0xb2d1}, /* '惭' -> 24813 */ {0x60ee, 0xb5ac}, /* '惮' -> 24814 */ {0x60ef, 0xb9df}, /* '惯' -> 24815 */ {0x60f0, 0xb6e8}, /* '惰' -> 24816 */ {0x60f3, 0xcfeb}, /* '想' -> 24819 */ {0x60f4, 0xe3b7}, /* '惴' -> 24820 */ {0x60f6, 0xbbcc}, /* '惶' -> 24822 */ {0x60f9, 0xc8c7}, /* '惹' -> 24825 */ {0x60fa, 0xd0ca}, /* '惺' -> 24826 */ {0x6100, 0xe3b8}, /* '愀' -> 24832 */ {0x6101, 0xb3ee}, /* '愁' -> 24833 */ {0x6106, 0xeda9}, /* '愆' -> 24838 */ {0x6108, 0xd3fa}, /* '愈' -> 24840 */ {0x6109, 0xd3e4}, /* '愉' -> 24841 */ {0x610d, 0xedaa}, /* '愍' -> 24845 */ {0x610e, 0xe3b9}, /* '愎' -> 24846 */ {0x610f, 0xd2e2}, /* '意' -> 24847 */ {0x6115, 0xe3b5}, /* '愕' -> 24853 */ {0x611a, 0xd3de}, /* '愚' -> 24858 */ {0x611f, 0xb8d0}, /* '感' -> 24863 */ {0x6120, 0xe3b3}, /* '愠' -> 24864 */ {0x6123, 0xe3b6}, /* '愣' -> 24867 */ {0x6124, 0xb7df}, /* '愤' -> 24868 */ {0x6126, 0xe3b4}, /* '愦' -> 24870 */ {0x6127, 0xc0a2}, /* '愧' -> 24871 */ {0x612b, 0xe3ba}, /* '愫' -> 24875 */ {0x613f, 0xd4b8}, /* '愿' -> 24895 */ {0x6148, 0xb4c8}, /* '慈' -> 24904 */ {0x614a, 0xe3bb}, /* '慊' -> 24906 */ {0x614c, 0xbbc5}, /* '慌' -> 24908 */ {0x614e, 0xc9f7}, /* '慎' -> 24910 */ {0x6151, 0xc9e5}, /* '慑' -> 24913 */ {0x6155, 0xc4bd}, /* '慕' -> 24917 */ {0x615d, 0xedab}, /* '慝' -> 24925 */ {0x6162, 0xc2fd}, /* '慢' -> 24930 */ {0x6167, 0xbbdb}, /* '慧' -> 24935 */ {0x6168, 0xbfae}, /* '慨' -> 24936 */ {0x6170, 0xcebf}, /* '慰' -> 24944 */ {0x6175, 0xe3bc}, /* '慵' -> 24949 */ {0x6177, 0xbfb6}, /* '慷' -> 24951 */ {0x618b, 0xb1ef}, /* '憋' -> 24971 */ {0x618e, 0xd4f7}, /* '憎' -> 24974 */ {0x6194, 0xe3be}, /* '憔' -> 24980 */ {0x619d, 0xedad}, /* '憝' -> 24989 */ {0x61a7, 0xe3bf}, /* '憧' -> 24999 */ {0x61a8, 0xbaa9}, /* '憨' -> 25000 */ {0x61a9, 0xedac}, /* '憩' -> 25001 */ {0x61ac, 0xe3bd}, /* '憬' -> 25004 */ {0x61b7, 0xe3c0}, /* '憷' -> 25015 */ {0x61be, 0xbab6}, /* '憾' -> 25022 */ {0x61c2, 0xb6ae}, /* '懂' -> 25026 */ {0x61c8, 0xd0b8}, /* '懈' -> 25032 */ {0x61ca, 0xb0c3}, /* '懊' -> 25034 */ {0x61cb, 0xedae}, /* '懋' -> 25035 */ {0x61d1, 0xedaf}, /* '懑' -> 25041 */ {0x61d2, 0xc0c1}, /* '懒' -> 25042 */ {0x61d4, 0xe3c1}, /* '懔' -> 25044 */ {0x61e6, 0xc5b3}, /* '懦' -> 25062 */ {0x61f5, 0xe3c2}, /* '懵' -> 25077 */ {0x61ff, 0xdcb2}, /* '懿' -> 25087 */ {0x6206, 0xedb0}, /* '戆' -> 25094 */ {0x6208, 0xb8ea}, /* '戈' -> 25096 */ {0x620a, 0xceec}, /* '戊' -> 25098 */ {0x620b, 0xeaa7}, /* '戋' -> 25099 */ {0x620c, 0xd0e7}, /* '戌' -> 25100 */ {0x620d, 0xcaf9}, /* '戍' -> 25101 */ {0x620e, 0xc8d6}, /* '戎' -> 25102 */ {0x620f, 0xcfb7}, /* '戏' -> 25103 */ {0x6210, 0xb3c9}, /* '成' -> 25104 */ {0x6211, 0xced2}, /* '我' -> 25105 */ {0x6212, 0xbde4}, /* '戒' -> 25106 */ {0x6215, 0xe3de}, /* '戕' -> 25109 */ {0x6216, 0xbbf2}, /* '或' -> 25110 */ {0x6217, 0xeaa8}, /* '戗' -> 25111 */ {0x6218, 0xd5bd}, /* '战' -> 25112 */ {0x621a, 0xc6dd}, /* '戚' -> 25114 */ {0x621b, 0xeaa9}, /* '戛' -> 25115 */ {0x621f, 0xeaaa}, /* '戟' -> 25119 */ {0x6221, 0xeaac}, /* '戡' -> 25121 */ {0x6222, 0xeaab}, /* '戢' -> 25122 */ {0x6224, 0xeaae}, /* '戤' -> 25124 */ {0x6225, 0xeaad}, /* '戥' -> 25125 */ {0x622a, 0xbdd8}, /* '截' -> 25130 */ {0x622c, 0xeaaf}, /* '戬' -> 25132 */ {0x622e, 0xc2be}, /* '戮' -> 25134 */ {0x6233, 0xb4c1}, /* '戳' -> 25139 */ {0x6234, 0xb4f7}, /* '戴' -> 25140 */ {0x6237, 0xbba7}, /* '户' -> 25143 */ {0x623d, 0xece6}, /* '戽' -> 25149 */ {0x623e, 0xece5}, /* '戾' -> 25150 */ {0x623f, 0xb7bf}, /* '房' -> 25151 */ {0x6240, 0xcbf9}, /* '所' -> 25152 */ {0x6241, 0xb1e2}, /* '扁' -> 25153 */ {0x6243, 0xece7}, /* '扃' -> 25155 */ {0x6247, 0xc9c8}, /* '扇' -> 25159 */ {0x6248, 0xece8}, /* '扈' -> 25160 */ {0x6249, 0xece9}, /* '扉' -> 25161 */ {0x624b, 0xcad6}, /* '手' -> 25163 */ {0x624c, 0xded0}, /* '扌' -> 25164 */ {0x624d, 0xb2c5}, /* '才' -> 25165 */ {0x624e, 0xd4fa}, /* '扎' -> 25166 */ {0x6251, 0xc6cb}, /* '扑' -> 25169 */ {0x6252, 0xb0c7}, /* '扒' -> 25170 */ {0x6253, 0xb4f2}, /* '打' -> 25171 */ {0x6254, 0xc8d3}, /* '扔' -> 25172 */ {0x6258, 0xcdd0}, /* '托' -> 25176 */ {0x625b, 0xbfb8}, /* '扛' -> 25179 */ {0x6263, 0xbfdb}, /* '扣' -> 25187 */ {0x6266, 0xc7a4}, /* '扦' -> 25190 */ {0x6267, 0xd6b4}, /* '执' -> 25191 */ {0x6269, 0xc0a9}, /* '扩' -> 25193 */ {0x626a, 0xded1}, /* '扪' -> 25194 */ {0x626b, 0xc9a8}, /* '扫' -> 25195 */ {0x626c, 0xd1ef}, /* '扬' -> 25196 */ {0x626d, 0xc5a4}, /* '扭' -> 25197 */ {0x626e, 0xb0e7}, /* '扮' -> 25198 */ {0x626f, 0xb3b6}, /* '扯' -> 25199 */ {0x6270, 0xc8c5}, /* '扰' -> 25200 */ {0x6273, 0xb0e2}, /* '扳' -> 25203 */ {0x6276, 0xb7f6}, /* '扶' -> 25206 */ {0x6279, 0xc5fa}, /* '批' -> 25209 */ {0x627c, 0xb6f3}, /* '扼' -> 25212 */ {0x627e, 0xd5d2}, /* '找' -> 25214 */ {0x627f, 0xb3d0}, /* '承' -> 25215 */ {0x6280, 0xbcbc}, /* '技' -> 25216 */ {0x6284, 0xb3ad}, /* '抄' -> 25220 */ {0x6289, 0xbef1}, /* '抉' -> 25225 */ {0x628a, 0xb0d1}, /* '把' -> 25226 */ {0x6291, 0xd2d6}, /* '抑' -> 25233 */ {0x6292, 0xcae3}, /* '抒' -> 25234 */ {0x6293, 0xd7a5}, /* '抓' -> 25235 */ {0x6295, 0xcdb6}, /* '投' -> 25237 */ {0x6296, 0xb6b6}, /* '抖' -> 25238 */ {0x6297, 0xbfb9}, /* '抗' -> 25239 */ {0x6298, 0xd5db}, /* '折' -> 25240 */ {0x629a, 0xb8a7}, /* '抚' -> 25242 */ {0x629b, 0xc5d7}, /* '抛' -> 25243 */ {0x629f, 0xded2}, /* '抟' -> 25247 */ {0x62a0, 0xbfd9}, /* '抠' -> 25248 */ {0x62a1, 0xc2d5}, /* '抡' -> 25249 */ {0x62a2, 0xc7c0}, /* '抢' -> 25250 */ {0x62a4, 0xbba4}, /* '护' -> 25252 */ {0x62a5, 0xb1a8}, /* '报' -> 25253 */ {0x62a8, 0xc5ea}, /* '抨' -> 25256 */ {0x62ab, 0xc5fb}, /* '披' -> 25259 */ {0x62ac, 0xcca7}, /* '抬' -> 25260 */ {0x62b1, 0xb1a7}, /* '抱' -> 25265 */ {0x62b5, 0xb5d6}, /* '抵' -> 25269 */ {0x62b9, 0xc4a8}, /* '抹' -> 25273 */ {0x62bb, 0xded3}, /* '抻' -> 25275 */ {0x62bc, 0xd1ba}, /* '押' -> 25276 */ {0x62bd, 0xb3e9}, /* '抽' -> 25277 */ {0x62bf, 0xc3f2}, /* '抿' -> 25279 */ {0x62c2, 0xb7f7}, /* '拂' -> 25282 */ {0x62c4, 0xd6f4}, /* '拄' -> 25284 */ {0x62c5, 0xb5a3}, /* '担' -> 25285 */ {0x62c6, 0xb2f0}, /* '拆' -> 25286 */ {0x62c7, 0xc4b4}, /* '拇' -> 25287 */ {0x62c8, 0xc4e9}, /* '拈' -> 25288 */ {0x62c9, 0xc0ad}, /* '拉' -> 25289 */ {0x62ca, 0xded4}, /* '拊' -> 25290 */ {0x62cc, 0xb0e8}, /* '拌' -> 25292 */ {0x62cd, 0xc5c4}, /* '拍' -> 25293 */ {0x62ce, 0xc1e0}, /* '拎' -> 25294 */ {0x62d0, 0xb9d5}, /* '拐' -> 25296 */ {0x62d2, 0xbedc}, /* '拒' -> 25298 */ {0x62d3, 0xcdd8}, /* '拓' -> 25299 */ {0x62d4, 0xb0ce}, /* '拔' -> 25300 */ {0x62d6, 0xcdcf}, /* '拖' -> 25302 */ {0x62d7, 0xded6}, /* '拗' -> 25303 */ {0x62d8, 0xbed0}, /* '拘' -> 25304 */ {0x62d9, 0xd7be}, /* '拙' -> 25305 */ {0x62da, 0xded5}, /* '拚' -> 25306 */ {0x62db, 0xd5d0}, /* '招' -> 25307 */ {0x62dc, 0xb0dd}, /* '拜' -> 25308 */ {0x62df, 0xc4e2}, /* '拟' -> 25311 */ {0x62e2, 0xc2a3}, /* '拢' -> 25314 */ {0x62e3, 0xbcf0}, /* '拣' -> 25315 */ {0x62e5, 0xd3b5}, /* '拥' -> 25317 */ {0x62e6, 0xc0b9}, /* '拦' -> 25318 */ {0x62e7, 0xc5a1}, /* '拧' -> 25319 */ {0x62e8, 0xb2a6}, /* '拨' -> 25320 */ {0x62e9, 0xd4f1}, /* '择' -> 25321 */ {0x62ec, 0xc0a8}, /* '括' -> 25324 */ {0x62ed, 0xcac3}, /* '拭' -> 25325 */ {0x62ee, 0xded7}, /* '拮' -> 25326 */ {0x62ef, 0xd5fc}, /* '拯' -> 25327 */ {0x62f1, 0xb9b0}, /* '拱' -> 25329 */ {0x62f3, 0xc8ad}, /* '拳' -> 25331 */ {0x62f4, 0xcba9}, /* '拴' -> 25332 */ {0x62f6, 0xded9}, /* '拶' -> 25334 */ {0x62f7, 0xbfbd}, /* '拷' -> 25335 */ {0x62fc, 0xc6b4}, /* '拼' -> 25340 */ {0x62fd, 0xd7a7}, /* '拽' -> 25341 */ {0x62fe, 0xcab0}, /* '拾' -> 25342 */ {0x62ff, 0xc4c3}, /* '拿' -> 25343 */ {0x6301, 0xb3d6}, /* '持' -> 25345 */ {0x6302, 0xb9d2}, /* '挂' -> 25346 */ {0x6307, 0xd6b8}, /* '指' -> 25351 */ {0x6308, 0xeafc}, /* '挈' -> 25352 */ {0x6309, 0xb0b4}, /* '按' -> 25353 */ {0x630e, 0xbfe6}, /* '挎' -> 25358 */ {0x6311, 0xccf4}, /* '挑' -> 25361 */ {0x6316, 0xcdda}, /* '挖' -> 25366 */ {0x631a, 0xd6bf}, /* '挚' -> 25370 */ {0x631b, 0xc2ce}, /* '挛' -> 25371 */ {0x631d, 0xcece}, /* '挝' -> 25373 */ {0x631e, 0xcca2}, /* '挞' -> 25374 */ {0x631f, 0xd0ae}, /* '挟' -> 25375 */ {0x6320, 0xc4d3}, /* '挠' -> 25376 */ {0x6321, 0xb5b2}, /* '挡' -> 25377 */ {0x6322, 0xded8}, /* '挢' -> 25378 */ {0x6323, 0xd5f5}, /* '挣' -> 25379 */ {0x6324, 0xbcb7}, /* '挤' -> 25380 */ {0x6325, 0xbbd3}, /* '挥' -> 25381 */ {0x6328, 0xb0a4}, /* '挨' -> 25384 */ {0x632a, 0xc5b2}, /* '挪' -> 25386 */ {0x632b, 0xb4ec}, /* '挫' -> 25387 */ {0x632f, 0xd5f1}, /* '振' -> 25391 */ {0x6332, 0xeafd}, /* '挲' -> 25394 */ {0x6339, 0xdeda}, /* '挹' -> 25401 */ {0x633a, 0xcda6}, /* '挺' -> 25402 */ {0x633d, 0xcdec}, /* '挽' -> 25405 */ {0x6342, 0xcee6}, /* '捂' -> 25410 */ {0x6343, 0xdedc}, /* '捃' -> 25411 */ {0x6345, 0xcdb1}, /* '捅' -> 25413 */ {0x6346, 0xc0a6}, /* '捆' -> 25414 */ {0x6349, 0xd7bd}, /* '捉' -> 25417 */ {0x634b, 0xdedb}, /* '捋' -> 25419 */ {0x634c, 0xb0c6}, /* '捌' -> 25420 */ {0x634d, 0xbab4}, /* '捍' -> 25421 */ {0x634e, 0xc9d3}, /* '捎' -> 25422 */ {0x634f, 0xc4f3}, /* '捏' -> 25423 */ {0x6350, 0xbee8}, /* '捐' -> 25424 */ {0x6355, 0xb2b6}, /* '捕' -> 25429 */ {0x635e, 0xc0cc}, /* '捞' -> 25438 */ {0x635f, 0xcbf0}, /* '损' -> 25439 */ {0x6361, 0xbcf1}, /* '捡' -> 25441 */ {0x6362, 0xbbbb}, /* '换' -> 25442 */ {0x6363, 0xb5b7}, /* '捣' -> 25443 */ {0x6367, 0xc5f5}, /* '捧' -> 25447 */ {0x6369, 0xdee6}, /* '捩' -> 25449 */ {0x636d, 0xdee3}, /* '捭' -> 25453 */ {0x636e, 0xbedd}, /* '据' -> 25454 */ {0x6371, 0xdedf}, /* '捱' -> 25457 */ {0x6376, 0xb4b7}, /* '捶' -> 25462 */ {0x6377, 0xbddd}, /* '捷' -> 25463 */ {0x637a, 0xdee0}, /* '捺' -> 25466 */ {0x637b, 0xc4ed}, /* '捻' -> 25467 */ {0x6380, 0xcfc6}, /* '掀' -> 25472 */ {0x6382, 0xb5e0}, /* '掂' -> 25474 */ {0x6387, 0xb6de}, /* '掇' -> 25479 */ {0x6388, 0xcada}, /* '授' -> 25480 */ {0x6389, 0xb5f4}, /* '掉' -> 25481 */ {0x638a, 0xdee5}, /* '掊' -> 25482 */ {0x638c, 0xd5c6}, /* '掌' -> 25484 */ {0x638e, 0xdee1}, /* '掎' -> 25486 */ {0x638f, 0xcccd}, /* '掏' -> 25487 */ {0x6390, 0xc6fe}, /* '掐' -> 25488 */ {0x6392, 0xc5c5}, /* '排' -> 25490 */ {0x6396, 0xd2b4}, /* '掖' -> 25494 */ {0x6398, 0xbef2}, /* '掘' -> 25496 */ {0x63a0, 0xc2d3}, /* '掠' -> 25504 */ {0x63a2, 0xccbd}, /* '探' -> 25506 */ {0x63a3, 0xb3b8}, /* '掣' -> 25507 */ {0x63a5, 0xbdd3}, /* '接' -> 25509 */ {0x63a7, 0xbfd8}, /* '控' -> 25511 */ {0x63a8, 0xcdc6}, /* '推' -> 25512 */ {0x63a9, 0xd1da}, /* '掩' -> 25513 */ {0x63aa, 0xb4eb}, /* '措' -> 25514 */ {0x63ac, 0xdee4}, /* '掬' -> 25516 */ {0x63ad, 0xdedd}, /* '掭' -> 25517 */ {0x63ae, 0xdee7}, /* '掮' -> 25518 */ {0x63b0, 0xeafe}, /* '掰' -> 25520 */ {0x63b3, 0xc2b0}, /* '掳' -> 25523 */ {0x63b4, 0xdee2}, /* '掴' -> 25524 */ {0x63b7, 0xd6c0}, /* '掷' -> 25527 */ {0x63b8, 0xb5a7}, /* '掸' -> 25528 */ {0x63ba, 0xb2f4}, /* '掺' -> 25530 */ {0x63bc, 0xdee8}, /* '掼' -> 25532 */ {0x63be, 0xdef2}, /* '掾' -> 25534 */ {0x63c4, 0xdeed}, /* '揄' -> 25540 */ {0x63c6, 0xdef1}, /* '揆' -> 25542 */ {0x63c9, 0xc8e0}, /* '揉' -> 25545 */ {0x63cd, 0xd7e1}, /* '揍' -> 25549 */ {0x63ce, 0xdeef}, /* '揎' -> 25550 */ {0x63cf, 0xc3e8}, /* '描' -> 25551 */ {0x63d0, 0xcce1}, /* '提' -> 25552 */ {0x63d2, 0xb2e5}, /* '插' -> 25554 */ {0x63d6, 0xd2be}, /* '揖' -> 25558 */ {0x63de, 0xdeee}, /* '揞' -> 25566 */ {0x63e0, 0xdeeb}, /* '揠' -> 25568 */ {0x63e1, 0xced5}, /* '握' -> 25569 */ {0x63e3, 0xb4a7}, /* '揣' -> 25571 */ {0x63e9, 0xbfab}, /* '揩' -> 25577 */ {0x63ea, 0xbebe}, /* '揪' -> 25578 */ {0x63ed, 0xbdd2}, /* '揭' -> 25581 */ {0x63f2, 0xdee9}, /* '揲' -> 25586 */ {0x63f4, 0xd4ae}, /* '援' -> 25588 */ {0x63f6, 0xdede}, /* '揶' -> 25590 */ {0x63f8, 0xdeea}, /* '揸' -> 25592 */ {0x63fd, 0xc0bf}, /* '揽' -> 25597 */ {0x63ff, 0xdeec}, /* '揿' -> 25599 */ {0x6400, 0xb2f3}, /* '搀' -> 25600 */ {0x6401, 0xb8e9}, /* '搁' -> 25601 */ {0x6402, 0xc2a7}, /* '搂' -> 25602 */ {0x6405, 0xbdc1}, /* '搅' -> 25605 */ {0x640b, 0xdef5}, /* '搋' -> 25611 */ {0x640c, 0xdef8}, /* '搌' -> 25612 */ {0x640f, 0xb2ab}, /* '搏' -> 25615 */ {0x6410, 0xb4a4}, /* '搐' -> 25616 */ {0x6413, 0xb4ea}, /* '搓' -> 25619 */ {0x6414, 0xc9a6}, /* '搔' -> 25620 */ {0x641b, 0xdef6}, /* '搛' -> 25627 */ {0x641c, 0xcbd1}, /* '搜' -> 25628 */ {0x641e, 0xb8e3}, /* '搞' -> 25630 */ {0x6420, 0xdef7}, /* '搠' -> 25632 */ {0x6421, 0xdefa}, /* '搡' -> 25633 */ {0x6426, 0xdef9}, /* '搦' -> 25638 */ {0x642a, 0xccc2}, /* '搪' -> 25642 */ {0x642c, 0xb0e1}, /* '搬' -> 25644 */ {0x642d, 0xb4ee}, /* '搭' -> 25645 */ {0x6434, 0xe5ba}, /* '搴' -> 25652 */ {0x643a, 0xd0af}, /* '携' -> 25658 */ {0x643d, 0xb2eb}, /* '搽' -> 25661 */ {0x643f, 0xeba1}, /* '搿' -> 25663 */ {0x6441, 0xdef4}, /* '摁' -> 25665 */ {0x6444, 0xc9e3}, /* '摄' -> 25668 */ {0x6445, 0xdef3}, /* '摅' -> 25669 */ {0x6446, 0xb0da}, /* '摆' -> 25670 */ {0x6447, 0xd2a1}, /* '摇' -> 25671 */ {0x6448, 0xb1f7}, /* '摈' -> 25672 */ {0x644a, 0xccaf}, /* '摊' -> 25674 */ {0x6452, 0xdef0}, /* '摒' -> 25682 */ {0x6454, 0xcba4}, /* '摔' -> 25684 */ {0x6458, 0xd5aa}, /* '摘' -> 25688 */ {0x645e, 0xdefb}, /* '摞' -> 25694 */ {0x6467, 0xb4dd}, /* '摧' -> 25703 */ {0x6469, 0xc4a6}, /* '摩' -> 25705 */ {0x646d, 0xdefd}, /* '摭' -> 25709 */ {0x6478, 0xc3fe}, /* '摸' -> 25720 */ {0x6479, 0xc4a1}, /* '摹' -> 25721 */ {0x647a, 0xdfa1}, /* '摺' -> 25722 */ {0x6482, 0xc1cc}, /* '撂' -> 25730 */ {0x6484, 0xdefc}, /* '撄' -> 25732 */ {0x6485, 0xbeef}, /* '撅' -> 25733 */ {0x6487, 0xc6b2}, /* '撇' -> 25735 */ {0x6491, 0xb3c5}, /* '撑' -> 25745 */ {0x6492, 0xc8f6}, /* '撒' -> 25746 */ {0x6495, 0xcbba}, /* '撕' -> 25749 */ {0x6496, 0xdefe}, /* '撖' -> 25750 */ {0x6499, 0xdfa4}, /* '撙' -> 25753 */ {0x649e, 0xd7b2}, /* '撞' -> 25758 */ {0x64a4, 0xb3b7}, /* '撤' -> 25764 */ {0x64a9, 0xc1c3}, /* '撩' -> 25769 */ {0x64ac, 0xc7cb}, /* '撬' -> 25772 */ {0x64ad, 0xb2a5}, /* '播' -> 25773 */ {0x64ae, 0xb4e9}, /* '撮' -> 25774 */ {0x64b0, 0xd7ab}, /* '撰' -> 25776 */ {0x64b5, 0xc4ec}, /* '撵' -> 25781 */ {0x64b7, 0xdfa2}, /* '撷' -> 25783 */ {0x64b8, 0xdfa3}, /* '撸' -> 25784 */ {0x64ba, 0xdfa5}, /* '撺' -> 25786 */ {0x64bc, 0xbab3}, /* '撼' -> 25788 */ {0x64c0, 0xdfa6}, /* '擀' -> 25792 */ {0x64c2, 0xc0de}, /* '擂' -> 25794 */ {0x64c5, 0xc9c3}, /* '擅' -> 25797 */ {0x64cd, 0xb2d9}, /* '操' -> 25805 */ {0x64ce, 0xc7e6}, /* '擎' -> 25806 */ {0x64d0, 0xdfa7}, /* '擐' -> 25808 */ {0x64d2, 0xc7dc}, /* '擒' -> 25810 */ {0x64d7, 0xdfa8}, /* '擗' -> 25815 */ {0x64d8, 0xeba2}, /* '擘' -> 25816 */ {0x64de, 0xcbd3}, /* '擞' -> 25822 */ {0x64e2, 0xdfaa}, /* '擢' -> 25826 */ {0x64e4, 0xdfa9}, /* '擤' -> 25828 */ {0x64e6, 0xb2c1}, /* '擦' -> 25830 */ {0x6500, 0xc5ca}, /* '攀' -> 25856 */ {0x6509, 0xdfab}, /* '攉' -> 25865 */ {0x6512, 0xd4dc}, /* '攒' -> 25874 */ {0x6518, 0xc8c1}, /* '攘' -> 25880 */ {0x6525, 0xdfac}, /* '攥' -> 25893 */ {0x652b, 0xbef0}, /* '攫' -> 25899 */ {0x652e, 0xdfad}, /* '攮' -> 25902 */ {0x652f, 0xd6a7}, /* '支' -> 25903 */ {0x6534, 0xeab7}, /* '攴' -> 25908 */ {0x6535, 0xebb6}, /* '攵' -> 25909 */ {0x6536, 0xcad5}, /* '收' -> 25910 */ {0x6538, 0xd8fc}, /* '攸' -> 25912 */ {0x6539, 0xb8c4}, /* '改' -> 25913 */ {0x653b, 0xb9a5}, /* '攻' -> 25915 */ {0x653e, 0xb7c5}, /* '放' -> 25918 */ {0x653f, 0xd5fe}, /* '政' -> 25919 */ {0x6545, 0xb9ca}, /* '故' -> 25925 */ {0x6548, 0xd0a7}, /* '效' -> 25928 */ {0x6549, 0xf4cd}, /* '敉' -> 25929 */ {0x654c, 0xb5d0}, /* '敌' -> 25932 */ {0x654f, 0xc3f4}, /* '敏' -> 25935 */ {0x6551, 0xbec8}, /* '救' -> 25937 */ {0x6555, 0xebb7}, /* '敕' -> 25941 */ {0x6556, 0xb0bd}, /* '敖' -> 25942 */ {0x6559, 0xbdcc}, /* '教' -> 25945 */ {0x655b, 0xc1b2}, /* '敛' -> 25947 */ {0x655d, 0xb1d6}, /* '敝' -> 25949 */ {0x655e, 0xb3a8}, /* '敞' -> 25950 */ {0x6562, 0xb8d2}, /* '敢' -> 25954 */ {0x6563, 0xc9a2}, /* '散' -> 25955 */ {0x6566, 0xb6d8}, /* '敦' -> 25958 */ {0x656b, 0xebb8}, /* '敫' -> 25963 */ {0x656c, 0xbeb4}, /* '敬' -> 25964 */ {0x6570, 0xcafd}, /* '数' -> 25968 */ {0x6572, 0xc7c3}, /* '敲' -> 25970 */ {0x6574, 0xd5fb}, /* '整' -> 25972 */ {0x6577, 0xb7f3}, /* '敷' -> 25975 */ {0x6587, 0xcec4}, /* '文' -> 25991 */ {0x658b, 0xd5ab}, /* '斋' -> 25995 */ {0x658c, 0xb1f3}, /* '斌' -> 25996 */ {0x6590, 0xecb3}, /* '斐' -> 26000 */ {0x6591, 0xb0df}, /* '斑' -> 26001 */ {0x6593, 0xecb5}, /* '斓' -> 26003 */ {0x6597, 0xb6b7}, /* '斗' -> 26007 */ {0x6599, 0xc1cf}, /* '料' -> 26009 */ {0x659b, 0xf5fa}, /* '斛' -> 26011 */ {0x659c, 0xd0b1}, /* '斜' -> 26012 */ {0x659f, 0xd5e5}, /* '斟' -> 26015 */ {0x65a1, 0xced3}, /* '斡' -> 26017 */ {0x65a4, 0xbdef}, /* '斤' -> 26020 */ {0x65a5, 0xb3e2}, /* '斥' -> 26021 */ {0x65a7, 0xb8ab}, /* '斧' -> 26023 */ {0x65a9, 0xd5b6}, /* '斩' -> 26025 */ {0x65ab, 0xedbd}, /* '斫' -> 26027 */ {0x65ad, 0xb6cf}, /* '断' -> 26029 */ {0x65af, 0xcbb9}, /* '斯' -> 26031 */ {0x65b0, 0xd0c2}, /* '新' -> 26032 */ {0x65b9, 0xb7bd}, /* '方' -> 26041 */ {0x65bc, 0xecb6}, /* '於' -> 26044 */ {0x65bd, 0xcaa9}, /* '施' -> 26045 */ {0x65c1, 0xc5d4}, /* '旁' -> 26049 */ {0x65c3, 0xecb9}, /* '旃' -> 26051 */ {0x65c4, 0xecb8}, /* '旄' -> 26052 */ {0x65c5, 0xc2c3}, /* '旅' -> 26053 */ {0x65c6, 0xecb7}, /* '旆' -> 26054 */ {0x65cb, 0xd0fd}, /* '旋' -> 26059 */ {0x65cc, 0xecba}, /* '旌' -> 26060 */ {0x65ce, 0xecbb}, /* '旎' -> 26062 */ {0x65cf, 0xd7e5}, /* '族' -> 26063 */ {0x65d2, 0xecbc}, /* '旒' -> 26066 */ {0x65d6, 0xecbd}, /* '旖' -> 26070 */ {0x65d7, 0xc6ec}, /* '旗' -> 26071 */ {0x65e0, 0xcede}, /* '无' -> 26080 */ {0x65e2, 0xbcc8}, /* '既' -> 26082 */ {0x65e5, 0xc8d5}, /* '日' -> 26085 */ {0x65e6, 0xb5a9}, /* '旦' -> 26086 */ {0x65e7, 0xbec9}, /* '旧' -> 26087 */ {0x65e8, 0xd6bc}, /* '旨' -> 26088 */ {0x65e9, 0xd4e7}, /* '早' -> 26089 */ {0x65ec, 0xd1ae}, /* '旬' -> 26092 */ {0x65ed, 0xd0f1}, /* '旭' -> 26093 */ {0x65ee, 0xeab8}, /* '旮' -> 26094 */ {0x65ef, 0xeab9}, /* '旯' -> 26095 */ {0x65f0, 0xeaba}, /* '旰' -> 26096 */ {0x65f1, 0xbab5}, /* '旱' -> 26097 */ {0x65f6, 0xcab1}, /* '时' -> 26102 */ {0x65f7, 0xbff5}, /* '旷' -> 26103 */ {0x65fa, 0xcdfa}, /* '旺' -> 26106 */ {0x6600, 0xeac0}, /* '昀' -> 26112 */ {0x6602, 0xb0ba}, /* '昂' -> 26114 */ {0x6603, 0xeabe}, /* '昃' -> 26115 */ {0x6606, 0xc0a5}, /* '昆' -> 26118 */ {0x660a, 0xeabb}, /* '昊' -> 26122 */ {0x660c, 0xb2fd}, /* '昌' -> 26124 */ {0x660e, 0xc3f7}, /* '明' -> 26126 */ {0x660f, 0xbbe8}, /* '昏' -> 26127 */ {0x6613, 0xd2d7}, /* '易' -> 26131 */ {0x6614, 0xcef4}, /* '昔' -> 26132 */ {0x6615, 0xeabf}, /* '昕' -> 26133 */ {0x6619, 0xeabc}, /* '昙' -> 26137 */ {0x661d, 0xeac3}, /* '昝' -> 26141 */ {0x661f, 0xd0c7}, /* '星' -> 26143 */ {0x6620, 0xd3b3}, /* '映' -> 26144 */ {0x6625, 0xb4ba}, /* '春' -> 26149 */ {0x6627, 0xc3c1}, /* '昧' -> 26151 */ {0x6628, 0xd7f2}, /* '昨' -> 26152 */ {0x662d, 0xd5d1}, /* '昭' -> 26157 */ {0x662f, 0xcac7}, /* '是' -> 26159 */ {0x6631, 0xeac5}, /* '昱' -> 26161 */ {0x6634, 0xeac4}, /* '昴' -> 26164 */ {0x6635, 0xeac7}, /* '昵' -> 26165 */ {0x6636, 0xeac6}, /* '昶' -> 26166 */ {0x663c, 0xd6e7}, /* '昼' -> 26172 */ {0x663e, 0xcfd4}, /* '显' -> 26174 */ {0x6641, 0xeacb}, /* '晁' -> 26177 */ {0x6643, 0xbbce}, /* '晃' -> 26179 */ {0x664b, 0xbdfa}, /* '晋' -> 26187 */ {0x664c, 0xc9ce}, /* '晌' -> 26188 */ {0x664f, 0xeacc}, /* '晏' -> 26191 */ {0x6652, 0xc9b9}, /* '晒' -> 26194 */ {0x6653, 0xcffe}, /* '晓' -> 26195 */ {0x6654, 0xeaca}, /* '晔' -> 26196 */ {0x6655, 0xd4ce}, /* '晕' -> 26197 */ {0x6656, 0xeacd}, /* '晖' -> 26198 */ {0x6657, 0xeacf}, /* '晗' -> 26199 */ {0x665a, 0xcded}, /* '晚' -> 26202 */ {0x665f, 0xeac9}, /* '晟' -> 26207 */ {0x6661, 0xeace}, /* '晡' -> 26209 */ {0x6664, 0xceee}, /* '晤' -> 26212 */ {0x6666, 0xbbde}, /* '晦' -> 26214 */ {0x6668, 0xb3bf}, /* '晨' -> 26216 */ {0x666e, 0xc6d5}, /* '普' -> 26222 */ {0x666f, 0xbeb0}, /* '景' -> 26223 */ {0x6670, 0xcefa}, /* '晰' -> 26224 */ {0x6674, 0xc7e7}, /* '晴' -> 26228 */ {0x6676, 0xbea7}, /* '晶' -> 26230 */ {0x6677, 0xead0}, /* '晷' -> 26231 */ {0x667a, 0xd6c7}, /* '智' -> 26234 */ {0x667e, 0xc1c0}, /* '晾' -> 26238 */ {0x6682, 0xd4dd}, /* '暂' -> 26242 */ {0x6684, 0xead1}, /* '暄' -> 26244 */ {0x6687, 0xcfbe}, /* '暇' -> 26247 */ {0x668c, 0xead2}, /* '暌' -> 26252 */ {0x6691, 0xcaee}, /* '暑' -> 26257 */ {0x6696, 0xc5af}, /* '暖' -> 26262 */ {0x6697, 0xb0b5}, /* '暗' -> 26263 */ {0x669d, 0xead4}, /* '暝' -> 26269 */ {0x66a7, 0xead3}, /* '暧' -> 26279 */ {0x66a8, 0xf4df}, /* '暨' -> 26280 */ {0x66ae, 0xc4ba}, /* '暮' -> 26286 */ {0x66b4, 0xb1a9}, /* '暴' -> 26292 */ {0x66b9, 0xe5df}, /* '暹' -> 26297 */ {0x66be, 0xead5}, /* '暾' -> 26302 */ {0x66d9, 0xcaef}, /* '曙' -> 26329 */ {0x66db, 0xead6}, /* '曛' -> 26331 */ {0x66dc, 0xead7}, /* '曜' -> 26332 */ {0x66dd, 0xc6d8}, /* '曝' -> 26333 */ {0x66e6, 0xead8}, /* '曦' -> 26342 */ {0x66e9, 0xead9}, /* '曩' -> 26345 */ {0x66f0, 0xd4bb}, /* '曰' -> 26352 */ {0x66f2, 0xc7fa}, /* '曲' -> 26354 */ {0x66f3, 0xd2b7}, /* '曳' -> 26355 */ {0x66f4, 0xb8fc}, /* '更' -> 26356 */ {0x66f7, 0xeac2}, /* '曷' -> 26359 */ {0x66f9, 0xb2dc}, /* '曹' -> 26361 */ {0x66fc, 0xc2fc}, /* '曼' -> 26364 */ {0x66fe, 0xd4f8}, /* '曾' -> 26366 */ {0x66ff, 0xcce6}, /* '替' -> 26367 */ {0x6700, 0xd7ee}, /* '最' -> 26368 */ {0x6708, 0xd4c2}, /* '月' -> 26376 */ {0x6709, 0xd3d0}, /* '有' -> 26377 */ {0x670a, 0xebc3}, /* '朊' -> 26378 */ {0x670b, 0xc5f3}, /* '朋' -> 26379 */ {0x670d, 0xb7fe}, /* '服' -> 26381 */ {0x6710, 0xebd4}, /* '朐' -> 26384 */ {0x6714, 0xcbb7}, /* '朔' -> 26388 */ {0x6715, 0xebde}, /* '朕' -> 26389 */ {0x6717, 0xc0ca}, /* '朗' -> 26391 */ {0x671b, 0xcdfb}, /* '望' -> 26395 */ {0x671d, 0xb3af}, /* '朝' -> 26397 */ {0x671f, 0xc6da}, /* '期' -> 26399 */ {0x6726, 0xebfc}, /* '朦' -> 26406 */ {0x6728, 0xc4be}, /* '木' -> 26408 */ {0x672a, 0xceb4}, /* '未' -> 26410 */ {0x672b, 0xc4a9}, /* '末' -> 26411 */ {0x672c, 0xb1be}, /* '本' -> 26412 */ {0x672d, 0xd4fd}, /* '札' -> 26413 */ {0x672f, 0xcaf5}, /* '术' -> 26415 */ {0x6731, 0xd6ec}, /* '朱' -> 26417 */ {0x6734, 0xc6d3}, /* '朴' -> 26420 */ {0x6735, 0xb6e4}, /* '朵' -> 26421 */ {0x673a, 0xbbfa}, /* '机' -> 26426 */ {0x673d, 0xd0e0}, /* '朽' -> 26429 */ {0x6740, 0xc9b1}, /* '杀' -> 26432 */ {0x6742, 0xd4d3}, /* '杂' -> 26434 */ {0x6743, 0xc8a8}, /* '权' -> 26435 */ {0x6746, 0xb8cb}, /* '杆' -> 26438 */ {0x6748, 0xe8be}, /* '杈' -> 26440 */ {0x6749, 0xc9bc}, /* '杉' -> 26441 */ {0x674c, 0xe8bb}, /* '杌' -> 26444 */ {0x674e, 0xc0ee}, /* '李' -> 26446 */ {0x674f, 0xd0d3}, /* '杏' -> 26447 */ {0x6750, 0xb2c4}, /* '材' -> 26448 */ {0x6751, 0xb4e5}, /* '村' -> 26449 */ {0x6753, 0xe8bc}, /* '杓' -> 26451 */ {0x6756, 0xd5c8}, /* '杖' -> 26454 */ {0x675c, 0xb6c5}, /* '杜' -> 26460 */ {0x675e, 0xe8bd}, /* '杞' -> 26462 */ {0x675f, 0xcaf8}, /* '束' -> 26463 */ {0x6760, 0xb8dc}, /* '杠' -> 26464 */ {0x6761, 0xccf5}, /* '条' -> 26465 */ {0x6765, 0xc0b4}, /* '来' -> 26469 */ {0x6768, 0xd1ee}, /* '杨' -> 26472 */ {0x6769, 0xe8bf}, /* '杩' -> 26473 */ {0x676a, 0xe8c2}, /* '杪' -> 26474 */ {0x676d, 0xbabc}, /* '杭' -> 26477 */ {0x676f, 0xb1ad}, /* '杯' -> 26479 */ {0x6770, 0xbddc}, /* '杰' -> 26480 */ {0x6772, 0xeabd}, /* '杲' -> 26482 */ {0x6773, 0xe8c3}, /* '杳' -> 26483 */ {0x6775, 0xe8c6}, /* '杵' -> 26485 */ {0x6777, 0xe8cb}, /* '杷' -> 26487 */ {0x677c, 0xe8cc}, /* '杼' -> 26492 */ {0x677e, 0xcbc9}, /* '松' -> 26494 */ {0x677f, 0xb0e5}, /* '板' -> 26495 */ {0x6781, 0xbcab}, /* '极' -> 26497 */ {0x6784, 0xb9b9}, /* '构' -> 26500 */ {0x6787, 0xe8c1}, /* '枇' -> 26503 */ {0x6789, 0xcdf7}, /* '枉' -> 26505 */ {0x678b, 0xe8ca}, /* '枋' -> 26507 */ {0x6790, 0xcef6}, /* '析' -> 26512 */ {0x6795, 0xd5ed}, /* '枕' -> 26517 */ {0x6797, 0xc1d6}, /* '林' -> 26519 */ {0x6798, 0xe8c4}, /* '枘' -> 26520 */ {0x679a, 0xc3b6}, /* '枚' -> 26522 */ {0x679c, 0xb9fb}, /* '果' -> 26524 */ {0x679d, 0xd6a6}, /* '枝' -> 26525 */ {0x679e, 0xe8c8}, /* '枞' -> 26526 */ {0x67a2, 0xcae0}, /* '枢' -> 26530 */ {0x67a3, 0xd4e6}, /* '枣' -> 26531 */ {0x67a5, 0xe8c0}, /* '枥' -> 26533 */ {0x67a7, 0xe8c5}, /* '枧' -> 26535 */ {0x67a8, 0xe8c7}, /* '枨' -> 26536 */ {0x67aa, 0xc7b9}, /* '枪' -> 26538 */ {0x67ab, 0xb7e3}, /* '枫' -> 26539 */ {0x67ad, 0xe8c9}, /* '枭' -> 26541 */ {0x67af, 0xbfdd}, /* '枯' -> 26543 */ {0x67b0, 0xe8d2}, /* '枰' -> 26544 */ {0x67b3, 0xe8d7}, /* '枳' -> 26547 */ {0x67b5, 0xe8d5}, /* '枵' -> 26549 */ {0x67b6, 0xbcdc}, /* '架' -> 26550 */ {0x67b7, 0xbccf}, /* '枷' -> 26551 */ {0x67b8, 0xe8db}, /* '枸' -> 26552 */ {0x67c1, 0xe8de}, /* '柁' -> 26561 */ {0x67c3, 0xe8da}, /* '柃' -> 26563 */ {0x67c4, 0xb1fa}, /* '柄' -> 26564 */ {0x67cf, 0xb0d8}, /* '柏' -> 26575 */ {0x67d0, 0xc4b3}, /* '某' -> 26576 */ {0x67d1, 0xb8cc}, /* '柑' -> 26577 */ {0x67d2, 0xc6e2}, /* '柒' -> 26578 */ {0x67d3, 0xc8be}, /* '染' -> 26579 */ {0x67d4, 0xc8e1}, /* '柔' -> 26580 */ {0x67d8, 0xe8cf}, /* '柘' -> 26584 */ {0x67d9, 0xe8d4}, /* '柙' -> 26585 */ {0x67da, 0xe8d6}, /* '柚' -> 26586 */ {0x67dc, 0xb9f1}, /* '柜' -> 26588 */ {0x67dd, 0xe8d8}, /* '柝' -> 26589 */ {0x67de, 0xd7f5}, /* '柞' -> 26590 */ {0x67e0, 0xc4fb}, /* '柠' -> 26592 */ {0x67e2, 0xe8dc}, /* '柢' -> 26594 */ {0x67e5, 0xb2e9}, /* '查' -> 26597 */ {0x67e9, 0xe8d1}, /* '柩' -> 26601 */ {0x67ec, 0xbced}, /* '柬' -> 26604 */ {0x67ef, 0xbfc2}, /* '柯' -> 26607 */ {0x67f0, 0xe8cd}, /* '柰' -> 26608 */ {0x67f1, 0xd6f9}, /* '柱' -> 26609 */ {0x67f3, 0xc1f8}, /* '柳' -> 26611 */ {0x67f4, 0xb2f1}, /* '柴' -> 26612 */ {0x67fd, 0xe8df}, /* '柽' -> 26621 */ {0x67ff, 0xcac1}, /* '柿' -> 26623 */ {0x6800, 0xe8d9}, /* '栀' -> 26624 */ {0x6805, 0xd5a4}, /* '栅' -> 26629 */ {0x6807, 0xb1ea}, /* '标' -> 26631 */ {0x6808, 0xd5bb}, /* '栈' -> 26632 */ {0x6809, 0xe8ce}, /* '栉' -> 26633 */ {0x680a, 0xe8d0}, /* '栊' -> 26634 */ {0x680b, 0xb6b0}, /* '栋' -> 26635 */ {0x680c, 0xe8d3}, /* '栌' -> 26636 */ {0x680e, 0xe8dd}, /* '栎' -> 26638 */ {0x680f, 0xc0b8}, /* '栏' -> 26639 */ {0x6811, 0xcaf7}, /* '树' -> 26641 */ {0x6813, 0xcba8}, /* '栓' -> 26643 */ {0x6816, 0xc6dc}, /* '栖' -> 26646 */ {0x6817, 0xc0f5}, /* '栗' -> 26647 */ {0x681d, 0xe8e9}, /* '栝' -> 26653 */ {0x6821, 0xd0a3}, /* '校' -> 26657 */ {0x6829, 0xe8f2}, /* '栩' -> 26665 */ {0x682a, 0xd6ea}, /* '株' -> 26666 */ {0x6832, 0xe8e0}, /* '栲' -> 26674 */ {0x6833, 0xe8e1}, /* '栳' -> 26675 */ {0x6837, 0xd1f9}, /* '样' -> 26679 */ {0x6838, 0xbacb}, /* '核' -> 26680 */ {0x6839, 0xb8f9}, /* '根' -> 26681 */ {0x683c, 0xb8f1}, /* '格' -> 26684 */ {0x683d, 0xd4d4}, /* '栽' -> 26685 */ {0x683e, 0xe8ef}, /* '栾' -> 26686 */ {0x6840, 0xe8ee}, /* '桀' -> 26688 */ {0x6841, 0xe8ec}, /* '桁' -> 26689 */ {0x6842, 0xb9f0}, /* '桂' -> 26690 */ {0x6843, 0xccd2}, /* '桃' -> 26691 */ {0x6844, 0xe8e6}, /* '桄' -> 26692 */ {0x6845, 0xcea6}, /* '桅' -> 26693 */ {0x6846, 0xbff2}, /* '框' -> 26694 */ {0x6848, 0xb0b8}, /* '案' -> 26696 */ {0x6849, 0xe8f1}, /* '桉' -> 26697 */ {0x684a, 0xe8f0}, /* '桊' -> 26698 */ {0x684c, 0xd7c0}, /* '桌' -> 26700 */ {0x684e, 0xe8e4}, /* '桎' -> 26702 */ {0x6850, 0xcda9}, /* '桐' -> 26704 */ {0x6851, 0xc9a3}, /* '桑' -> 26705 */ {0x6853, 0xbbb8}, /* '桓' -> 26707 */ {0x6854, 0xbddb}, /* '桔' -> 26708 */ {0x6855, 0xe8ea}, /* '桕' -> 26709 */ {0x6860, 0xe8e2}, /* '桠' -> 26720 */ {0x6861, 0xe8e3}, /* '桡' -> 26721 */ {0x6862, 0xe8e5}, /* '桢' -> 26722 */ {0x6863, 0xb5b5}, /* '档' -> 26723 */ {0x6864, 0xe8e7}, /* '桤' -> 26724 */ {0x6865, 0xc7c5}, /* '桥' -> 26725 */ {0x6866, 0xe8eb}, /* '桦' -> 26726 */ {0x6867, 0xe8ed}, /* '桧' -> 26727 */ {0x6868, 0xbdb0}, /* '桨' -> 26728 */ {0x6869, 0xd7ae}, /* '桩' -> 26729 */ {0x686b, 0xe8f8}, /* '桫' -> 26731 */ {0x6874, 0xe8f5}, /* '桴' -> 26740 */ {0x6876, 0xcdb0}, /* '桶' -> 26742 */ {0x6877, 0xe8f6}, /* '桷' -> 26743 */ {0x6881, 0xc1ba}, /* '梁' -> 26753 */ {0x6883, 0xe8e8}, /* '梃' -> 26755 */ {0x6885, 0xc3b7}, /* '梅' -> 26757 */ {0x6886, 0xb0f0}, /* '梆' -> 26758 */ {0x688f, 0xe8f4}, /* '梏' -> 26767 */ {0x6893, 0xe8f7}, /* '梓' -> 26771 */ {0x6897, 0xb9a3}, /* '梗' -> 26775 */ {0x68a2, 0xc9d2}, /* '梢' -> 26786 */ {0x68a6, 0xc3ce}, /* '梦' -> 26790 */ {0x68a7, 0xcee0}, /* '梧' -> 26791 */ {0x68a8, 0xc0e6}, /* '梨' -> 26792 */ {0x68ad, 0xcbf3}, /* '梭' -> 26797 */ {0x68af, 0xccdd}, /* '梯' -> 26799 */ {0x68b0, 0xd0b5}, /* '械' -> 26800 */ {0x68b3, 0xcae1}, /* '梳' -> 26803 */ {0x68b5, 0xe8f3}, /* '梵' -> 26805 */ {0x68c0, 0xbcec}, /* '检' -> 26816 */ {0x68c2, 0xe8f9}, /* '棂' -> 26818 */ {0x68c9, 0xc3de}, /* '棉' -> 26825 */ {0x68cb, 0xc6e5}, /* '棋' -> 26827 */ {0x68cd, 0xb9f7}, /* '棍' -> 26829 */ {0x68d2, 0xb0f4}, /* '棒' -> 26834 */ {0x68d5, 0xd7d8}, /* '棕' -> 26837 */ {0x68d8, 0xbcac}, /* '棘' -> 26840 */ {0x68da, 0xc5ef}, /* '棚' -> 26842 */ {0x68e0, 0xccc4}, /* '棠' -> 26848 */ {0x68e3, 0xe9a6}, /* '棣' -> 26851 */ {0x68ee, 0xc9ad}, /* '森' -> 26862 */ {0x68f0, 0xe9a2}, /* '棰' -> 26864 */ {0x68f1, 0xc0e2}, /* '棱' -> 26865 */ {0x68f5, 0xbfc3}, /* '棵' -> 26869 */ {0x68f9, 0xe8fe}, /* '棹' -> 26873 */ {0x68fa, 0xb9d7}, /* '棺' -> 26874 */ {0x68fc, 0xe8fb}, /* '棼' -> 26876 */ {0x6901, 0xe9a4}, /* '椁' -> 26881 */ {0x6905, 0xd2ce}, /* '椅' -> 26885 */ {0x690b, 0xe9a3}, /* '椋' -> 26891 */ {0x690d, 0xd6b2}, /* '植' -> 26893 */ {0x690e, 0xd7b5}, /* '椎' -> 26894 */ {0x6910, 0xe9a7}, /* '椐' -> 26896 */ {0x6912, 0xbdb7}, /* '椒' -> 26898 */ {0x691f, 0xe8fc}, /* '椟' -> 26911 */ {0x6920, 0xe8fd}, /* '椠' -> 26912 */ {0x6924, 0xe9a1}, /* '椤' -> 26916 */ {0x692d, 0xcdd6}, /* '椭' -> 26925 */ {0x6930, 0xd2ac}, /* '椰' -> 26928 */ {0x6934, 0xe9b2}, /* '椴' -> 26932 */ {0x6939, 0xe9a9}, /* '椹' -> 26937 */ {0x693d, 0xb4aa}, /* '椽' -> 26941 */ {0x693f, 0xb4bb}, /* '椿' -> 26943 */ {0x6942, 0xe9ab}, /* '楂' -> 26946 */ {0x6954, 0xd0a8}, /* '楔' -> 26964 */ {0x6957, 0xe9a5}, /* '楗' -> 26967 */ {0x695a, 0xb3fe}, /* '楚' -> 26970 */ {0x695d, 0xe9ac}, /* '楝' -> 26973 */ {0x695e, 0xc0e3}, /* '楞' -> 26974 */ {0x6960, 0xe9aa}, /* '楠' -> 26976 */ {0x6963, 0xe9b9}, /* '楣' -> 26979 */ {0x6966, 0xe9b8}, /* '楦' -> 26982 */ {0x696b, 0xe9ae}, /* '楫' -> 26987 */ {0x696e, 0xe8fa}, /* '楮' -> 26990 */ {0x6971, 0xe9a8}, /* '楱' -> 26993 */ {0x6977, 0xbfac}, /* '楷' -> 26999 */ {0x6978, 0xe9b1}, /* '楸' -> 27000 */ {0x6979, 0xe9ba}, /* '楹' -> 27001 */ {0x697c, 0xc2a5}, /* '楼' -> 27004 */ {0x6980, 0xe9af}, /* '榀' -> 27008 */ {0x6982, 0xb8c5}, /* '概' -> 27010 */ {0x6984, 0xe9ad}, /* '榄' -> 27012 */ {0x6986, 0xd3dc}, /* '榆' -> 27014 */ {0x6987, 0xe9b4}, /* '榇' -> 27015 */ {0x6988, 0xe9b5}, /* '榈' -> 27016 */ {0x6989, 0xe9b7}, /* '榉' -> 27017 */ {0x698d, 0xe9c7}, /* '榍' -> 27021 */ {0x6994, 0xc0c6}, /* '榔' -> 27028 */ {0x6995, 0xe9c5}, /* '榕' -> 27029 */ {0x6998, 0xe9b0}, /* '榘' -> 27032 */ {0x699b, 0xe9bb}, /* '榛' -> 27035 */ {0x699c, 0xb0f1}, /* '榜' -> 27036 */ {0x69a7, 0xe9bc}, /* '榧' -> 27047 */ {0x69a8, 0xd5a5}, /* '榨' -> 27048 */ {0x69ab, 0xe9be}, /* '榫' -> 27051 */ {0x69ad, 0xe9bf}, /* '榭' -> 27053 */ {0x69b1, 0xe9c1}, /* '榱' -> 27057 */ {0x69b4, 0xc1f1}, /* '榴' -> 27060 */ {0x69b7, 0xc8b6}, /* '榷' -> 27063 */ {0x69bb, 0xe9bd}, /* '榻' -> 27067 */ {0x69c1, 0xe9c2}, /* '槁' -> 27073 */ {0x69ca, 0xe9c3}, /* '槊' -> 27082 */ {0x69cc, 0xe9b3}, /* '槌' -> 27084 */ {0x69ce, 0xe9b6}, /* '槎' -> 27086 */ {0x69d0, 0xbbb1}, /* '槐' -> 27088 */ {0x69d4, 0xe9c0}, /* '槔' -> 27092 */ {0x69db, 0xbcf7}, /* '槛' -> 27099 */ {0x69df, 0xe9c4}, /* '槟' -> 27103 */ {0x69e0, 0xe9c6}, /* '槠' -> 27104 */ {0x69ed, 0xe9ca}, /* '槭' -> 27117 */ {0x69f2, 0xe9ce}, /* '槲' -> 27122 */ {0x69fd, 0xb2db}, /* '槽' -> 27133 */ {0x69ff, 0xe9c8}, /* '槿' -> 27135 */ {0x6a0a, 0xb7ae}, /* '樊' -> 27146 */ {0x6a17, 0xe9cb}, /* '樗' -> 27159 */ {0x6a18, 0xe9cc}, /* '樘' -> 27160 */ {0x6a1f, 0xd5c1}, /* '樟' -> 27167 */ {0x6a21, 0xc4a3}, /* '模' -> 27169 */ {0x6a28, 0xe9d8}, /* '樨' -> 27176 */ {0x6a2a, 0xbae1}, /* '横' -> 27178 */ {0x6a2f, 0xe9c9}, /* '樯' -> 27183 */ {0x6a31, 0xd3a3}, /* '樱' -> 27185 */ {0x6a35, 0xe9d4}, /* '樵' -> 27189 */ {0x6a3d, 0xe9d7}, /* '樽' -> 27197 */ {0x6a3e, 0xe9d0}, /* '樾' -> 27198 */ {0x6a44, 0xe9cf}, /* '橄' -> 27204 */ {0x6a47, 0xc7c1}, /* '橇' -> 27207 */ {0x6a50, 0xe9d2}, /* '橐' -> 27216 */ {0x6a58, 0xe9d9}, /* '橘' -> 27224 */ {0x6a59, 0xb3c8}, /* '橙' -> 27225 */ {0x6a5b, 0xe9d3}, /* '橛' -> 27227 */ {0x6a61, 0xcff0}, /* '橡' -> 27233 */ {0x6a65, 0xe9cd}, /* '橥' -> 27237 */ {0x6a71, 0xb3f7}, /* '橱' -> 27249 */ {0x6a79, 0xe9d6}, /* '橹' -> 27257 */ {0x6a7c, 0xe9da}, /* '橼' -> 27260 */ {0x6a80, 0xccb4}, /* '檀' -> 27264 */ {0x6a84, 0xcfad}, /* '檄' -> 27268 */ {0x6a8e, 0xe9d5}, /* '檎' -> 27278 */ {0x6a90, 0xe9dc}, /* '檐' -> 27280 */ {0x6a91, 0xe9db}, /* '檑' -> 27281 */ {0x6a97, 0xe9de}, /* '檗' -> 27287 */ {0x6aa0, 0xe9d1}, /* '檠' -> 27296 */ {0x6aa9, 0xe9dd}, /* '檩' -> 27305 */ {0x6aab, 0xe9df}, /* '檫' -> 27307 */ {0x6aac, 0xc3ca}, /* '檬' -> 27308 */ {0x6b20, 0xc7b7}, /* '欠' -> 27424 */ {0x6b21, 0xb4ce}, /* '次' -> 27425 */ {0x6b22, 0xbbb6}, /* '欢' -> 27426 */ {0x6b23, 0xd0c0}, /* '欣' -> 27427 */ {0x6b24, 0xeca3}, /* '欤' -> 27428 */ {0x6b27, 0xc5b7}, /* '欧' -> 27431 */ {0x6b32, 0xd3fb}, /* '欲' -> 27442 */ {0x6b37, 0xeca4}, /* '欷' -> 27447 */ {0x6b39, 0xeca5}, /* '欹' -> 27449 */ {0x6b3a, 0xc6db}, /* '欺' -> 27450 */ {0x6b3e, 0xbfee}, /* '款' -> 27454 */ {0x6b43, 0xeca6}, /* '歃' -> 27459 */ {0x6b46, 0xeca7}, /* '歆' -> 27462 */ {0x6b47, 0xd0aa}, /* '歇' -> 27463 */ {0x6b49, 0xc7b8}, /* '歉' -> 27465 */ {0x6b4c, 0xb8e8}, /* '歌' -> 27468 */ {0x6b59, 0xeca8}, /* '歙' -> 27481 */ {0x6b62, 0xd6b9}, /* '止' -> 27490 */ {0x6b63, 0xd5fd}, /* '正' -> 27491 */ {0x6b64, 0xb4cb}, /* '此' -> 27492 */ {0x6b65, 0xb2bd}, /* '步' -> 27493 */ {0x6b66, 0xcee4}, /* '武' -> 27494 */ {0x6b67, 0xc6e7}, /* '歧' -> 27495 */ {0x6b6a, 0xcde1}, /* '歪' -> 27498 */ {0x6b79, 0xb4f5}, /* '歹' -> 27513 */ {0x6b7b, 0xcbc0}, /* '死' -> 27515 */ {0x6b7c, 0xbcdf}, /* '歼' -> 27516 */ {0x6b81, 0xe9e2}, /* '殁' -> 27521 */ {0x6b82, 0xe9e3}, /* '殂' -> 27522 */ {0x6b83, 0xd1ea}, /* '殃' -> 27523 */ {0x6b84, 0xe9e5}, /* '殄' -> 27524 */ {0x6b86, 0xb4f9}, /* '殆' -> 27526 */ {0x6b87, 0xe9e4}, /* '殇' -> 27527 */ {0x6b89, 0xd1b3}, /* '殉' -> 27529 */ {0x6b8a, 0xcae2}, /* '殊' -> 27530 */ {0x6b8b, 0xb2d0}, /* '残' -> 27531 */ {0x6b8d, 0xe9e8}, /* '殍' -> 27533 */ {0x6b92, 0xe9e6}, /* '殒' -> 27538 */ {0x6b93, 0xe9e7}, /* '殓' -> 27539 */ {0x6b96, 0xd6b3}, /* '殖' -> 27542 */ {0x6b9a, 0xe9e9}, /* '殚' -> 27546 */ {0x6b9b, 0xe9ea}, /* '殛' -> 27547 */ {0x6ba1, 0xe9eb}, /* '殡' -> 27553 */ {0x6baa, 0xe9ec}, /* '殪' -> 27562 */ {0x6bb3, 0xecaf}, /* '殳' -> 27571 */ {0x6bb4, 0xc5b9}, /* '殴' -> 27572 */ {0x6bb5, 0xb6ce}, /* '段' -> 27573 */ {0x6bb7, 0xd2f3}, /* '殷' -> 27575 */ {0x6bbf, 0xb5ee}, /* '殿' -> 27583 */ {0x6bc1, 0xbbd9}, /* '毁' -> 27585 */ {0x6bc2, 0xecb1}, /* '毂' -> 27586 */ {0x6bc5, 0xd2e3}, /* '毅' -> 27589 */ {0x6bcb, 0xcee3}, /* '毋' -> 27595 */ {0x6bcd, 0xc4b8}, /* '母' -> 27597 */ {0x6bcf, 0xc3bf}, /* '每' -> 27599 */ {0x6bd2, 0xb6be}, /* '毒' -> 27602 */ {0x6bd3, 0xd8b9}, /* '毓' -> 27603 */ {0x6bd4, 0xb1c8}, /* '比' -> 27604 */ {0x6bd5, 0xb1cf}, /* '毕' -> 27605 */ {0x6bd6, 0xb1d1}, /* '毖' -> 27606 */ {0x6bd7, 0xc5fe}, /* '毗' -> 27607 */ {0x6bd9, 0xb1d0}, /* '毙' -> 27609 */ {0x6bdb, 0xc3ab}, /* '毛' -> 27611 */ {0x6be1, 0xd5b1}, /* '毡' -> 27617 */ {0x6bea, 0xeba4}, /* '毪' -> 27626 */ {0x6beb, 0xbac1}, /* '毫' -> 27627 */ {0x6bef, 0xccba}, /* '毯' -> 27631 */ {0x6bf3, 0xeba5}, /* '毳' -> 27635 */ {0x6bf5, 0xeba7}, /* '毵' -> 27637 */ {0x6bf9, 0xeba8}, /* '毹' -> 27641 */ {0x6bfd, 0xeba6}, /* '毽' -> 27645 */ {0x6c05, 0xeba9}, /* '氅' -> 27653 */ {0x6c06, 0xebab}, /* '氆' -> 27654 */ {0x6c07, 0xebaa}, /* '氇' -> 27655 */ {0x6c0d, 0xebac}, /* '氍' -> 27661 */ {0x6c0f, 0xcacf}, /* '氏' -> 27663 */ {0x6c10, 0xd8b5}, /* '氐' -> 27664 */ {0x6c11, 0xc3f1}, /* '民' -> 27665 */ {0x6c13, 0xc3a5}, /* '氓' -> 27667 */ {0x6c14, 0xc6f8}, /* '气' -> 27668 */ {0x6c15, 0xebad}, /* '氕' -> 27669 */ {0x6c16, 0xc4ca}, /* '氖' -> 27670 */ {0x6c18, 0xebae}, /* '氘' -> 27672 */ {0x6c19, 0xebaf}, /* '氙' -> 27673 */ {0x6c1a, 0xebb0}, /* '氚' -> 27674 */ {0x6c1b, 0xb7d5}, /* '氛' -> 27675 */ {0x6c1f, 0xb7fa}, /* '氟' -> 27679 */ {0x6c21, 0xebb1}, /* '氡' -> 27681 */ {0x6c22, 0xc7e2}, /* '氢' -> 27682 */ {0x6c24, 0xebb3}, /* '氤' -> 27684 */ {0x6c26, 0xbaa4}, /* '氦' -> 27686 */ {0x6c27, 0xd1f5}, /* '氧' -> 27687 */ {0x6c28, 0xb0b1}, /* '氨' -> 27688 */ {0x6c29, 0xebb2}, /* '氩' -> 27689 */ {0x6c2a, 0xebb4}, /* '氪' -> 27690 */ {0x6c2e, 0xb5aa}, /* '氮' -> 27694 */ {0x6c2f, 0xc2c8}, /* '氯' -> 27695 */ {0x6c30, 0xc7e8}, /* '氰' -> 27696 */ {0x6c32, 0xebb5}, /* '氲' -> 27698 */ {0x6c34, 0xcbae}, /* '水' -> 27700 */ {0x6c35, 0xe3df}, /* '氵' -> 27701 */ {0x6c38, 0xd3c0}, /* '永' -> 27704 */ {0x6c3d, 0xd9db}, /* '氽' -> 27709 */ {0x6c40, 0xcda1}, /* '汀' -> 27712 */ {0x6c41, 0xd6ad}, /* '汁' -> 27713 */ {0x6c42, 0xc7f3}, /* '求' -> 27714 */ {0x6c46, 0xd9e0}, /* '汆' -> 27718 */ {0x6c47, 0xbbe3}, /* '汇' -> 27719 */ {0x6c49, 0xbaba}, /* '汉' -> 27721 */ {0x6c4a, 0xe3e2}, /* '汊' -> 27722 */ {0x6c50, 0xcfab}, /* '汐' -> 27728 */ {0x6c54, 0xe3e0}, /* '汔' -> 27732 */ {0x6c55, 0xc9c7}, /* '汕' -> 27733 */ {0x6c57, 0xbab9}, /* '汗' -> 27735 */ {0x6c5b, 0xd1b4}, /* '汛' -> 27739 */ {0x6c5c, 0xe3e1}, /* '汜' -> 27740 */ {0x6c5d, 0xc8ea}, /* '汝' -> 27741 */ {0x6c5e, 0xb9af}, /* '汞' -> 27742 */ {0x6c5f, 0xbdad}, /* '江' -> 27743 */ {0x6c60, 0xb3d8}, /* '池' -> 27744 */ {0x6c61, 0xcedb}, /* '污' -> 27745 */ {0x6c64, 0xccc0}, /* '汤' -> 27748 */ {0x6c68, 0xe3e8}, /* '汨' -> 27752 */ {0x6c69, 0xe3e9}, /* '汩' -> 27753 */ {0x6c6a, 0xcdf4}, /* '汪' -> 27754 */ {0x6c70, 0xccad}, /* '汰' -> 27760 */ {0x6c72, 0xbcb3}, /* '汲' -> 27762 */ {0x6c74, 0xe3ea}, /* '汴' -> 27764 */ {0x6c76, 0xe3eb}, /* '汶' -> 27766 */ {0x6c79, 0xd0da}, /* '汹' -> 27769 */ {0x6c7d, 0xc6fb}, /* '汽' -> 27773 */ {0x6c7e, 0xb7da}, /* '汾' -> 27774 */ {0x6c81, 0xc7df}, /* '沁' -> 27777 */ {0x6c82, 0xd2ca}, /* '沂' -> 27778 */ {0x6c83, 0xced6}, /* '沃' -> 27779 */ {0x6c85, 0xe3e4}, /* '沅' -> 27781 */ {0x6c86, 0xe3ec}, /* '沆' -> 27782 */ {0x6c88, 0xc9f2}, /* '沈' -> 27784 */ {0x6c89, 0xb3c1}, /* '沉' -> 27785 */ {0x6c8c, 0xe3e7}, /* '沌' -> 27788 */ {0x6c8f, 0xc6e3}, /* '沏' -> 27791 */ {0x6c90, 0xe3e5}, /* '沐' -> 27792 */ {0x6c93, 0xedb3}, /* '沓' -> 27795 */ {0x6c94, 0xe3e6}, /* '沔' -> 27796 */ {0x6c99, 0xc9b3}, /* '沙' -> 27801 */ {0x6c9b, 0xc5e6}, /* '沛' -> 27803 */ {0x6c9f, 0xb9b5}, /* '沟' -> 27807 */ {0x6ca1, 0xc3bb}, /* '没' -> 27809 */ {0x6ca3, 0xe3e3}, /* '沣' -> 27811 */ {0x6ca4, 0xc5bd}, /* '沤' -> 27812 */ {0x6ca5, 0xc1a4}, /* '沥' -> 27813 */ {0x6ca6, 0xc2d9}, /* '沦' -> 27814 */ {0x6ca7, 0xb2d7}, /* '沧' -> 27815 */ {0x6ca9, 0xe3ed}, /* '沩' -> 27817 */ {0x6caa, 0xbba6}, /* '沪' -> 27818 */ {0x6cab, 0xc4ad}, /* '沫' -> 27819 */ {0x6cad, 0xe3f0}, /* '沭' -> 27821 */ {0x6cae, 0xbeda}, /* '沮' -> 27822 */ {0x6cb1, 0xe3fb}, /* '沱' -> 27825 */ {0x6cb2, 0xe3f5}, /* '沲' -> 27826 */ {0x6cb3, 0xbad3}, /* '河' -> 27827 */ {0x6cb8, 0xb7d0}, /* '沸' -> 27832 */ {0x6cb9, 0xd3cd}, /* '油' -> 27833 */ {0x6cbb, 0xd6ce}, /* '治' -> 27835 */ {0x6cbc, 0xd5d3}, /* '沼' -> 27836 */ {0x6cbd, 0xb9c1}, /* '沽' -> 27837 */ {0x6cbe, 0xd5b4}, /* '沾' -> 27838 */ {0x6cbf, 0xd1d8}, /* '沿' -> 27839 */ {0x6cc4, 0xd0b9}, /* '泄' -> 27844 */ {0x6cc5, 0xc7f6}, /* '泅' -> 27845 */ {0x6cc9, 0xc8aa}, /* '泉' -> 27849 */ {0x6cca, 0xb2b4}, /* '泊' -> 27850 */ {0x6ccc, 0xc3da}, /* '泌' -> 27852 */ {0x6cd0, 0xe3ee}, /* '泐' -> 27856 */ {0x6cd3, 0xe3fc}, /* '泓' -> 27859 */ {0x6cd4, 0xe3ef}, /* '泔' -> 27860 */ {0x6cd5, 0xb7a8}, /* '法' -> 27861 */ {0x6cd6, 0xe3f7}, /* '泖' -> 27862 */ {0x6cd7, 0xe3f4}, /* '泗' -> 27863 */ {0x6cdb, 0xb7ba}, /* '泛' -> 27867 */ {0x6cde, 0xc5a2}, /* '泞' -> 27870 */ {0x6ce0, 0xe3f6}, /* '泠' -> 27872 */ {0x6ce1, 0xc5dd}, /* '泡' -> 27873 */ {0x6ce2, 0xb2a8}, /* '波' -> 27874 */ {0x6ce3, 0xc6fc}, /* '泣' -> 27875 */ {0x6ce5, 0xc4e0}, /* '泥' -> 27877 */ {0x6ce8, 0xd7a2}, /* '注' -> 27880 */ {0x6cea, 0xc0e1}, /* '泪' -> 27882 */ {0x6ceb, 0xe3f9}, /* '泫' -> 27883 */ {0x6cee, 0xe3fa}, /* '泮' -> 27886 */ {0x6cef, 0xe3fd}, /* '泯' -> 27887 */ {0x6cf0, 0xcca9}, /* '泰' -> 27888 */ {0x6cf1, 0xe3f3}, /* '泱' -> 27889 */ {0x6cf3, 0xd3be}, /* '泳' -> 27891 */ {0x6cf5, 0xb1c3}, /* '泵' -> 27893 */ {0x6cf6, 0xedb4}, /* '泶' -> 27894 */ {0x6cf7, 0xe3f1}, /* '泷' -> 27895 */ {0x6cf8, 0xe3f2}, /* '泸' -> 27896 */ {0x6cfa, 0xe3f8}, /* '泺' -> 27898 */ {0x6cfb, 0xd0ba}, /* '泻' -> 27899 */ {0x6cfc, 0xc6c3}, /* '泼' -> 27900 */ {0x6cfd, 0xd4f3}, /* '泽' -> 27901 */ {0x6cfe, 0xe3fe}, /* '泾' -> 27902 */ {0x6d01, 0xbde0}, /* '洁' -> 27905 */ {0x6d04, 0xe4a7}, /* '洄' -> 27908 */ {0x6d07, 0xe4a6}, /* '洇' -> 27911 */ {0x6d0b, 0xd1f3}, /* '洋' -> 27915 */ {0x6d0c, 0xe4a3}, /* '洌' -> 27916 */ {0x6d0e, 0xe4a9}, /* '洎' -> 27918 */ {0x6d12, 0xc8f7}, /* '洒' -> 27922 */ {0x6d17, 0xcfb4}, /* '洗' -> 27927 */ {0x6d19, 0xe4a8}, /* '洙' -> 27929 */ {0x6d1a, 0xe4ae}, /* '洚' -> 27930 */ {0x6d1b, 0xc2e5}, /* '洛' -> 27931 */ {0x6d1e, 0xb6b4}, /* '洞' -> 27934 */ {0x6d25, 0xbdf2}, /* '津' -> 27941 */ {0x6d27, 0xe4a2}, /* '洧' -> 27943 */ {0x6d2a, 0xbae9}, /* '洪' -> 27946 */ {0x6d2b, 0xe4aa}, /* '洫' -> 27947 */ {0x6d2e, 0xe4ac}, /* '洮' -> 27950 */ {0x6d31, 0xb6fd}, /* '洱' -> 27953 */ {0x6d32, 0xd6de}, /* '洲' -> 27954 */ {0x6d33, 0xe4b2}, /* '洳' -> 27955 */ {0x6d35, 0xe4ad}, /* '洵' -> 27957 */ {0x6d39, 0xe4a1}, /* '洹' -> 27961 */ {0x6d3b, 0xbbee}, /* '活' -> 27963 */ {0x6d3c, 0xcddd}, /* '洼' -> 27964 */ {0x6d3d, 0xc7a2}, /* '洽' -> 27965 */ {0x6d3e, 0xc5c9}, /* '派' -> 27966 */ {0x6d41, 0xc1f7}, /* '流' -> 27969 */ {0x6d43, 0xe4a4}, /* '浃' -> 27971 */ {0x6d45, 0xc7b3}, /* '浅' -> 27973 */ {0x6d46, 0xbdac}, /* '浆' -> 27974 */ {0x6d47, 0xbdbd}, /* '浇' -> 27975 */ {0x6d48, 0xe4a5}, /* '浈' -> 27976 */ {0x6d4a, 0xd7c7}, /* '浊' -> 27978 */ {0x6d4b, 0xb2e2}, /* '测' -> 27979 */ {0x6d4d, 0xe4ab}, /* '浍' -> 27981 */ {0x6d4e, 0xbcc3}, /* '济' -> 27982 */ {0x6d4f, 0xe4af}, /* '浏' -> 27983 */ {0x6d51, 0xbbeb}, /* '浑' -> 27985 */ {0x6d52, 0xe4b0}, /* '浒' -> 27986 */ {0x6d53, 0xc5a8}, /* '浓' -> 27987 */ {0x6d54, 0xe4b1}, /* '浔' -> 27988 */ {0x6d59, 0xd5e3}, /* '浙' -> 27993 */ {0x6d5a, 0xbfa3}, /* '浚' -> 27994 */ {0x6d5c, 0xe4ba}, /* '浜' -> 27996 */ {0x6d5e, 0xe4b7}, /* '浞' -> 27998 */ {0x6d60, 0xe4bb}, /* '浠' -> 28000 */ {0x6d63, 0xe4bd}, /* '浣' -> 28003 */ {0x6d66, 0xc6d6}, /* '浦' -> 28006 */ {0x6d69, 0xbac6}, /* '浩' -> 28009 */ {0x6d6a, 0xc0cb}, /* '浪' -> 28010 */ {0x6d6e, 0xb8a1}, /* '浮' -> 28014 */ {0x6d6f, 0xe4b4}, /* '浯' -> 28015 */ {0x6d74, 0xd4a1}, /* '浴' -> 28020 */ {0x6d77, 0xbaa3}, /* '海' -> 28023 */ {0x6d78, 0xbdfe}, /* '浸' -> 28024 */ {0x6d7c, 0xe4bc}, /* '浼' -> 28028 */ {0x6d82, 0xcdbf}, /* '涂' -> 28034 */ {0x6d85, 0xc4f9}, /* '涅' -> 28037 */ {0x6d88, 0xcffb}, /* '消' -> 28040 */ {0x6d89, 0xc9e6}, /* '涉' -> 28041 */ {0x6d8c, 0xd3bf}, /* '涌' -> 28044 */ {0x6d8e, 0xcfd1}, /* '涎' -> 28046 */ {0x6d91, 0xe4b3}, /* '涑' -> 28049 */ {0x6d93, 0xe4b8}, /* '涓' -> 28051 */ {0x6d94, 0xe4b9}, /* '涔' -> 28052 */ {0x6d95, 0xcce9}, /* '涕' -> 28053 */ {0x6d9b, 0xccce}, /* '涛' -> 28059 */ {0x6d9d, 0xc0d4}, /* '涝' -> 28061 */ {0x6d9e, 0xe4b5}, /* '涞' -> 28062 */ {0x6d9f, 0xc1b0}, /* '涟' -> 28063 */ {0x6da0, 0xe4b6}, /* '涠' -> 28064 */ {0x6da1, 0xced0}, /* '涡' -> 28065 */ {0x6da3, 0xbbc1}, /* '涣' -> 28067 */ {0x6da4, 0xb5d3}, /* '涤' -> 28068 */ {0x6da6, 0xc8f3}, /* '润' -> 28070 */ {0x6da7, 0xbda7}, /* '涧' -> 28071 */ {0x6da8, 0xd5c7}, /* '涨' -> 28072 */ {0x6da9, 0xc9ac}, /* '涩' -> 28073 */ {0x6daa, 0xb8a2}, /* '涪' -> 28074 */ {0x6dab, 0xe4ca}, /* '涫' -> 28075 */ {0x6dae, 0xe4cc}, /* '涮' -> 28078 */ {0x6daf, 0xd1c4}, /* '涯' -> 28079 */ {0x6db2, 0xd2ba}, /* '液' -> 28082 */ {0x6db5, 0xbaad}, /* '涵' -> 28085 */ {0x6db8, 0xbad4}, /* '涸' -> 28088 */ {0x6dbf, 0xe4c3}, /* '涿' -> 28095 */ {0x6dc0, 0xb5ed}, /* '淀' -> 28096 */ {0x6dc4, 0xd7cd}, /* '淄' -> 28100 */ {0x6dc5, 0xe4c0}, /* '淅' -> 28101 */ {0x6dc6, 0xcffd}, /* '淆' -> 28102 */ {0x6dc7, 0xe4bf}, /* '淇' -> 28103 */ {0x6dcb, 0xc1dc}, /* '淋' -> 28107 */ {0x6dcc, 0xccca}, /* '淌' -> 28108 */ {0x6dd1, 0xcae7}, /* '淑' -> 28113 */ {0x6dd6, 0xc4d7}, /* '淖' -> 28118 */ {0x6dd8, 0xccd4}, /* '淘' -> 28120 */ {0x6dd9, 0xe4c8}, /* '淙' -> 28121 */ {0x6ddd, 0xe4c7}, /* '淝' -> 28125 */ {0x6dde, 0xe4c1}, /* '淞' -> 28126 */ {0x6de0, 0xe4c4}, /* '淠' -> 28128 */ {0x6de1, 0xb5ad}, /* '淡' -> 28129 */ {0x6de4, 0xd3d9}, /* '淤' -> 28132 */ {0x6de6, 0xe4c6}, /* '淦' -> 28134 */ {0x6deb, 0xd2f9}, /* '淫' -> 28139 */ {0x6dec, 0xb4e3}, /* '淬' -> 28140 */ {0x6dee, 0xbbb4}, /* '淮' -> 28142 */ {0x6df1, 0xc9ee}, /* '深' -> 28145 */ {0x6df3, 0xb4be}, /* '淳' -> 28147 */ {0x6df7, 0xbbec}, /* '混' -> 28151 */ {0x6df9, 0xd1cd}, /* '淹' -> 28153 */ {0x6dfb, 0xcced}, /* '添' -> 28155 */ {0x6dfc, 0xedb5}, /* '淼' -> 28156 */ {0x6e05, 0xc7e5}, /* '清' -> 28165 */ {0x6e0a, 0xd4a8}, /* '渊' -> 28170 */ {0x6e0c, 0xe4cb}, /* '渌' -> 28172 */ {0x6e0d, 0xd7d5}, /* '渍' -> 28173 */ {0x6e0e, 0xe4c2}, /* '渎' -> 28174 */ {0x6e10, 0xbda5}, /* '渐' -> 28176 */ {0x6e11, 0xe4c5}, /* '渑' -> 28177 */ {0x6e14, 0xd3e6}, /* '渔' -> 28180 */ {0x6e16, 0xe4c9}, /* '渖' -> 28182 */ {0x6e17, 0xc9f8}, /* '渗' -> 28183 */ {0x6e1a, 0xe4be}, /* '渚' -> 28186 */ {0x6e1d, 0xd3e5}, /* '渝' -> 28189 */ {0x6e20, 0xc7fe}, /* '渠' -> 28192 */ {0x6e21, 0xb6c9}, /* '渡' -> 28193 */ {0x6e23, 0xd4fc}, /* '渣' -> 28195 */ {0x6e24, 0xb2b3}, /* '渤' -> 28196 */ {0x6e25, 0xe4d7}, /* '渥' -> 28197 */ {0x6e29, 0xcec2}, /* '温' -> 28201 */ {0x6e2b, 0xe4cd}, /* '渫' -> 28203 */ {0x6e2d, 0xcebc}, /* '渭' -> 28205 */ {0x6e2f, 0xb8db}, /* '港' -> 28207 */ {0x6e32, 0xe4d6}, /* '渲' -> 28210 */ {0x6e34, 0xbfca}, /* '渴' -> 28212 */ {0x6e38, 0xd3ce}, /* '游' -> 28216 */ {0x6e3a, 0xc3ec}, /* '渺' -> 28218 */ {0x6e43, 0xc5c8}, /* '湃' -> 28227 */ {0x6e44, 0xe4d8}, /* '湄' -> 28228 */ {0x6e4d, 0xcdc4}, /* '湍' -> 28237 */ {0x6e4e, 0xe4cf}, /* '湎' -> 28238 */ {0x6e53, 0xe4d4}, /* '湓' -> 28243 */ {0x6e54, 0xe4d5}, /* '湔' -> 28244 */ {0x6e56, 0xbafe}, /* '湖' -> 28246 */ {0x6e58, 0xcfe6}, /* '湘' -> 28248 */ {0x6e5b, 0xd5bf}, /* '湛' -> 28251 */ {0x6e5f, 0xe4d2}, /* '湟' -> 28255 */ {0x6e6b, 0xe4d0}, /* '湫' -> 28267 */ {0x6e6e, 0xe4ce}, /* '湮' -> 28270 */ {0x6e7e, 0xcde5}, /* '湾' -> 28286 */ {0x6e7f, 0xcaaa}, /* '湿' -> 28287 */ {0x6e83, 0xc0a3}, /* '溃' -> 28291 */ {0x6e85, 0xbda6}, /* '溅' -> 28293 */ {0x6e86, 0xe4d3}, /* '溆' -> 28294 */ {0x6e89, 0xb8c8}, /* '溉' -> 28297 */ {0x6e8f, 0xe4e7}, /* '溏' -> 28303 */ {0x6e90, 0xd4b4}, /* '源' -> 28304 */ {0x6e98, 0xe4db}, /* '溘' -> 28312 */ {0x6e9c, 0xc1ef}, /* '溜' -> 28316 */ {0x6e9f, 0xe4e9}, /* '溟' -> 28319 */ {0x6ea2, 0xd2e7}, /* '溢' -> 28322 */ {0x6ea5, 0xe4df}, /* '溥' -> 28325 */ {0x6ea7, 0xe4e0}, /* '溧' -> 28327 */ {0x6eaa, 0xcfaa}, /* '溪' -> 28330 */ {0x6eaf, 0xcbdd}, /* '溯' -> 28335 */ {0x6eb1, 0xe4da}, /* '溱' -> 28337 */ {0x6eb2, 0xe4d1}, /* '溲' -> 28338 */ {0x6eb4, 0xe4e5}, /* '溴' -> 28340 */ {0x6eb6, 0xc8dc}, /* '溶' -> 28342 */ {0x6eb7, 0xe4e3}, /* '溷' -> 28343 */ {0x6eba, 0xc4e7}, /* '溺' -> 28346 */ {0x6ebb, 0xe4e2}, /* '溻' -> 28347 */ {0x6ebd, 0xe4e1}, /* '溽' -> 28349 */ {0x6ec1, 0xb3fc}, /* '滁' -> 28353 */ {0x6ec2, 0xe4e8}, /* '滂' -> 28354 */ {0x6ec7, 0xb5e1}, /* '滇' -> 28359 */ {0x6ecb, 0xd7cc}, /* '滋' -> 28363 */ {0x6ecf, 0xe4e6}, /* '滏' -> 28367 */ {0x6ed1, 0xbbac}, /* '滑' -> 28369 */ {0x6ed3, 0xd7d2}, /* '滓' -> 28371 */ {0x6ed4, 0xcccf}, /* '滔' -> 28372 */ {0x6ed5, 0xebf8}, /* '滕' -> 28373 */ {0x6ed7, 0xe4e4}, /* '滗' -> 28375 */ {0x6eda, 0xb9f6}, /* '滚' -> 28378 */ {0x6ede, 0xd6cd}, /* '滞' -> 28382 */ {0x6edf, 0xe4d9}, /* '滟' -> 28383 */ {0x6ee0, 0xe4dc}, /* '滠' -> 28384 */ {0x6ee1, 0xc2fa}, /* '满' -> 28385 */ {0x6ee2, 0xe4de}, /* '滢' -> 28386 */ {0x6ee4, 0xc2cb}, /* '滤' -> 28388 */ {0x6ee5, 0xc0c4}, /* '滥' -> 28389 */ {0x6ee6, 0xc2d0}, /* '滦' -> 28390 */ {0x6ee8, 0xb1f5}, /* '滨' -> 28392 */ {0x6ee9, 0xccb2}, /* '滩' -> 28393 */ {0x6ef4, 0xb5ce}, /* '滴' -> 28404 */ {0x6ef9, 0xe4ef}, /* '滹' -> 28409 */ {0x6f02, 0xc6af}, /* '漂' -> 28418 */ {0x6f06, 0xc6e1}, /* '漆' -> 28422 */ {0x6f09, 0xe4f5}, /* '漉' -> 28425 */ {0x6f0f, 0xc2a9}, /* '漏' -> 28431 */ {0x6f13, 0xc0ec}, /* '漓' -> 28435 */ {0x6f14, 0xd1dd}, /* '演' -> 28436 */ {0x6f15, 0xe4ee}, /* '漕' -> 28437 */ {0x6f20, 0xc4ae}, /* '漠' -> 28448 */ {0x6f24, 0xe4ed}, /* '漤' -> 28452 */ {0x6f29, 0xe4f6}, /* '漩' -> 28457 */ {0x6f2a, 0xe4f4}, /* '漪' -> 28458 */ {0x6f2b, 0xc2fe}, /* '漫' -> 28459 */ {0x6f2d, 0xe4dd}, /* '漭' -> 28461 */ {0x6f2f, 0xe4f0}, /* '漯' -> 28463 */ {0x6f31, 0xcafe}, /* '漱' -> 28465 */ {0x6f33, 0xd5c4}, /* '漳' -> 28467 */ {0x6f36, 0xe4f1}, /* '漶' -> 28470 */ {0x6f3e, 0xd1fa}, /* '漾' -> 28478 */ {0x6f46, 0xe4eb}, /* '潆' -> 28486 */ {0x6f47, 0xe4ec}, /* '潇' -> 28487 */ {0x6f4b, 0xe4f2}, /* '潋' -> 28491 */ {0x6f4d, 0xceab}, /* '潍' -> 28493 */ {0x6f58, 0xc5cb}, /* '潘' -> 28504 */ {0x6f5c, 0xc7b1}, /* '潜' -> 28508 */ {0x6f5e, 0xc2ba}, /* '潞' -> 28510 */ {0x6f62, 0xe4ea}, /* '潢' -> 28514 */ {0x6f66, 0xc1ca}, /* '潦' -> 28518 */ {0x6f6d, 0xccb6}, /* '潭' -> 28525 */ {0x6f6e, 0xb3b1}, /* '潮' -> 28526 */ {0x6f72, 0xe4fb}, /* '潲' -> 28530 */ {0x6f74, 0xe4f3}, /* '潴' -> 28532 */ {0x6f78, 0xe4fa}, /* '潸' -> 28536 */ {0x6f7a, 0xe4fd}, /* '潺' -> 28538 */ {0x6f7c, 0xe4fc}, /* '潼' -> 28540 */ {0x6f84, 0xb3ce}, /* '澄' -> 28548 */ {0x6f88, 0xb3ba}, /* '澈' -> 28552 */ {0x6f89, 0xe4f7}, /* '澉' -> 28553 */ {0x6f8c, 0xe4f9}, /* '澌' -> 28556 */ {0x6f8d, 0xe4f8}, /* '澍' -> 28557 */ {0x6f8e, 0xc5ec}, /* '澎' -> 28558 */ {0x6f9c, 0xc0bd}, /* '澜' -> 28572 */ {0x6fa1, 0xd4e8}, /* '澡' -> 28577 */ {0x6fa7, 0xe5a2}, /* '澧' -> 28583 */ {0x6fb3, 0xb0c4}, /* '澳' -> 28595 */ {0x6fb6, 0xe5a4}, /* '澶' -> 28598 */ {0x6fb9, 0xe5a3}, /* '澹' -> 28601 */ {0x6fc0, 0xbca4}, /* '激' -> 28608 */ {0x6fc2, 0xe5a5}, /* '濂' -> 28610 */ {0x6fc9, 0xe5a1}, /* '濉' -> 28617 */ {0x6fd1, 0xe4fe}, /* '濑' -> 28625 */ {0x6fd2, 0xb1f4}, /* '濒' -> 28626 */ {0x6fde, 0xe5a8}, /* '濞' -> 28638 */ {0x6fe0, 0xe5a9}, /* '濠' -> 28640 */ {0x6fe1, 0xe5a6}, /* '濡' -> 28641 */ {0x6fee, 0xe5a7}, /* '濮' -> 28654 */ {0x6fef, 0xe5aa}, /* '濯' -> 28655 */ {0x7011, 0xc6d9}, /* '瀑' -> 28689 */ {0x701a, 0xe5ab}, /* '瀚' -> 28698 */ {0x701b, 0xe5ad}, /* '瀛' -> 28699 */ {0x7023, 0xe5ac}, /* '瀣' -> 28707 */ {0x7035, 0xe5af}, /* '瀵' -> 28725 */ {0x7039, 0xe5ae}, /* '瀹' -> 28729 */ {0x704c, 0xb9e0}, /* '灌' -> 28748 */ {0x704f, 0xe5b0}, /* '灏' -> 28751 */ {0x705e, 0xe5b1}, /* '灞' -> 28766 */ {0x706b, 0xbbf0}, /* '火' -> 28779 */ {0x706c, 0xece1}, /* '灬' -> 28780 */ {0x706d, 0xc3f0}, /* '灭' -> 28781 */ {0x706f, 0xb5c6}, /* '灯' -> 28783 */ {0x7070, 0xbbd2}, /* '灰' -> 28784 */ {0x7075, 0xc1e9}, /* '灵' -> 28789 */ {0x7076, 0xd4ee}, /* '灶' -> 28790 */ {0x7078, 0xbec4}, /* '灸' -> 28792 */ {0x707c, 0xd7c6}, /* '灼' -> 28796 */ {0x707e, 0xd4d6}, /* '灾' -> 28798 */ {0x707f, 0xb2d3}, /* '灿' -> 28799 */ {0x7080, 0xecbe}, /* '炀' -> 28800 */ {0x7085, 0xeac1}, /* '炅' -> 28805 */ {0x7089, 0xc2af}, /* '炉' -> 28809 */ {0x708a, 0xb4b6}, /* '炊' -> 28810 */ {0x708e, 0xd1d7}, /* '炎' -> 28814 */ {0x7092, 0xb3b4}, /* '炒' -> 28818 */ {0x7094, 0xc8b2}, /* '炔' -> 28820 */ {0x7095, 0xbfbb}, /* '炕' -> 28821 */ {0x7096, 0xecc0}, /* '炖' -> 28822 */ {0x7099, 0xd6cb}, /* '炙' -> 28825 */ {0x709c, 0xecbf}, /* '炜' -> 28828 */ {0x709d, 0xecc1}, /* '炝' -> 28829 */ {0x70ab, 0xecc5}, /* '炫' -> 28843 */ {0x70ac, 0xbee6}, /* '炬' -> 28844 */ {0x70ad, 0xccbf}, /* '炭' -> 28845 */ {0x70ae, 0xc5da}, /* '炮' -> 28846 */ {0x70af, 0xbebc}, /* '炯' -> 28847 */ {0x70b1, 0xecc6}, /* '炱' -> 28849 */ {0x70b3, 0xb1fe}, /* '炳' -> 28851 */ {0x70b7, 0xecc4}, /* '炷' -> 28855 */ {0x70b8, 0xd5a8}, /* '炸' -> 28856 */ {0x70b9, 0xb5e3}, /* '点' -> 28857 */ {0x70bb, 0xecc2}, /* '炻' -> 28859 */ {0x70bc, 0xc1b6}, /* '炼' -> 28860 */ {0x70bd, 0xb3e3}, /* '炽' -> 28861 */ {0x70c0, 0xecc3}, /* '烀' -> 28864 */ {0x70c1, 0xcbb8}, /* '烁' -> 28865 */ {0x70c2, 0xc0c3}, /* '烂' -> 28866 */ {0x70c3, 0xccfe}, /* '烃' -> 28867 */ {0x70c8, 0xc1d2}, /* '烈' -> 28872 */ {0x70ca, 0xecc8}, /* '烊' -> 28874 */ {0x70d8, 0xbae6}, /* '烘' -> 28888 */ {0x70d9, 0xc0d3}, /* '烙' -> 28889 */ {0x70db, 0xd6f2}, /* '烛' -> 28891 */ {0x70df, 0xd1cc}, /* '烟' -> 28895 */ {0x70e4, 0xbfbe}, /* '烤' -> 28900 */ {0x70e6, 0xb7b3}, /* '烦' -> 28902 */ {0x70e7, 0xc9d5}, /* '烧' -> 28903 */ {0x70e8, 0xecc7}, /* '烨' -> 28904 */ {0x70e9, 0xbbe2}, /* '烩' -> 28905 */ {0x70eb, 0xcccc}, /* '烫' -> 28907 */ {0x70ec, 0xbdfd}, /* '烬' -> 28908 */ {0x70ed, 0xc8c8}, /* '热' -> 28909 */ {0x70ef, 0xcfa9}, /* '烯' -> 28911 */ {0x70f7, 0xcde9}, /* '烷' -> 28919 */ {0x70f9, 0xc5eb}, /* '烹' -> 28921 */ {0x70fd, 0xb7e9}, /* '烽' -> 28925 */ {0x7109, 0xd1c9}, /* '焉' -> 28937 */ {0x710a, 0xbab8}, /* '焊' -> 28938 */ {0x7110, 0xecc9}, /* '焐' -> 28944 */ {0x7113, 0xecca}, /* '焓' -> 28947 */ {0x7115, 0xbbc0}, /* '焕' -> 28949 */ {0x7116, 0xeccb}, /* '焖' -> 28950 */ {0x7118, 0xece2}, /* '焘' -> 28952 */ {0x7119, 0xb1ba}, /* '焙' -> 28953 */ {0x711a, 0xb7d9}, /* '焚' -> 28954 */ {0x7126, 0xbdb9}, /* '焦' -> 28966 */ {0x712f, 0xeccc}, /* '焯' -> 28975 */ {0x7130, 0xd1e6}, /* '焰' -> 28976 */ {0x7131, 0xeccd}, /* '焱' -> 28977 */ {0x7136, 0xc8bb}, /* '然' -> 28982 */ {0x7145, 0xecd1}, /* '煅' -> 28997 */ {0x714a, 0xecd3}, /* '煊' -> 29002 */ {0x714c, 0xbbcd}, /* '煌' -> 29004 */ {0x714e, 0xbce5}, /* '煎' -> 29006 */ {0x715c, 0xeccf}, /* '煜' -> 29020 */ {0x715e, 0xc9b7}, /* '煞' -> 29022 */ {0x7164, 0xc3ba}, /* '煤' -> 29028 */ {0x7166, 0xece3}, /* '煦' -> 29030 */ {0x7167, 0xd5d5}, /* '照' -> 29031 */ {0x7168, 0xecd0}, /* '煨' -> 29032 */ {0x716e, 0xd6f3}, /* '煮' -> 29038 */ {0x7172, 0xecd2}, /* '煲' -> 29042 */ {0x7173, 0xecce}, /* '煳' -> 29043 */ {0x7178, 0xecd4}, /* '煸' -> 29048 */ {0x717a, 0xecd5}, /* '煺' -> 29050 */ {0x717d, 0xc9bf}, /* '煽' -> 29053 */ {0x7184, 0xcfa8}, /* '熄' -> 29060 */ {0x718a, 0xd0dc}, /* '熊' -> 29066 */ {0x718f, 0xd1ac}, /* '熏' -> 29071 */ {0x7194, 0xc8db}, /* '熔' -> 29076 */ {0x7198, 0xecd6}, /* '熘' -> 29080 */ {0x7199, 0xcef5}, /* '熙' -> 29081 */ {0x719f, 0xcaec}, /* '熟' -> 29087 */ {0x71a0, 0xecda}, /* '熠' -> 29088 */ {0x71a8, 0xecd9}, /* '熨' -> 29096 */ {0x71ac, 0xb0be}, /* '熬' -> 29100 */ {0x71b3, 0xecd7}, /* '熳' -> 29107 */ {0x71b5, 0xecd8}, /* '熵' -> 29109 */ {0x71b9, 0xece4}, /* '熹' -> 29113 */ {0x71c3, 0xc8bc}, /* '燃' -> 29123 */ {0x71ce, 0xc1c7}, /* '燎' -> 29134 */ {0x71d4, 0xecdc}, /* '燔' -> 29140 */ {0x71d5, 0xd1e0}, /* '燕' -> 29141 */ {0x71e0, 0xecdb}, /* '燠' -> 29152 */ {0x71e5, 0xd4ef}, /* '燥' -> 29157 */ {0x71e7, 0xecdd}, /* '燧' -> 29159 */ {0x71ee, 0xdbc6}, /* '燮' -> 29166 */ {0x71f9, 0xecde}, /* '燹' -> 29177 */ {0x7206, 0xb1ac}, /* '爆' -> 29190 */ {0x721d, 0xecdf}, /* '爝' -> 29213 */ {0x7228, 0xece0}, /* '爨' -> 29224 */ {0x722a, 0xd7a6}, /* '爪' -> 29226 */ {0x722c, 0xc5c0}, /* '爬' -> 29228 */ {0x7230, 0xebbc}, /* '爰' -> 29232 */ {0x7231, 0xb0ae}, /* '爱' -> 29233 */ {0x7235, 0xbef4}, /* '爵' -> 29237 */ {0x7236, 0xb8b8}, /* '父' -> 29238 */ {0x7237, 0xd2af}, /* '爷' -> 29239 */ {0x7238, 0xb0d6}, /* '爸' -> 29240 */ {0x7239, 0xb5f9}, /* '爹' -> 29241 */ {0x723b, 0xd8b3}, /* '爻' -> 29243 */ {0x723d, 0xcbac}, /* '爽' -> 29245 */ {0x723f, 0xe3dd}, /* '爿' -> 29247 */ {0x7247, 0xc6ac}, /* '片' -> 29255 */ {0x7248, 0xb0e6}, /* '版' -> 29256 */ {0x724c, 0xc5c6}, /* '牌' -> 29260 */ {0x724d, 0xebb9}, /* '牍' -> 29261 */ {0x7252, 0xebba}, /* '牒' -> 29266 */ {0x7256, 0xebbb}, /* '牖' -> 29270 */ {0x7259, 0xd1c0}, /* '牙' -> 29273 */ {0x725b, 0xc5a3}, /* '牛' -> 29275 */ {0x725d, 0xeaf2}, /* '牝' -> 29277 */ {0x725f, 0xc4b2}, /* '牟' -> 29279 */ {0x7261, 0xc4b5}, /* '牡' -> 29281 */ {0x7262, 0xc0ce}, /* '牢' -> 29282 */ {0x7266, 0xeaf3}, /* '牦' -> 29286 */ {0x7267, 0xc4c1}, /* '牧' -> 29287 */ {0x7269, 0xceef}, /* '物' -> 29289 */ {0x726e, 0xeaf0}, /* '牮' -> 29294 */ {0x726f, 0xeaf4}, /* '牯' -> 29295 */ {0x7272, 0xc9fc}, /* '牲' -> 29298 */ {0x7275, 0xc7a3}, /* '牵' -> 29301 */ {0x7279, 0xccd8}, /* '特' -> 29305 */ {0x727a, 0xcefe}, /* '牺' -> 29306 */ {0x727e, 0xeaf5}, /* '牾' -> 29310 */ {0x727f, 0xeaf6}, /* '牿' -> 29311 */ {0x7280, 0xcfac}, /* '犀' -> 29312 */ {0x7281, 0xc0e7}, /* '犁' -> 29313 */ {0x7284, 0xeaf7}, /* '犄' -> 29316 */ {0x728a, 0xb6bf}, /* '犊' -> 29322 */ {0x728b, 0xeaf8}, /* '犋' -> 29323 */ {0x728d, 0xeaf9}, /* '犍' -> 29325 */ {0x728f, 0xeafa}, /* '犏' -> 29327 */ {0x7292, 0xeafb}, /* '犒' -> 29330 */ {0x729f, 0xeaf1}, /* '犟' -> 29343 */ {0x72ac, 0xc8ae}, /* '犬' -> 29356 */ {0x72ad, 0xe1eb}, /* '犭' -> 29357 */ {0x72af, 0xb7b8}, /* '犯' -> 29359 */ {0x72b0, 0xe1ec}, /* '犰' -> 29360 */ {0x72b4, 0xe1ed}, /* '犴' -> 29364 */ {0x72b6, 0xd7b4}, /* '状' -> 29366 */ {0x72b7, 0xe1ee}, /* '犷' -> 29367 */ {0x72b8, 0xe1ef}, /* '犸' -> 29368 */ {0x72b9, 0xd3cc}, /* '犹' -> 29369 */ {0x72c1, 0xe1f1}, /* '狁' -> 29377 */ {0x72c2, 0xbff1}, /* '狂' -> 29378 */ {0x72c3, 0xe1f0}, /* '狃' -> 29379 */ {0x72c4, 0xb5d2}, /* '狄' -> 29380 */ {0x72c8, 0xb1b7}, /* '狈' -> 29384 */ {0x72cd, 0xe1f3}, /* '狍' -> 29389 */ {0x72ce, 0xe1f2}, /* '狎' -> 29390 */ {0x72d0, 0xbafc}, /* '狐' -> 29392 */ {0x72d2, 0xe1f4}, /* '狒' -> 29394 */ {0x72d7, 0xb9b7}, /* '狗' -> 29399 */ {0x72d9, 0xbed1}, /* '狙' -> 29401 */ {0x72de, 0xc4fc}, /* '狞' -> 29406 */ {0x72e0, 0xbadd}, /* '狠' -> 29408 */ {0x72e1, 0xbdc6}, /* '狡' -> 29409 */ {0x72e8, 0xe1f5}, /* '狨' -> 29416 */ {0x72e9, 0xe1f7}, /* '狩' -> 29417 */ {0x72ec, 0xb6c0}, /* '独' -> 29420 */ {0x72ed, 0xcfc1}, /* '狭' -> 29421 */ {0x72ee, 0xcaa8}, /* '狮' -> 29422 */ {0x72ef, 0xe1f6}, /* '狯' -> 29423 */ {0x72f0, 0xd5f8}, /* '狰' -> 29424 */ {0x72f1, 0xd3fc}, /* '狱' -> 29425 */ {0x72f2, 0xe1f8}, /* '狲' -> 29426 */ {0x72f3, 0xe1fc}, /* '狳' -> 29427 */ {0x72f4, 0xe1f9}, /* '狴' -> 29428 */ {0x72f7, 0xe1fa}, /* '狷' -> 29431 */ {0x72f8, 0xc0ea}, /* '狸' -> 29432 */ {0x72fa, 0xe1fe}, /* '狺' -> 29434 */ {0x72fb, 0xe2a1}, /* '狻' -> 29435 */ {0x72fc, 0xc0c7}, /* '狼' -> 29436 */ {0x7301, 0xe1fb}, /* '猁' -> 29441 */ {0x7303, 0xe1fd}, /* '猃' -> 29443 */ {0x730a, 0xe2a5}, /* '猊' -> 29450 */ {0x730e, 0xc1d4}, /* '猎' -> 29454 */ {0x7313, 0xe2a3}, /* '猓' -> 29459 */ {0x7315, 0xe2a8}, /* '猕' -> 29461 */ {0x7316, 0xb2fe}, /* '猖' -> 29462 */ {0x7317, 0xe2a2}, /* '猗' -> 29463 */ {0x731b, 0xc3cd}, /* '猛' -> 29467 */ {0x731c, 0xb2c2}, /* '猜' -> 29468 */ {0x731d, 0xe2a7}, /* '猝' -> 29469 */ {0x731e, 0xe2a6}, /* '猞' -> 29470 */ {0x7321, 0xe2a4}, /* '猡' -> 29473 */ {0x7322, 0xe2a9}, /* '猢' -> 29474 */ {0x7325, 0xe2ab}, /* '猥' -> 29477 */ {0x7329, 0xd0c9}, /* '猩' -> 29481 */ {0x732a, 0xd6ed}, /* '猪' -> 29482 */ {0x732b, 0xc3a8}, /* '猫' -> 29483 */ {0x732c, 0xe2ac}, /* '猬' -> 29484 */ {0x732e, 0xcfd7}, /* '献' -> 29486 */ {0x7331, 0xe2ae}, /* '猱' -> 29489 */ {0x7334, 0xbaef}, /* '猴' -> 29492 */ {0x7337, 0xe9e0}, /* '猷' -> 29495 */ {0x7338, 0xe2ad}, /* '猸' -> 29496 */ {0x7339, 0xe2aa}, /* '猹' -> 29497 */ {0x733e, 0xbbab}, /* '猾' -> 29502 */ {0x733f, 0xd4b3}, /* '猿' -> 29503 */ {0x734d, 0xe2b0}, /* '獍' -> 29517 */ {0x7350, 0xe2af}, /* '獐' -> 29520 */ {0x7352, 0xe9e1}, /* '獒' -> 29522 */ {0x7357, 0xe2b1}, /* '獗' -> 29527 */ {0x7360, 0xe2b2}, /* '獠' -> 29536 */ {0x736c, 0xe2b3}, /* '獬' -> 29548 */ {0x736d, 0xcca1}, /* '獭' -> 29549 */ {0x736f, 0xe2b4}, /* '獯' -> 29551 */ {0x737e, 0xe2b5}, /* '獾' -> 29566 */ {0x7384, 0xd0fe}, /* '玄' -> 29572 */ {0x7387, 0xc2ca}, /* '率' -> 29575 */ {0x7389, 0xd3f1}, /* '玉' -> 29577 */ {0x738b, 0xcdf5}, /* '王' -> 29579 */ {0x738e, 0xe7e0}, /* '玎' -> 29582 */ {0x7391, 0xe7e1}, /* '玑' -> 29585 */ {0x7396, 0xbec1}, /* '玖' -> 29590 */ {0x739b, 0xc2ea}, /* '玛' -> 29595 */ {0x739f, 0xe7e4}, /* '玟' -> 29599 */ {0x73a2, 0xe7e3}, /* '玢' -> 29602 */ {0x73a9, 0xcde6}, /* '玩' -> 29609 */ {0x73ab, 0xc3b5}, /* '玫' -> 29611 */ {0x73ae, 0xe7e2}, /* '玮' -> 29614 */ {0x73af, 0xbbb7}, /* '环' -> 29615 */ {0x73b0, 0xcfd6}, /* '现' -> 29616 */ {0x73b2, 0xc1e1}, /* '玲' -> 29618 */ {0x73b3, 0xe7e9}, /* '玳' -> 29619 */ {0x73b7, 0xe7e8}, /* '玷' -> 29623 */ {0x73ba, 0xe7f4}, /* '玺' -> 29626 */ {0x73bb, 0xb2a3}, /* '玻' -> 29627 */ {0x73c0, 0xe7ea}, /* '珀' -> 29632 */ {0x73c2, 0xe7e6}, /* '珂' -> 29634 */ {0x73c8, 0xe7ec}, /* '珈' -> 29640 */ {0x73c9, 0xe7eb}, /* '珉' -> 29641 */ {0x73ca, 0xc9ba}, /* '珊' -> 29642 */ {0x73cd, 0xd5e4}, /* '珍' -> 29645 */ {0x73cf, 0xe7e5}, /* '珏' -> 29647 */ {0x73d0, 0xb7a9}, /* '珐' -> 29648 */ {0x73d1, 0xe7e7}, /* '珑' -> 29649 */ {0x73d9, 0xe7ee}, /* '珙' -> 29657 */ {0x73de, 0xe7f3}, /* '珞' -> 29662 */ {0x73e0, 0xd6e9}, /* '珠' -> 29664 */ {0x73e5, 0xe7ed}, /* '珥' -> 29669 */ {0x73e7, 0xe7f2}, /* '珧' -> 29671 */ {0x73e9, 0xe7f1}, /* '珩' -> 29673 */ {0x73ed, 0xb0e0}, /* '班' -> 29677 */ {0x73f2, 0xe7f5}, /* '珲' -> 29682 */ {0x7403, 0xc7f2}, /* '球' -> 29699 */ {0x7405, 0xc0c5}, /* '琅' -> 29701 */ {0x7406, 0xc0ed}, /* '理' -> 29702 */ {0x7409, 0xc1f0}, /* '琉' -> 29705 */ {0x740a, 0xe7f0}, /* '琊' -> 29706 */ {0x740f, 0xe7f6}, /* '琏' -> 29711 */ {0x7410, 0xcbf6}, /* '琐' -> 29712 */ {0x741a, 0xe8a2}, /* '琚' -> 29722 */ {0x741b, 0xe8a1}, /* '琛' -> 29723 */ {0x7422, 0xd7c1}, /* '琢' -> 29730 */ {0x7425, 0xe7fa}, /* '琥' -> 29733 */ {0x7426, 0xe7f9}, /* '琦' -> 29734 */ {0x7428, 0xe7fb}, /* '琨' -> 29736 */ {0x742a, 0xe7f7}, /* '琪' -> 29738 */ {0x742c, 0xe7fe}, /* '琬' -> 29740 */ {0x742e, 0xe7fd}, /* '琮' -> 29742 */ {0x7430, 0xe7fc}, /* '琰' -> 29744 */ {0x7433, 0xc1d5}, /* '琳' -> 29747 */ {0x7434, 0xc7d9}, /* '琴' -> 29748 */ {0x7435, 0xc5fd}, /* '琵' -> 29749 */ {0x7436, 0xc5c3}, /* '琶' -> 29750 */ {0x743c, 0xc7ed}, /* '琼' -> 29756 */ {0x7441, 0xe8a3}, /* '瑁' -> 29761 */ {0x7455, 0xe8a6}, /* '瑕' -> 29781 */ {0x7457, 0xe8a5}, /* '瑗' -> 29783 */ {0x7459, 0xe8a7}, /* '瑙' -> 29785 */ {0x745a, 0xbaf7}, /* '瑚' -> 29786 */ {0x745b, 0xe7f8}, /* '瑛' -> 29787 */ {0x745c, 0xe8a4}, /* '瑜' -> 29788 */ {0x745e, 0xc8f0}, /* '瑞' -> 29790 */ {0x745f, 0xc9aa}, /* '瑟' -> 29791 */ {0x746d, 0xe8a9}, /* '瑭' -> 29805 */ {0x7470, 0xb9e5}, /* '瑰' -> 29808 */ {0x7476, 0xd1fe}, /* '瑶' -> 29814 */ {0x7477, 0xe8a8}, /* '瑷' -> 29815 */ {0x747e, 0xe8aa}, /* '瑾' -> 29822 */ {0x7480, 0xe8ad}, /* '璀' -> 29824 */ {0x7481, 0xe8ae}, /* '璁' -> 29825 */ {0x7483, 0xc1a7}, /* '璃' -> 29827 */ {0x7487, 0xe8af}, /* '璇' -> 29831 */ {0x748b, 0xe8b0}, /* '璋' -> 29835 */ {0x748e, 0xe8ac}, /* '璎' -> 29838 */ {0x7490, 0xe8b4}, /* '璐' -> 29840 */ {0x749c, 0xe8ab}, /* '璜' -> 29852 */ {0x749e, 0xe8b1}, /* '璞' -> 29854 */ {0x74a7, 0xe8b5}, /* '璧' -> 29863 */ {0x74a8, 0xe8b2}, /* '璨' -> 29864 */ {0x74a9, 0xe8b3}, /* '璩' -> 29865 */ {0x74ba, 0xe8b7}, /* '璺' -> 29882 */ {0x74d2, 0xe8b6}, /* '瓒' -> 29906 */ {0x74dc, 0xb9cf}, /* '瓜' -> 29916 */ {0x74de, 0xf0ac}, /* '瓞' -> 29918 */ {0x74e0, 0xf0ad}, /* '瓠' -> 29920 */ {0x74e2, 0xc6b0}, /* '瓢' -> 29922 */ {0x74e3, 0xb0ea}, /* '瓣' -> 29923 */ {0x74e4, 0xc8bf}, /* '瓤' -> 29924 */ {0x74e6, 0xcddf}, /* '瓦' -> 29926 */ {0x74ee, 0xcecd}, /* '瓮' -> 29934 */ {0x74ef, 0xeab1}, /* '瓯' -> 29935 */ {0x74f4, 0xeab2}, /* '瓴' -> 29940 */ {0x74f6, 0xc6bf}, /* '瓶' -> 29942 */ {0x74f7, 0xb4c9}, /* '瓷' -> 29943 */ {0x74ff, 0xeab3}, /* '瓿' -> 29951 */ {0x7504, 0xd5e7}, /* '甄' -> 29956 */ {0x750d, 0xddf9}, /* '甍' -> 29965 */ {0x750f, 0xeab4}, /* '甏' -> 29967 */ {0x7511, 0xeab5}, /* '甑' -> 29969 */ {0x7513, 0xeab6}, /* '甓' -> 29971 */ {0x7518, 0xb8ca}, /* '甘' -> 29976 */ {0x7519, 0xdfb0}, /* '甙' -> 29977 */ {0x751a, 0xc9f5}, /* '甚' -> 29978 */ {0x751c, 0xccf0}, /* '甜' -> 29980 */ {0x751f, 0xc9fa}, /* '生' -> 29983 */ {0x7525, 0xc9fb}, /* '甥' -> 29989 */ {0x7528, 0xd3c3}, /* '用' -> 29992 */ {0x7529, 0xcba6}, /* '甩' -> 29993 */ {0x752b, 0xb8a6}, /* '甫' -> 29995 */ {0x752c, 0xf0ae}, /* '甬' -> 29996 */ {0x752d, 0xb1c2}, /* '甭' -> 29997 */ {0x752f, 0xe5b8}, /* '甯' -> 29999 */ {0x7530, 0xccef}, /* '田' -> 30000 */ {0x7531, 0xd3c9}, /* '由' -> 30001 */ {0x7532, 0xbcd7}, /* '甲' -> 30002 */ {0x7533, 0xc9ea}, /* '申' -> 30003 */ {0x7535, 0xb5e7}, /* '电' -> 30005 */ {0x7537, 0xc4d0}, /* '男' -> 30007 */ {0x7538, 0xb5e9}, /* '甸' -> 30008 */ {0x753a, 0xeeae}, /* '町' -> 30010 */ {0x753b, 0xbbad}, /* '画' -> 30011 */ {0x753e, 0xe7de}, /* '甾' -> 30014 */ {0x7540, 0xeeaf}, /* '畀' -> 30016 */ {0x7545, 0xb3a9}, /* '畅' -> 30021 */ {0x7548, 0xeeb2}, /* '畈' -> 30024 */ {0x754b, 0xeeb1}, /* '畋' -> 30027 */ {0x754c, 0xbde7}, /* '界' -> 30028 */ {0x754e, 0xeeb0}, /* '畎' -> 30030 */ {0x754f, 0xceb7}, /* '畏' -> 30031 */ {0x7554, 0xc5cf}, /* '畔' -> 30036 */ {0x7559, 0xc1f4}, /* '留' -> 30041 */ {0x755a, 0xdbce}, /* '畚' -> 30042 */ {0x755b, 0xeeb3}, /* '畛' -> 30043 */ {0x755c, 0xd0f3}, /* '畜' -> 30044 */ {0x7565, 0xc2d4}, /* '略' -> 30053 */ {0x7566, 0xc6e8}, /* '畦' -> 30054 */ {0x756a, 0xb7ac}, /* '番' -> 30058 */ {0x7572, 0xeeb4}, /* '畲' -> 30066 */ {0x7574, 0xb3eb}, /* '畴' -> 30068 */ {0x7578, 0xbbfb}, /* '畸' -> 30072 */ {0x7579, 0xeeb5}, /* '畹' -> 30073 */ {0x757f, 0xe7dc}, /* '畿' -> 30079 */ {0x7583, 0xeeb6}, /* '疃' -> 30083 */ {0x7586, 0xbdae}, /* '疆' -> 30086 */ {0x758b, 0xf1e2}, /* '疋' -> 30091 */ {0x758f, 0xcae8}, /* '疏' -> 30095 */ {0x7591, 0xd2c9}, /* '疑' -> 30097 */ {0x7592, 0xf0da}, /* '疒' -> 30098 */ {0x7594, 0xf0db}, /* '疔' -> 30100 */ {0x7596, 0xf0dc}, /* '疖' -> 30102 */ {0x7597, 0xc1c6}, /* '疗' -> 30103 */ {0x7599, 0xb8ed}, /* '疙' -> 30105 */ {0x759a, 0xbece}, /* '疚' -> 30106 */ {0x759d, 0xf0de}, /* '疝' -> 30109 */ {0x759f, 0xc5b1}, /* '疟' -> 30111 */ {0x75a0, 0xf0dd}, /* '疠' -> 30112 */ {0x75a1, 0xd1f1}, /* '疡' -> 30113 */ {0x75a3, 0xf0e0}, /* '疣' -> 30115 */ {0x75a4, 0xb0cc}, /* '疤' -> 30116 */ {0x75a5, 0xbdea}, /* '疥' -> 30117 */ {0x75ab, 0xd2df}, /* '疫' -> 30123 */ {0x75ac, 0xf0df}, /* '疬' -> 30124 */ {0x75ae, 0xb4af}, /* '疮' -> 30126 */ {0x75af, 0xb7e8}, /* '疯' -> 30127 */ {0x75b0, 0xf0e6}, /* '疰' -> 30128 */ {0x75b1, 0xf0e5}, /* '疱' -> 30129 */ {0x75b2, 0xc6a3}, /* '疲' -> 30130 */ {0x75b3, 0xf0e1}, /* '疳' -> 30131 */ {0x75b4, 0xf0e2}, /* '疴' -> 30132 */ {0x75b5, 0xb4c3}, /* '疵' -> 30133 */ {0x75b8, 0xf0e3}, /* '疸' -> 30136 */ {0x75b9, 0xd5ee}, /* '疹' -> 30137 */ {0x75bc, 0xccdb}, /* '疼' -> 30140 */ {0x75bd, 0xbed2}, /* '疽' -> 30141 */ {0x75be, 0xbcb2}, /* '疾' -> 30142 */ {0x75c2, 0xf0e8}, /* '痂' -> 30146 */ {0x75c3, 0xf0e7}, /* '痃' -> 30147 */ {0x75c4, 0xf0e4}, /* '痄' -> 30148 */ {0x75c5, 0xb2a1}, /* '病' -> 30149 */ {0x75c7, 0xd6a2}, /* '症' -> 30151 */ {0x75c8, 0xd3b8}, /* '痈' -> 30152 */ {0x75c9, 0xbeb7}, /* '痉' -> 30153 */ {0x75ca, 0xc8ac}, /* '痊' -> 30154 */ {0x75cd, 0xf0ea}, /* '痍' -> 30157 */ {0x75d2, 0xd1f7}, /* '痒' -> 30162 */ {0x75d4, 0xd6cc}, /* '痔' -> 30164 */ {0x75d5, 0xbadb}, /* '痕' -> 30165 */ {0x75d6, 0xf0e9}, /* '痖' -> 30166 */ {0x75d8, 0xb6bb}, /* '痘' -> 30168 */ {0x75db, 0xcdb4}, /* '痛' -> 30171 */ {0x75de, 0xc6a6}, /* '痞' -> 30174 */ {0x75e2, 0xc1a1}, /* '痢' -> 30178 */ {0x75e3, 0xf0eb}, /* '痣' -> 30179 */ {0x75e4, 0xf0ee}, /* '痤' -> 30180 */ {0x75e6, 0xf0ed}, /* '痦' -> 30182 */ {0x75e7, 0xf0f0}, /* '痧' -> 30183 */ {0x75e8, 0xf0ec}, /* '痨' -> 30184 */ {0x75ea, 0xbbbe}, /* '痪' -> 30186 */ {0x75eb, 0xf0ef}, /* '痫' -> 30187 */ {0x75f0, 0xccb5}, /* '痰' -> 30192 */ {0x75f1, 0xf0f2}, /* '痱' -> 30193 */ {0x75f4, 0xb3d5}, /* '痴' -> 30196 */ {0x75f9, 0xb1d4}, /* '痹' -> 30201 */ {0x75fc, 0xf0f3}, /* '痼' -> 30204 */ {0x75ff, 0xf0f4}, /* '痿' -> 30207 */ {0x7600, 0xf0f6}, /* '瘀' -> 30208 */ {0x7601, 0xb4e1}, /* '瘁' -> 30209 */ {0x7603, 0xf0f1}, /* '瘃' -> 30211 */ {0x7605, 0xf0f7}, /* '瘅' -> 30213 */ {0x760a, 0xf0fa}, /* '瘊' -> 30218 */ {0x760c, 0xf0f8}, /* '瘌' -> 30220 */ {0x7610, 0xf0f5}, /* '瘐' -> 30224 */ {0x7615, 0xf0fd}, /* '瘕' -> 30229 */ {0x7617, 0xf0f9}, /* '瘗' -> 30231 */ {0x7618, 0xf0fc}, /* '瘘' -> 30232 */ {0x7619, 0xf0fe}, /* '瘙' -> 30233 */ {0x761b, 0xf1a1}, /* '瘛' -> 30235 */ {0x761f, 0xcec1}, /* '瘟' -> 30239 */ {0x7620, 0xf1a4}, /* '瘠' -> 30240 */ {0x7622, 0xf1a3}, /* '瘢' -> 30242 */ {0x7624, 0xc1f6}, /* '瘤' -> 30244 */ {0x7625, 0xf0fb}, /* '瘥' -> 30245 */ {0x7626, 0xcadd}, /* '瘦' -> 30246 */ {0x7629, 0xb4f1}, /* '瘩' -> 30249 */ {0x762a, 0xb1f1}, /* '瘪' -> 30250 */ {0x762b, 0xccb1}, /* '瘫' -> 30251 */ {0x762d, 0xf1a6}, /* '瘭' -> 30253 */ {0x7630, 0xf1a7}, /* '瘰' -> 30256 */ {0x7633, 0xf1ac}, /* '瘳' -> 30259 */ {0x7634, 0xd5ce}, /* '瘴' -> 30260 */ {0x7635, 0xf1a9}, /* '瘵' -> 30261 */ {0x7638, 0xc8b3}, /* '瘸' -> 30264 */ {0x763c, 0xf1a2}, /* '瘼' -> 30268 */ {0x763e, 0xf1ab}, /* '瘾' -> 30270 */ {0x763f, 0xf1a8}, /* '瘿' -> 30271 */ {0x7640, 0xf1a5}, /* '癀' -> 30272 */ {0x7643, 0xf1aa}, /* '癃' -> 30275 */ {0x764c, 0xb0a9}, /* '癌' -> 30284 */ {0x764d, 0xf1ad}, /* '癍' -> 30285 */ {0x7654, 0xf1af}, /* '癔' -> 30292 */ {0x7656, 0xf1b1}, /* '癖' -> 30294 */ {0x765c, 0xf1b0}, /* '癜' -> 30300 */ {0x765e, 0xf1ae}, /* '癞' -> 30302 */ {0x7663, 0xd1a2}, /* '癣' -> 30307 */ {0x766b, 0xf1b2}, /* '癫' -> 30315 */ {0x766f, 0xf1b3}, /* '癯' -> 30319 */ {0x7678, 0xb9ef}, /* '癸' -> 30328 */ {0x767b, 0xb5c7}, /* '登' -> 30331 */ {0x767d, 0xb0d7}, /* '白' -> 30333 */ {0x767e, 0xb0d9}, /* '百' -> 30334 */ {0x7682, 0xd4ed}, /* '皂' -> 30338 */ {0x7684, 0xb5c4}, /* '的' -> 30340 */ {0x7686, 0xbdd4}, /* '皆' -> 30342 */ {0x7687, 0xbbca}, /* '皇' -> 30343 */ {0x7688, 0xf0a7}, /* '皈' -> 30344 */ {0x768b, 0xb8de}, /* '皋' -> 30347 */ {0x768e, 0xf0a8}, /* '皎' -> 30350 */ {0x7691, 0xb0a8}, /* '皑' -> 30353 */ {0x7693, 0xf0a9}, /* '皓' -> 30355 */ {0x7696, 0xcdee}, /* '皖' -> 30358 */ {0x7699, 0xf0aa}, /* '皙' -> 30361 */ {0x76a4, 0xf0ab}, /* '皤' -> 30372 */ {0x76ae, 0xc6a4}, /* '皮' -> 30382 */ {0x76b1, 0xd6e5}, /* '皱' -> 30385 */ {0x76b2, 0xf1e4}, /* '皲' -> 30386 */ {0x76b4, 0xf1e5}, /* '皴' -> 30388 */ {0x76bf, 0xc3f3}, /* '皿' -> 30399 */ {0x76c2, 0xd3db}, /* '盂' -> 30402 */ {0x76c5, 0xd6d1}, /* '盅' -> 30405 */ {0x76c6, 0xc5e8}, /* '盆' -> 30406 */ {0x76c8, 0xd3af}, /* '盈' -> 30408 */ {0x76ca, 0xd2e6}, /* '益' -> 30410 */ {0x76cd, 0xeec1}, /* '盍' -> 30413 */ {0x76ce, 0xb0bb}, /* '盎' -> 30414 */ {0x76cf, 0xd5b5}, /* '盏' -> 30415 */ {0x76d0, 0xd1ce}, /* '盐' -> 30416 */ {0x76d1, 0xbce0}, /* '监' -> 30417 */ {0x76d2, 0xbad0}, /* '盒' -> 30418 */ {0x76d4, 0xbff8}, /* '盔' -> 30420 */ {0x76d6, 0xb8c7}, /* '盖' -> 30422 */ {0x76d7, 0xb5c1}, /* '盗' -> 30423 */ {0x76d8, 0xc5cc}, /* '盘' -> 30424 */ {0x76db, 0xcaa2}, /* '盛' -> 30427 */ {0x76df, 0xc3cb}, /* '盟' -> 30431 */ {0x76e5, 0xeec2}, /* '盥' -> 30437 */ {0x76ee, 0xc4bf}, /* '目' -> 30446 */ {0x76ef, 0xb6a2}, /* '盯' -> 30447 */ {0x76f1, 0xedec}, /* '盱' -> 30449 */ {0x76f2, 0xc3a4}, /* '盲' -> 30450 */ {0x76f4, 0xd6b1}, /* '直' -> 30452 */ {0x76f8, 0xcfe0}, /* '相' -> 30456 */ {0x76f9, 0xedef}, /* '盹' -> 30457 */ {0x76fc, 0xc5ce}, /* '盼' -> 30460 */ {0x76fe, 0xb6dc}, /* '盾' -> 30462 */ {0x7701, 0xcaa1}, /* '省' -> 30465 */ {0x7704, 0xeded}, /* '眄' -> 30468 */ {0x7707, 0xedf0}, /* '眇' -> 30471 */ {0x7708, 0xedf1}, /* '眈' -> 30472 */ {0x7709, 0xc3bc}, /* '眉' -> 30473 */ {0x770b, 0xbfb4}, /* '看' -> 30475 */ {0x770d, 0xedee}, /* '眍' -> 30477 */ {0x7719, 0xedf4}, /* '眙' -> 30489 */ {0x771a, 0xedf2}, /* '眚' -> 30490 */ {0x771f, 0xd5e6}, /* '真' -> 30495 */ {0x7720, 0xc3df}, /* '眠' -> 30496 */ {0x7722, 0xedf3}, /* '眢' -> 30498 */ {0x7726, 0xedf6}, /* '眦' -> 30502 */ {0x7728, 0xd5a3}, /* '眨' -> 30504 */ {0x7729, 0xd1a3}, /* '眩' -> 30505 */ {0x772d, 0xedf5}, /* '眭' -> 30509 */ {0x772f, 0xc3d0}, /* '眯' -> 30511 */ {0x7735, 0xedf7}, /* '眵' -> 30517 */ {0x7736, 0xbff4}, /* '眶' -> 30518 */ {0x7737, 0xbeec}, /* '眷' -> 30519 */ {0x7738, 0xedf8}, /* '眸' -> 30520 */ {0x773a, 0xccf7}, /* '眺' -> 30522 */ {0x773c, 0xd1db}, /* '眼' -> 30524 */ {0x7740, 0xd7c5}, /* '着' -> 30528 */ {0x7741, 0xd5f6}, /* '睁' -> 30529 */ {0x7743, 0xedfc}, /* '睃' -> 30531 */ {0x7747, 0xedfb}, /* '睇' -> 30535 */ {0x7750, 0xedf9}, /* '睐' -> 30544 */ {0x7751, 0xedfa}, /* '睑' -> 30545 */ {0x775a, 0xedfd}, /* '睚' -> 30554 */ {0x775b, 0xbea6}, /* '睛' -> 30555 */ {0x7761, 0xcbaf}, /* '睡' -> 30561 */ {0x7762, 0xeea1}, /* '睢' -> 30562 */ {0x7763, 0xb6bd}, /* '督' -> 30563 */ {0x7765, 0xeea2}, /* '睥' -> 30565 */ {0x7766, 0xc4c0}, /* '睦' -> 30566 */ {0x7768, 0xedfe}, /* '睨' -> 30568 */ {0x776b, 0xbdde}, /* '睫' -> 30571 */ {0x776c, 0xb2c7}, /* '睬' -> 30572 */ {0x7779, 0xb6c3}, /* '睹' -> 30585 */ {0x777d, 0xeea5}, /* '睽' -> 30589 */ {0x777e, 0xd8ba}, /* '睾' -> 30590 */ {0x777f, 0xeea3}, /* '睿' -> 30591 */ {0x7780, 0xeea6}, /* '瞀' -> 30592 */ {0x7784, 0xc3e9}, /* '瞄' -> 30596 */ {0x7785, 0xb3f2}, /* '瞅' -> 30597 */ {0x778c, 0xeea7}, /* '瞌' -> 30604 */ {0x778d, 0xeea4}, /* '瞍' -> 30605 */ {0x778e, 0xcfb9}, /* '瞎' -> 30606 */ {0x7791, 0xeea8}, /* '瞑' -> 30609 */ {0x7792, 0xc2f7}, /* '瞒' -> 30610 */ {0x779f, 0xeea9}, /* '瞟' -> 30623 */ {0x77a0, 0xeeaa}, /* '瞠' -> 30624 */ {0x77a2, 0xdeab}, /* '瞢' -> 30626 */ {0x77a5, 0xc6b3}, /* '瞥' -> 30629 */ {0x77a7, 0xc7c6}, /* '瞧' -> 30631 */ {0x77a9, 0xd6f5}, /* '瞩' -> 30633 */ {0x77aa, 0xb5c9}, /* '瞪' -> 30634 */ {0x77ac, 0xcbb2}, /* '瞬' -> 30636 */ {0x77b0, 0xeeab}, /* '瞰' -> 30640 */ {0x77b3, 0xcdab}, /* '瞳' -> 30643 */ {0x77b5, 0xeeac}, /* '瞵' -> 30645 */ {0x77bb, 0xd5b0}, /* '瞻' -> 30651 */ {0x77bd, 0xeead}, /* '瞽' -> 30653 */ {0x77bf, 0xf6c4}, /* '瞿' -> 30655 */ {0x77cd, 0xdbc7}, /* '矍' -> 30669 */ {0x77d7, 0xb4a3}, /* '矗' -> 30679 */ {0x77db, 0xc3ac}, /* '矛' -> 30683 */ {0x77dc, 0xf1e6}, /* '矜' -> 30684 */ {0x77e2, 0xcab8}, /* '矢' -> 30690 */ {0x77e3, 0xd2d3}, /* '矣' -> 30691 */ {0x77e5, 0xd6aa}, /* '知' -> 30693 */ {0x77e7, 0xeff2}, /* '矧' -> 30695 */ {0x77e9, 0xbed8}, /* '矩' -> 30697 */ {0x77eb, 0xbdc3}, /* '矫' -> 30699 */ {0x77ec, 0xeff3}, /* '矬' -> 30700 */ {0x77ed, 0xb6cc}, /* '短' -> 30701 */ {0x77ee, 0xb0ab}, /* '矮' -> 30702 */ {0x77f3, 0xcaaf}, /* '石' -> 30707 */ {0x77f6, 0xedb6}, /* '矶' -> 30710 */ {0x77f8, 0xedb7}, /* '矸' -> 30712 */ {0x77fd, 0xcef9}, /* '矽' -> 30717 */ {0x77fe, 0xb7af}, /* '矾' -> 30718 */ {0x77ff, 0xbff3}, /* '矿' -> 30719 */ {0x7800, 0xedb8}, /* '砀' -> 30720 */ {0x7801, 0xc2eb}, /* '码' -> 30721 */ {0x7802, 0xc9b0}, /* '砂' -> 30722 */ {0x7809, 0xedb9}, /* '砉' -> 30729 */ {0x780c, 0xc6f6}, /* '砌' -> 30732 */ {0x780d, 0xbfb3}, /* '砍' -> 30733 */ {0x7811, 0xedbc}, /* '砑' -> 30737 */ {0x7812, 0xc5f8}, /* '砒' -> 30738 */ {0x7814, 0xd1d0}, /* '研' -> 30740 */ {0x7816, 0xd7a9}, /* '砖' -> 30742 */ {0x7817, 0xedba}, /* '砗' -> 30743 */ {0x7818, 0xedbb}, /* '砘' -> 30744 */ {0x781a, 0xd1e2}, /* '砚' -> 30746 */ {0x781c, 0xedbf}, /* '砜' -> 30748 */ {0x781d, 0xedc0}, /* '砝' -> 30749 */ {0x781f, 0xedc4}, /* '砟' -> 30751 */ {0x7823, 0xedc8}, /* '砣' -> 30755 */ {0x7825, 0xedc6}, /* '砥' -> 30757 */ {0x7826, 0xedce}, /* '砦' -> 30758 */ {0x7827, 0xd5e8}, /* '砧' -> 30759 */ {0x7829, 0xedc9}, /* '砩' -> 30761 */ {0x782c, 0xedc7}, /* '砬' -> 30764 */ {0x782d, 0xedbe}, /* '砭' -> 30765 */ {0x7830, 0xc5e9}, /* '砰' -> 30768 */ {0x7834, 0xc6c6}, /* '破' -> 30772 */ {0x7837, 0xc9e9}, /* '砷' -> 30775 */ {0x7838, 0xd4d2}, /* '砸' -> 30776 */ {0x7839, 0xedc1}, /* '砹' -> 30777 */ {0x783a, 0xedc2}, /* '砺' -> 30778 */ {0x783b, 0xedc3}, /* '砻' -> 30779 */ {0x783c, 0xedc5}, /* '砼' -> 30780 */ {0x783e, 0xc0f9}, /* '砾' -> 30782 */ {0x7840, 0xb4a1}, /* '础' -> 30784 */ {0x7845, 0xb9e8}, /* '硅' -> 30789 */ {0x7847, 0xedd0}, /* '硇' -> 30791 */ {0x784c, 0xedd1}, /* '硌' -> 30796 */ {0x784e, 0xedca}, /* '硎' -> 30798 */ {0x7850, 0xedcf}, /* '硐' -> 30800 */ {0x7852, 0xcef8}, /* '硒' -> 30802 */ {0x7855, 0xcbb6}, /* '硕' -> 30805 */ {0x7856, 0xedcc}, /* '硖' -> 30806 */ {0x7857, 0xedcd}, /* '硗' -> 30807 */ {0x785d, 0xcff5}, /* '硝' -> 30813 */ {0x786a, 0xedd2}, /* '硪' -> 30826 */ {0x786b, 0xc1f2}, /* '硫' -> 30827 */ {0x786c, 0xd3b2}, /* '硬' -> 30828 */ {0x786d, 0xedcb}, /* '硭' -> 30829 */ {0x786e, 0xc8b7}, /* '确' -> 30830 */ {0x7877, 0xbcef}, /* '硷' -> 30839 */ {0x787c, 0xc5f0}, /* '硼' -> 30844 */ {0x7887, 0xedd6}, /* '碇' -> 30855 */ {0x7889, 0xb5ef}, /* '碉' -> 30857 */ {0x788c, 0xc2b5}, /* '碌' -> 30860 */ {0x788d, 0xb0ad}, /* '碍' -> 30861 */ {0x788e, 0xcbe9}, /* '碎' -> 30862 */ {0x7891, 0xb1ae}, /* '碑' -> 30865 */ {0x7893, 0xedd4}, /* '碓' -> 30867 */ {0x7897, 0xcdeb}, /* '碗' -> 30871 */ {0x7898, 0xb5e2}, /* '碘' -> 30872 */ {0x789a, 0xedd5}, /* '碚' -> 30874 */ {0x789b, 0xedd3}, /* '碛' -> 30875 */ {0x789c, 0xedd7}, /* '碜' -> 30876 */ {0x789f, 0xb5fa}, /* '碟' -> 30879 */ {0x78a1, 0xedd8}, /* '碡' -> 30881 */ {0x78a3, 0xedd9}, /* '碣' -> 30883 */ {0x78a5, 0xeddc}, /* '碥' -> 30885 */ {0x78a7, 0xb1cc}, /* '碧' -> 30887 */ {0x78b0, 0xc5f6}, /* '碰' -> 30896 */ {0x78b1, 0xbcee}, /* '碱' -> 30897 */ {0x78b2, 0xedda}, /* '碲' -> 30898 */ {0x78b3, 0xccbc}, /* '碳' -> 30899 */ {0x78b4, 0xb2ea}, /* '碴' -> 30900 */ {0x78b9, 0xeddb}, /* '碹' -> 30905 */ {0x78be, 0xc4eb}, /* '碾' -> 30910 */ {0x78c1, 0xb4c5}, /* '磁' -> 30913 */ {0x78c5, 0xb0f5}, /* '磅' -> 30917 */ {0x78c9, 0xeddf}, /* '磉' -> 30921 */ {0x78ca, 0xc0da}, /* '磊' -> 30922 */ {0x78cb, 0xb4e8}, /* '磋' -> 30923 */ {0x78d0, 0xc5cd}, /* '磐' -> 30928 */ {0x78d4, 0xeddd}, /* '磔' -> 30932 */ {0x78d5, 0xbfc4}, /* '磕' -> 30933 */ {0x78d9, 0xedde}, /* '磙' -> 30937 */ {0x78e8, 0xc4a5}, /* '磨' -> 30952 */ {0x78ec, 0xede0}, /* '磬' -> 30956 */ {0x78f2, 0xede1}, /* '磲' -> 30962 */ {0x78f4, 0xede3}, /* '磴' -> 30964 */ {0x78f7, 0xc1d7}, /* '磷' -> 30967 */ {0x78fa, 0xbbc7}, /* '磺' -> 30970 */ {0x7901, 0xbdb8}, /* '礁' -> 30977 */ {0x7905, 0xede2}, /* '礅' -> 30981 */ {0x7913, 0xede4}, /* '礓' -> 30995 */ {0x791e, 0xede6}, /* '礞' -> 31006 */ {0x7924, 0xede5}, /* '礤' -> 31012 */ {0x7934, 0xede7}, /* '礴' -> 31028 */ {0x793a, 0xcabe}, /* '示' -> 31034 */ {0x793b, 0xecea}, /* '礻' -> 31035 */ {0x793c, 0xc0f1}, /* '礼' -> 31036 */ {0x793e, 0xc9e7}, /* '社' -> 31038 */ {0x7940, 0xeceb}, /* '祀' -> 31040 */ {0x7941, 0xc6ee}, /* '祁' -> 31041 */ {0x7946, 0xecec}, /* '祆' -> 31046 */ {0x7948, 0xc6ed}, /* '祈' -> 31048 */ {0x7949, 0xeced}, /* '祉' -> 31049 */ {0x7953, 0xecf0}, /* '祓' -> 31059 */ {0x7956, 0xd7e6}, /* '祖' -> 31062 */ {0x7957, 0xecf3}, /* '祗' -> 31063 */ {0x795a, 0xecf1}, /* '祚' -> 31066 */ {0x795b, 0xecee}, /* '祛' -> 31067 */ {0x795c, 0xecef}, /* '祜' -> 31068 */ {0x795d, 0xd7a3}, /* '祝' -> 31069 */ {0x795e, 0xc9f1}, /* '神' -> 31070 */ {0x795f, 0xcbee}, /* '祟' -> 31071 */ {0x7960, 0xecf4}, /* '祠' -> 31072 */ {0x7962, 0xecf2}, /* '祢' -> 31074 */ {0x7965, 0xcfe9}, /* '祥' -> 31077 */ {0x7967, 0xecf6}, /* '祧' -> 31079 */ {0x7968, 0xc6b1}, /* '票' -> 31080 */ {0x796d, 0xbcc0}, /* '祭' -> 31085 */ {0x796f, 0xecf5}, /* '祯' -> 31087 */ {0x7977, 0xb5bb}, /* '祷' -> 31095 */ {0x7978, 0xbbf6}, /* '祸' -> 31096 */ {0x797a, 0xecf7}, /* '祺' -> 31098 */ {0x7980, 0xd9f7}, /* '禀' -> 31104 */ {0x7981, 0xbdfb}, /* '禁' -> 31105 */ {0x7984, 0xc2bb}, /* '禄' -> 31108 */ {0x7985, 0xecf8}, /* '禅' -> 31109 */ {0x798a, 0xecf9}, /* '禊' -> 31114 */ {0x798f, 0xb8a3}, /* '福' -> 31119 */ {0x799a, 0xecfa}, /* '禚' -> 31130 */ {0x79a7, 0xecfb}, /* '禧' -> 31143 */ {0x79b3, 0xecfc}, /* '禳' -> 31155 */ {0x79b9, 0xd3ed}, /* '禹' -> 31161 */ {0x79ba, 0xd8ae}, /* '禺' -> 31162 */ {0x79bb, 0xc0eb}, /* '离' -> 31163 */ {0x79bd, 0xc7dd}, /* '禽' -> 31165 */ {0x79be, 0xbacc}, /* '禾' -> 31166 */ {0x79c0, 0xd0e3}, /* '秀' -> 31168 */ {0x79c1, 0xcbbd}, /* '私' -> 31169 */ {0x79c3, 0xcdba}, /* '秃' -> 31171 */ {0x79c6, 0xb8d1}, /* '秆' -> 31174 */ {0x79c9, 0xb1fc}, /* '秉' -> 31177 */ {0x79cb, 0xc7ef}, /* '秋' -> 31179 */ {0x79cd, 0xd6d6}, /* '种' -> 31181 */ {0x79d1, 0xbfc6}, /* '科' -> 31185 */ {0x79d2, 0xc3eb}, /* '秒' -> 31186 */ {0x79d5, 0xeff5}, /* '秕' -> 31189 */ {0x79d8, 0xc3d8}, /* '秘' -> 31192 */ {0x79df, 0xd7e2}, /* '租' -> 31199 */ {0x79e3, 0xeff7}, /* '秣' -> 31203 */ {0x79e4, 0xb3d3}, /* '秤' -> 31204 */ {0x79e6, 0xc7d8}, /* '秦' -> 31206 */ {0x79e7, 0xd1ed}, /* '秧' -> 31207 */ {0x79e9, 0xd6c8}, /* '秩' -> 31209 */ {0x79eb, 0xeff8}, /* '秫' -> 31211 */ {0x79ed, 0xeff6}, /* '秭' -> 31213 */ {0x79ef, 0xbbfd}, /* '积' -> 31215 */ {0x79f0, 0xb3c6}, /* '称' -> 31216 */ {0x79f8, 0xbdd5}, /* '秸' -> 31224 */ {0x79fb, 0xd2c6}, /* '移' -> 31227 */ {0x79fd, 0xbbe0}, /* '秽' -> 31229 */ {0x7a00, 0xcfa1}, /* '稀' -> 31232 */ {0x7a02, 0xeffc}, /* '稂' -> 31234 */ {0x7a03, 0xeffb}, /* '稃' -> 31235 */ {0x7a06, 0xeff9}, /* '稆' -> 31238 */ {0x7a0b, 0xb3cc}, /* '程' -> 31243 */ {0x7a0d, 0xc9d4}, /* '稍' -> 31245 */ {0x7a0e, 0xcbb0}, /* '税' -> 31246 */ {0x7a14, 0xeffe}, /* '稔' -> 31252 */ {0x7a17, 0xb0de}, /* '稗' -> 31255 */ {0x7a1a, 0xd6c9}, /* '稚' -> 31258 */ {0x7a1e, 0xeffd}, /* '稞' -> 31262 */ {0x7a20, 0xb3ed}, /* '稠' -> 31264 */ {0x7a23, 0xf6d5}, /* '稣' -> 31267 */ {0x7a33, 0xcec8}, /* '稳' -> 31283 */ {0x7a37, 0xf0a2}, /* '稷' -> 31287 */ {0x7a39, 0xf0a1}, /* '稹' -> 31289 */ {0x7a3b, 0xb5be}, /* '稻' -> 31291 */ {0x7a3c, 0xbcda}, /* '稼' -> 31292 */ {0x7a3d, 0xbbfc}, /* '稽' -> 31293 */ {0x7a3f, 0xb8e5}, /* '稿' -> 31295 */ {0x7a46, 0xc4c2}, /* '穆' -> 31302 */ {0x7a51, 0xf0a3}, /* '穑' -> 31313 */ {0x7a57, 0xcbeb}, /* '穗' -> 31319 */ {0x7a70, 0xf0a6}, /* '穰' -> 31344 */ {0x7a74, 0xd1a8}, /* '穴' -> 31348 */ {0x7a76, 0xbebf}, /* '究' -> 31350 */ {0x7a77, 0xc7ee}, /* '穷' -> 31351 */ {0x7a78, 0xf1b6}, /* '穸' -> 31352 */ {0x7a79, 0xf1b7}, /* '穹' -> 31353 */ {0x7a7a, 0xbfd5}, /* '空' -> 31354 */ {0x7a7f, 0xb4a9}, /* '穿' -> 31359 */ {0x7a80, 0xf1b8}, /* '窀' -> 31360 */ {0x7a81, 0xcdbb}, /* '突' -> 31361 */ {0x7a83, 0xc7d4}, /* '窃' -> 31363 */ {0x7a84, 0xd5ad}, /* '窄' -> 31364 */ {0x7a86, 0xf1b9}, /* '窆' -> 31366 */ {0x7a88, 0xf1ba}, /* '窈' -> 31368 */ {0x7a8d, 0xc7cf}, /* '窍' -> 31373 */ {0x7a91, 0xd2a4}, /* '窑' -> 31377 */ {0x7a92, 0xd6cf}, /* '窒' -> 31378 */ {0x7a95, 0xf1bb}, /* '窕' -> 31381 */ {0x7a96, 0xbdd1}, /* '窖' -> 31382 */ {0x7a97, 0xb4b0}, /* '窗' -> 31383 */ {0x7a98, 0xbebd}, /* '窘' -> 31384 */ {0x7a9c, 0xb4dc}, /* '窜' -> 31388 */ {0x7a9d, 0xced1}, /* '窝' -> 31389 */ {0x7a9f, 0xbfdf}, /* '窟' -> 31391 */ {0x7aa0, 0xf1bd}, /* '窠' -> 31392 */ {0x7aa5, 0xbffa}, /* '窥' -> 31397 */ {0x7aa6, 0xf1bc}, /* '窦' -> 31398 */ {0x7aa8, 0xf1bf}, /* '窨' -> 31400 */ {0x7aac, 0xf1be}, /* '窬' -> 31404 */ {0x7aad, 0xf1c0}, /* '窭' -> 31405 */ {0x7ab3, 0xf1c1}, /* '窳' -> 31411 */ {0x7abf, 0xc1fe}, /* '窿' -> 31423 */ {0x7acb, 0xc1a2}, /* '立' -> 31435 */ {0x7ad6, 0xcafa}, /* '竖' -> 31446 */ {0x7ad9, 0xd5be}, /* '站' -> 31449 */ {0x7ade, 0xbeba}, /* '竞' -> 31454 */ {0x7adf, 0xbeb9}, /* '竟' -> 31455 */ {0x7ae0, 0xd5c2}, /* '章' -> 31456 */ {0x7ae3, 0xbfa2}, /* '竣' -> 31459 */ {0x7ae5, 0xcdaf}, /* '童' -> 31461 */ {0x7ae6, 0xf1b5}, /* '竦' -> 31462 */ {0x7aed, 0xbddf}, /* '竭' -> 31469 */ {0x7aef, 0xb6cb}, /* '端' -> 31471 */ {0x7af9, 0xd6f1}, /* '竹' -> 31481 */ {0x7afa, 0xf3c3}, /* '竺' -> 31482 */ {0x7afd, 0xf3c4}, /* '竽' -> 31485 */ {0x7aff, 0xb8cd}, /* '竿' -> 31487 */ {0x7b03, 0xf3c6}, /* '笃' -> 31491 */ {0x7b04, 0xf3c7}, /* '笄' -> 31492 */ {0x7b06, 0xb0ca}, /* '笆' -> 31494 */ {0x7b08, 0xf3c5}, /* '笈' -> 31496 */ {0x7b0a, 0xf3c9}, /* '笊' -> 31498 */ {0x7b0b, 0xcbf1}, /* '笋' -> 31499 */ {0x7b0f, 0xf3cb}, /* '笏' -> 31503 */ {0x7b11, 0xd0a6}, /* '笑' -> 31505 */ {0x7b14, 0xb1ca}, /* '笔' -> 31508 */ {0x7b15, 0xf3c8}, /* '笕' -> 31509 */ {0x7b19, 0xf3cf}, /* '笙' -> 31513 */ {0x7b1b, 0xb5d1}, /* '笛' -> 31515 */ {0x7b1e, 0xf3d7}, /* '笞' -> 31518 */ {0x7b20, 0xf3d2}, /* '笠' -> 31520 */ {0x7b24, 0xf3d4}, /* '笤' -> 31524 */ {0x7b25, 0xf3d3}, /* '笥' -> 31525 */ {0x7b26, 0xb7fb}, /* '符' -> 31526 */ {0x7b28, 0xb1bf}, /* '笨' -> 31528 */ {0x7b2a, 0xf3ce}, /* '笪' -> 31530 */ {0x7b2b, 0xf3ca}, /* '笫' -> 31531 */ {0x7b2c, 0xb5da}, /* '第' -> 31532 */ {0x7b2e, 0xf3d0}, /* '笮' -> 31534 */ {0x7b31, 0xf3d1}, /* '笱' -> 31537 */ {0x7b33, 0xf3d5}, /* '笳' -> 31539 */ {0x7b38, 0xf3cd}, /* '笸' -> 31544 */ {0x7b3a, 0xbce3}, /* '笺' -> 31546 */ {0x7b3c, 0xc1fd}, /* '笼' -> 31548 */ {0x7b3e, 0xf3d6}, /* '笾' -> 31550 */ {0x7b45, 0xf3da}, /* '筅' -> 31557 */ {0x7b47, 0xf3cc}, /* '筇' -> 31559 */ {0x7b49, 0xb5c8}, /* '等' -> 31561 */ {0x7b4b, 0xbdee}, /* '筋' -> 31563 */ {0x7b4c, 0xf3dc}, /* '筌' -> 31564 */ {0x7b4f, 0xb7a4}, /* '筏' -> 31567 */ {0x7b50, 0xbff0}, /* '筐' -> 31568 */ {0x7b51, 0xd6fe}, /* '筑' -> 31569 */ {0x7b52, 0xcdb2}, /* '筒' -> 31570 */ {0x7b54, 0xb4f0}, /* '答' -> 31572 */ {0x7b56, 0xb2df}, /* '策' -> 31574 */ {0x7b58, 0xf3d8}, /* '筘' -> 31576 */ {0x7b5a, 0xf3d9}, /* '筚' -> 31578 */ {0x7b5b, 0xc9b8}, /* '筛' -> 31579 */ {0x7b5d, 0xf3dd}, /* '筝' -> 31581 */ {0x7b60, 0xf3de}, /* '筠' -> 31584 */ {0x7b62, 0xf3e1}, /* '筢' -> 31586 */ {0x7b6e, 0xf3df}, /* '筮' -> 31598 */ {0x7b71, 0xf3e3}, /* '筱' -> 31601 */ {0x7b72, 0xf3e2}, /* '筲' -> 31602 */ {0x7b75, 0xf3db}, /* '筵' -> 31605 */ {0x7b77, 0xbfea}, /* '筷' -> 31607 */ {0x7b79, 0xb3ef}, /* '筹' -> 31609 */ {0x7b7b, 0xf3e0}, /* '筻' -> 31611 */ {0x7b7e, 0xc7a9}, /* '签' -> 31614 */ {0x7b80, 0xbcf2}, /* '简' -> 31616 */ {0x7b85, 0xf3eb}, /* '箅' -> 31621 */ {0x7b8d, 0xb9bf}, /* '箍' -> 31629 */ {0x7b90, 0xf3e4}, /* '箐' -> 31632 */ {0x7b94, 0xb2ad}, /* '箔' -> 31636 */ {0x7b95, 0xbbfe}, /* '箕' -> 31637 */ {0x7b97, 0xcbe3}, /* '算' -> 31639 */ {0x7b9c, 0xf3ed}, /* '箜' -> 31644 */ {0x7b9d, 0xf3e9}, /* '箝' -> 31645 */ {0x7ba1, 0xb9dc}, /* '管' -> 31649 */ {0x7ba2, 0xf3ee}, /* '箢' -> 31650 */ {0x7ba6, 0xf3e5}, /* '箦' -> 31654 */ {0x7ba7, 0xf3e6}, /* '箧' -> 31655 */ {0x7ba8, 0xf3ea}, /* '箨' -> 31656 */ {0x7ba9, 0xc2e1}, /* '箩' -> 31657 */ {0x7baa, 0xf3ec}, /* '箪' -> 31658 */ {0x7bab, 0xf3ef}, /* '箫' -> 31659 */ {0x7bac, 0xf3e8}, /* '箬' -> 31660 */ {0x7bad, 0xbcfd}, /* '箭' -> 31661 */ {0x7bb1, 0xcfe4}, /* '箱' -> 31665 */ {0x7bb4, 0xf3f0}, /* '箴' -> 31668 */ {0x7bb8, 0xf3e7}, /* '箸' -> 31672 */ {0x7bc1, 0xf3f2}, /* '篁' -> 31681 */ {0x7bc6, 0xd7ad}, /* '篆' -> 31686 */ {0x7bc7, 0xc6aa}, /* '篇' -> 31687 */ {0x7bcc, 0xf3f3}, /* '篌' -> 31692 */ {0x7bd1, 0xf3f1}, /* '篑' -> 31697 */ {0x7bd3, 0xc2a8}, /* '篓' -> 31699 */ {0x7bd9, 0xb8dd}, /* '篙' -> 31705 */ {0x7bda, 0xf3f5}, /* '篚' -> 31706 */ {0x7bdd, 0xf3f4}, /* '篝' -> 31709 */ {0x7be1, 0xb4db}, /* '篡' -> 31713 */ {0x7be5, 0xf3f6}, /* '篥' -> 31717 */ {0x7be6, 0xf3f7}, /* '篦' -> 31718 */ {0x7bea, 0xf3f8}, /* '篪' -> 31722 */ {0x7bee, 0xc0ba}, /* '篮' -> 31726 */ {0x7bf1, 0xc0e9}, /* '篱' -> 31729 */ {0x7bf7, 0xc5f1}, /* '篷' -> 31735 */ {0x7bfc, 0xf3fb}, /* '篼' -> 31740 */ {0x7bfe, 0xf3fa}, /* '篾' -> 31742 */ {0x7c07, 0xb4d8}, /* '簇' -> 31751 */ {0x7c0b, 0xf3fe}, /* '簋' -> 31755 */ {0x7c0c, 0xf3f9}, /* '簌' -> 31756 */ {0x7c0f, 0xf3fc}, /* '簏' -> 31759 */ {0x7c16, 0xf3fd}, /* '簖' -> 31766 */ {0x7c1f, 0xf4a1}, /* '簟' -> 31775 */ {0x7c26, 0xf4a3}, /* '簦' -> 31782 */ {0x7c27, 0xbbc9}, /* '簧' -> 31783 */ {0x7c2a, 0xf4a2}, /* '簪' -> 31786 */ {0x7c38, 0xf4a4}, /* '簸' -> 31800 */ {0x7c3f, 0xb2be}, /* '簿' -> 31807 */ {0x7c40, 0xf4a6}, /* '籀' -> 31808 */ {0x7c41, 0xf4a5}, /* '籁' -> 31809 */ {0x7c4d, 0xbcae}, /* '籍' -> 31821 */ {0x7c73, 0xc3d7}, /* '米' -> 31859 */ {0x7c74, 0xd9e1}, /* '籴' -> 31860 */ {0x7c7b, 0xc0e0}, /* '类' -> 31867 */ {0x7c7c, 0xf4cc}, /* '籼' -> 31868 */ {0x7c7d, 0xd7d1}, /* '籽' -> 31869 */ {0x7c89, 0xb7db}, /* '粉' -> 31881 */ {0x7c91, 0xf4ce}, /* '粑' -> 31889 */ {0x7c92, 0xc1a3}, /* '粒' -> 31890 */ {0x7c95, 0xc6c9}, /* '粕' -> 31893 */ {0x7c97, 0xb4d6}, /* '粗' -> 31895 */ {0x7c98, 0xd5b3}, /* '粘' -> 31896 */ {0x7c9c, 0xf4d0}, /* '粜' -> 31900 */ {0x7c9d, 0xf4cf}, /* '粝' -> 31901 */ {0x7c9e, 0xf4d1}, /* '粞' -> 31902 */ {0x7c9f, 0xcbda}, /* '粟' -> 31903 */ {0x7ca2, 0xf4d2}, /* '粢' -> 31906 */ {0x7ca4, 0xd4c1}, /* '粤' -> 31908 */ {0x7ca5, 0xd6e0}, /* '粥' -> 31909 */ {0x7caa, 0xb7e0}, /* '粪' -> 31914 */ {0x7cae, 0xc1b8}, /* '粮' -> 31918 */ {0x7cb1, 0xc1bb}, /* '粱' -> 31921 */ {0x7cb2, 0xf4d3}, /* '粲' -> 31922 */ {0x7cb3, 0xbeac}, /* '粳' -> 31923 */ {0x7cb9, 0xb4e2}, /* '粹' -> 31929 */ {0x7cbc, 0xf4d4}, /* '粼' -> 31932 */ {0x7cbd, 0xf4d5}, /* '粽' -> 31933 */ {0x7cbe, 0xbeab}, /* '精' -> 31934 */ {0x7cc1, 0xf4d6}, /* '糁' -> 31937 */ {0x7cc5, 0xf4db}, /* '糅' -> 31941 */ {0x7cc7, 0xf4d7}, /* '糇' -> 31943 */ {0x7cc8, 0xf4da}, /* '糈' -> 31944 */ {0x7cca, 0xbafd}, /* '糊' -> 31946 */ {0x7ccc, 0xf4d8}, /* '糌' -> 31948 */ {0x7ccd, 0xf4d9}, /* '糍' -> 31949 */ {0x7cd5, 0xb8e2}, /* '糕' -> 31957 */ {0x7cd6, 0xccc7}, /* '糖' -> 31958 */ {0x7cd7, 0xf4dc}, /* '糗' -> 31959 */ {0x7cd9, 0xb2da}, /* '糙' -> 31961 */ {0x7cdc, 0xc3d3}, /* '糜' -> 31964 */ {0x7cdf, 0xd4e3}, /* '糟' -> 31967 */ {0x7ce0, 0xbfb7}, /* '糠' -> 31968 */ {0x7ce8, 0xf4dd}, /* '糨' -> 31976 */ {0x7cef, 0xc5b4}, /* '糯' -> 31983 */ {0x7cf8, 0xf4e9}, /* '糸' -> 31992 */ {0x7cfb, 0xcfb5}, /* '系' -> 31995 */ {0x7d0a, 0xcec9}, /* '紊' -> 32010 */ {0x7d20, 0xcbd8}, /* '素' -> 32032 */ {0x7d22, 0xcbf7}, /* '索' -> 32034 */ {0x7d27, 0xbdf4}, /* '紧' -> 32039 */ {0x7d2b, 0xd7cf}, /* '紫' -> 32043 */ {0x7d2f, 0xc0db}, /* '累' -> 32047 */ {0x7d6e, 0xd0f5}, /* '絮' -> 32110 */ {0x7d77, 0xf4ea}, /* '絷' -> 32119 */ {0x7da6, 0xf4eb}, /* '綦' -> 32166 */ {0x7dae, 0xf4ec}, /* '綮' -> 32174 */ {0x7e3b, 0xf7e3}, /* '縻' -> 32315 */ {0x7e41, 0xb7b1}, /* '繁' -> 32321 */ {0x7e47, 0xf4ed}, /* '繇' -> 32327 */ {0x7e82, 0xd7eb}, /* '纂' -> 32386 */ {0x7e9b, 0xf4ee}, /* '纛' -> 32411 */ {0x7e9f, 0xe6f9}, /* '纟' -> 32415 */ {0x7ea0, 0xbec0}, /* '纠' -> 32416 */ {0x7ea1, 0xe6fa}, /* '纡' -> 32417 */ {0x7ea2, 0xbaec}, /* '红' -> 32418 */ {0x7ea3, 0xe6fb}, /* '纣' -> 32419 */ {0x7ea4, 0xcfcb}, /* '纤' -> 32420 */ {0x7ea5, 0xe6fc}, /* '纥' -> 32421 */ {0x7ea6, 0xd4bc}, /* '约' -> 32422 */ {0x7ea7, 0xbcb6}, /* '级' -> 32423 */ {0x7ea8, 0xe6fd}, /* '纨' -> 32424 */ {0x7ea9, 0xe6fe}, /* '纩' -> 32425 */ {0x7eaa, 0xbccd}, /* '纪' -> 32426 */ {0x7eab, 0xc8d2}, /* '纫' -> 32427 */ {0x7eac, 0xceb3}, /* '纬' -> 32428 */ {0x7ead, 0xe7a1}, /* '纭' -> 32429 */ {0x7eaf, 0xb4bf}, /* '纯' -> 32431 */ {0x7eb0, 0xe7a2}, /* '纰' -> 32432 */ {0x7eb1, 0xc9b4}, /* '纱' -> 32433 */ {0x7eb2, 0xb8d9}, /* '纲' -> 32434 */ {0x7eb3, 0xc4c9}, /* '纳' -> 32435 */ {0x7eb5, 0xd7dd}, /* '纵' -> 32437 */ {0x7eb6, 0xc2da}, /* '纶' -> 32438 */ {0x7eb7, 0xb7d7}, /* '纷' -> 32439 */ {0x7eb8, 0xd6bd}, /* '纸' -> 32440 */ {0x7eb9, 0xcec6}, /* '纹' -> 32441 */ {0x7eba, 0xb7c4}, /* '纺' -> 32442 */ {0x7ebd, 0xc5a6}, /* '纽' -> 32445 */ {0x7ebe, 0xe7a3}, /* '纾' -> 32446 */ {0x7ebf, 0xcfdf}, /* '线' -> 32447 */ {0x7ec0, 0xe7a4}, /* '绀' -> 32448 */ {0x7ec1, 0xe7a5}, /* '绁' -> 32449 */ {0x7ec2, 0xe7a6}, /* '绂' -> 32450 */ {0x7ec3, 0xc1b7}, /* '练' -> 32451 */ {0x7ec4, 0xd7e9}, /* '组' -> 32452 */ {0x7ec5, 0xc9f0}, /* '绅' -> 32453 */ {0x7ec6, 0xcfb8}, /* '细' -> 32454 */ {0x7ec7, 0xd6af}, /* '织' -> 32455 */ {0x7ec8, 0xd6d5}, /* '终' -> 32456 */ {0x7ec9, 0xe7a7}, /* '绉' -> 32457 */ {0x7eca, 0xb0ed}, /* '绊' -> 32458 */ {0x7ecb, 0xe7a8}, /* '绋' -> 32459 */ {0x7ecc, 0xe7a9}, /* '绌' -> 32460 */ {0x7ecd, 0xc9dc}, /* '绍' -> 32461 */ {0x7ece, 0xd2ef}, /* '绎' -> 32462 */ {0x7ecf, 0xbead}, /* '经' -> 32463 */ {0x7ed0, 0xe7aa}, /* '绐' -> 32464 */ {0x7ed1, 0xb0f3}, /* '绑' -> 32465 */ {0x7ed2, 0xc8de}, /* '绒' -> 32466 */ {0x7ed3, 0xbde1}, /* '结' -> 32467 */ {0x7ed4, 0xe7ab}, /* '绔' -> 32468 */ {0x7ed5, 0xc8c6}, /* '绕' -> 32469 */ {0x7ed7, 0xe7ac}, /* '绗' -> 32471 */ {0x7ed8, 0xbbe6}, /* '绘' -> 32472 */ {0x7ed9, 0xb8f8}, /* '给' -> 32473 */ {0x7eda, 0xd1a4}, /* '绚' -> 32474 */ {0x7edb, 0xe7ad}, /* '绛' -> 32475 */ {0x7edc, 0xc2e7}, /* '络' -> 32476 */ {0x7edd, 0xbef8}, /* '绝' -> 32477 */ {0x7ede, 0xbdca}, /* '绞' -> 32478 */ {0x7edf, 0xcdb3}, /* '统' -> 32479 */ {0x7ee0, 0xe7ae}, /* '绠' -> 32480 */ {0x7ee1, 0xe7af}, /* '绡' -> 32481 */ {0x7ee2, 0xbeee}, /* '绢' -> 32482 */ {0x7ee3, 0xd0e5}, /* '绣' -> 32483 */ {0x7ee5, 0xcbe7}, /* '绥' -> 32485 */ {0x7ee6, 0xccd0}, /* '绦' -> 32486 */ {0x7ee7, 0xbccc}, /* '继' -> 32487 */ {0x7ee8, 0xe7b0}, /* '绨' -> 32488 */ {0x7ee9, 0xbca8}, /* '绩' -> 32489 */ {0x7eea, 0xd0f7}, /* '绪' -> 32490 */ {0x7eeb, 0xe7b1}, /* '绫' -> 32491 */ {0x7eed, 0xd0f8}, /* '续' -> 32493 */ {0x7eee, 0xe7b2}, /* '绮' -> 32494 */ {0x7eef, 0xe7b3}, /* '绯' -> 32495 */ {0x7ef0, 0xb4c2}, /* '绰' -> 32496 */ {0x7ef1, 0xe7b4}, /* '绱' -> 32497 */ {0x7ef2, 0xe7b5}, /* '绲' -> 32498 */ {0x7ef3, 0xc9fe}, /* '绳' -> 32499 */ {0x7ef4, 0xceac}, /* '维' -> 32500 */ {0x7ef5, 0xc3e0}, /* '绵' -> 32501 */ {0x7ef6, 0xe7b7}, /* '绶' -> 32502 */ {0x7ef7, 0xb1c1}, /* '绷' -> 32503 */ {0x7ef8, 0xb3f1}, /* '绸' -> 32504 */ {0x7efa, 0xe7b8}, /* '绺' -> 32506 */ {0x7efb, 0xe7b9}, /* '绻' -> 32507 */ {0x7efc, 0xd7db}, /* '综' -> 32508 */ {0x7efd, 0xd5c0}, /* '绽' -> 32509 */ {0x7efe, 0xe7ba}, /* '绾' -> 32510 */ {0x7eff, 0xc2cc}, /* '绿' -> 32511 */ {0x7f00, 0xd7ba}, /* '缀' -> 32512 */ {0x7f01, 0xe7bb}, /* '缁' -> 32513 */ {0x7f02, 0xe7bc}, /* '缂' -> 32514 */ {0x7f03, 0xe7bd}, /* '缃' -> 32515 */ {0x7f04, 0xbcea}, /* '缄' -> 32516 */ {0x7f05, 0xc3e5}, /* '缅' -> 32517 */ {0x7f06, 0xc0c2}, /* '缆' -> 32518 */ {0x7f07, 0xe7be}, /* '缇' -> 32519 */ {0x7f08, 0xe7bf}, /* '缈' -> 32520 */ {0x7f09, 0xbca9}, /* '缉' -> 32521 */ {0x7f0b, 0xe7c0}, /* '缋' -> 32523 */ {0x7f0c, 0xe7c1}, /* '缌' -> 32524 */ {0x7f0d, 0xe7b6}, /* '缍' -> 32525 */ {0x7f0e, 0xb6d0}, /* '缎' -> 32526 */ {0x7f0f, 0xe7c2}, /* '缏' -> 32527 */ {0x7f11, 0xe7c3}, /* '缑' -> 32529 */ {0x7f12, 0xe7c4}, /* '缒' -> 32530 */ {0x7f13, 0xbbba}, /* '缓' -> 32531 */ {0x7f14, 0xb5de}, /* '缔' -> 32532 */ {0x7f15, 0xc2c6}, /* '缕' -> 32533 */ {0x7f16, 0xb1e0}, /* '编' -> 32534 */ {0x7f17, 0xe7c5}, /* '缗' -> 32535 */ {0x7f18, 0xd4b5}, /* '缘' -> 32536 */ {0x7f19, 0xe7c6}, /* '缙' -> 32537 */ {0x7f1a, 0xb8bf}, /* '缚' -> 32538 */ {0x7f1b, 0xe7c8}, /* '缛' -> 32539 */ {0x7f1c, 0xe7c7}, /* '缜' -> 32540 */ {0x7f1d, 0xb7ec}, /* '缝' -> 32541 */ {0x7f1f, 0xe7c9}, /* '缟' -> 32543 */ {0x7f20, 0xb2f8}, /* '缠' -> 32544 */ {0x7f21, 0xe7ca}, /* '缡' -> 32545 */ {0x7f22, 0xe7cb}, /* '缢' -> 32546 */ {0x7f23, 0xe7cc}, /* '缣' -> 32547 */ {0x7f24, 0xe7cd}, /* '缤' -> 32548 */ {0x7f25, 0xe7ce}, /* '缥' -> 32549 */ {0x7f26, 0xe7cf}, /* '缦' -> 32550 */ {0x7f27, 0xe7d0}, /* '缧' -> 32551 */ {0x7f28, 0xd3a7}, /* '缨' -> 32552 */ {0x7f29, 0xcbf5}, /* '缩' -> 32553 */ {0x7f2a, 0xe7d1}, /* '缪' -> 32554 */ {0x7f2b, 0xe7d2}, /* '缫' -> 32555 */ {0x7f2c, 0xe7d3}, /* '缬' -> 32556 */ {0x7f2d, 0xe7d4}, /* '缭' -> 32557 */ {0x7f2e, 0xc9c9}, /* '缮' -> 32558 */ {0x7f2f, 0xe7d5}, /* '缯' -> 32559 */ {0x7f30, 0xe7d6}, /* '缰' -> 32560 */ {0x7f31, 0xe7d7}, /* '缱' -> 32561 */ {0x7f32, 0xe7d8}, /* '缲' -> 32562 */ {0x7f33, 0xe7d9}, /* '缳' -> 32563 */ {0x7f34, 0xbdc9}, /* '缴' -> 32564 */ {0x7f35, 0xe7da}, /* '缵' -> 32565 */ {0x7f36, 0xf3be}, /* '缶' -> 32566 */ {0x7f38, 0xb8d7}, /* '缸' -> 32568 */ {0x7f3a, 0xc8b1}, /* '缺' -> 32570 */ {0x7f42, 0xf3bf}, /* '罂' -> 32578 */ {0x7f44, 0xf3c0}, /* '罄' -> 32580 */ {0x7f45, 0xf3c1}, /* '罅' -> 32581 */ {0x7f50, 0xb9de}, /* '罐' -> 32592 */ {0x7f51, 0xcdf8}, /* '网' -> 32593 */ {0x7f54, 0xd8e8}, /* '罔' -> 32596 */ {0x7f55, 0xbab1}, /* '罕' -> 32597 */ {0x7f57, 0xc2de}, /* '罗' -> 32599 */ {0x7f58, 0xeeb7}, /* '罘' -> 32600 */ {0x7f5a, 0xb7a3}, /* '罚' -> 32602 */ {0x7f5f, 0xeeb9}, /* '罟' -> 32607 */ {0x7f61, 0xeeb8}, /* '罡' -> 32609 */ {0x7f62, 0xb0d5}, /* '罢' -> 32610 */ {0x7f68, 0xeebb}, /* '罨' -> 32616 */ {0x7f69, 0xd5d6}, /* '罩' -> 32617 */ {0x7f6a, 0xd7ef}, /* '罪' -> 32618 */ {0x7f6e, 0xd6c3}, /* '置' -> 32622 */ {0x7f71, 0xeebd}, /* '罱' -> 32625 */ {0x7f72, 0xcaf0}, /* '署' -> 32626 */ {0x7f74, 0xeebc}, /* '罴' -> 32628 */ {0x7f79, 0xeebe}, /* '罹' -> 32633 */ {0x7f7e, 0xeec0}, /* '罾' -> 32638 */ {0x7f81, 0xeebf}, /* '羁' -> 32641 */ {0x7f8a, 0xd1f2}, /* '羊' -> 32650 */ {0x7f8c, 0xc7bc}, /* '羌' -> 32652 */ {0x7f8e, 0xc3c0}, /* '美' -> 32654 */ {0x7f94, 0xb8e1}, /* '羔' -> 32660 */ {0x7f9a, 0xc1e7}, /* '羚' -> 32666 */ {0x7f9d, 0xf4c6}, /* '羝' -> 32669 */ {0x7f9e, 0xd0df}, /* '羞' -> 32670 */ {0x7f9f, 0xf4c7}, /* '羟' -> 32671 */ {0x7fa1, 0xcfdb}, /* '羡' -> 32673 */ {0x7fa4, 0xc8ba}, /* '群' -> 32676 */ {0x7fa7, 0xf4c8}, /* '羧' -> 32679 */ {0x7faf, 0xf4c9}, /* '羯' -> 32687 */ {0x7fb0, 0xf4ca}, /* '羰' -> 32688 */ {0x7fb2, 0xf4cb}, /* '羲' -> 32690 */ {0x7fb8, 0xd9fa}, /* '羸' -> 32696 */ {0x7fb9, 0xb8fe}, /* '羹' -> 32697 */ {0x7fbc, 0xe5f1}, /* '羼' -> 32700 */ {0x7fbd, 0xd3f0}, /* '羽' -> 32701 */ {0x7fbf, 0xf4e0}, /* '羿' -> 32703 */ {0x7fc1, 0xcecc}, /* '翁' -> 32705 */ {0x7fc5, 0xb3e1}, /* '翅' -> 32709 */ {0x7fca, 0xf1b4}, /* '翊' -> 32714 */ {0x7fcc, 0xd2ee}, /* '翌' -> 32716 */ {0x7fce, 0xf4e1}, /* '翎' -> 32718 */ {0x7fd4, 0xcfe8}, /* '翔' -> 32724 */ {0x7fd5, 0xf4e2}, /* '翕' -> 32725 */ {0x7fd8, 0xc7cc}, /* '翘' -> 32728 */ {0x7fdf, 0xb5d4}, /* '翟' -> 32735 */ {0x7fe0, 0xb4e4}, /* '翠' -> 32736 */ {0x7fe1, 0xf4e4}, /* '翡' -> 32737 */ {0x7fe5, 0xf4e3}, /* '翥' -> 32741 */ {0x7fe6, 0xf4e5}, /* '翦' -> 32742 */ {0x7fe9, 0xf4e6}, /* '翩' -> 32745 */ {0x7fee, 0xf4e7}, /* '翮' -> 32750 */ {0x7ff0, 0xbab2}, /* '翰' -> 32752 */ {0x7ff1, 0xb0bf}, /* '翱' -> 32753 */ {0x7ff3, 0xf4e8}, /* '翳' -> 32755 */ {0x7ffb, 0xb7ad}, /* '翻' -> 32763 */ {0x7ffc, 0xd2ed}, /* '翼' -> 32764 */ {0x8000, 0xd2ab}, /* '耀' -> 32768 */ {0x8001, 0xc0cf}, /* '老' -> 32769 */ {0x8003, 0xbfbc}, /* '考' -> 32771 */ {0x8004, 0xeba3}, /* '耄' -> 32772 */ {0x8005, 0xd5df}, /* '者' -> 32773 */ {0x8006, 0xeac8}, /* '耆' -> 32774 */ {0x800b, 0xf1f3}, /* '耋' -> 32779 */ {0x800c, 0xb6f8}, /* '而' -> 32780 */ {0x800d, 0xcba3}, /* '耍' -> 32781 */ {0x8010, 0xc4cd}, /* '耐' -> 32784 */ {0x8012, 0xf1e7}, /* '耒' -> 32786 */ {0x8014, 0xf1e8}, /* '耔' -> 32788 */ {0x8015, 0xb8fb}, /* '耕' -> 32789 */ {0x8016, 0xf1e9}, /* '耖' -> 32790 */ {0x8017, 0xbac4}, /* '耗' -> 32791 */ {0x8018, 0xd4c5}, /* '耘' -> 32792 */ {0x8019, 0xb0d2}, /* '耙' -> 32793 */ {0x801c, 0xf1ea}, /* '耜' -> 32796 */ {0x8020, 0xf1eb}, /* '耠' -> 32800 */ {0x8022, 0xf1ec}, /* '耢' -> 32802 */ {0x8025, 0xf1ed}, /* '耥' -> 32805 */ {0x8026, 0xf1ee}, /* '耦' -> 32806 */ {0x8027, 0xf1ef}, /* '耧' -> 32807 */ {0x8028, 0xf1f1}, /* '耨' -> 32808 */ {0x8029, 0xf1f0}, /* '耩' -> 32809 */ {0x802a, 0xc5d5}, /* '耪' -> 32810 */ {0x8031, 0xf1f2}, /* '耱' -> 32817 */ {0x8033, 0xb6fa}, /* '耳' -> 32819 */ {0x8035, 0xf1f4}, /* '耵' -> 32821 */ {0x8036, 0xd2ae}, /* '耶' -> 32822 */ {0x8037, 0xdec7}, /* '耷' -> 32823 */ {0x8038, 0xcbca}, /* '耸' -> 32824 */ {0x803b, 0xb3dc}, /* '耻' -> 32827 */ {0x803d, 0xb5a2}, /* '耽' -> 32829 */ {0x803f, 0xb9a2}, /* '耿' -> 32831 */ {0x8042, 0xc4f4}, /* '聂' -> 32834 */ {0x8043, 0xf1f5}, /* '聃' -> 32835 */ {0x8046, 0xf1f6}, /* '聆' -> 32838 */ {0x804a, 0xc1c4}, /* '聊' -> 32842 */ {0x804b, 0xc1fb}, /* '聋' -> 32843 */ {0x804c, 0xd6b0}, /* '职' -> 32844 */ {0x804d, 0xf1f7}, /* '聍' -> 32845 */ {0x8052, 0xf1f8}, /* '聒' -> 32850 */ {0x8054, 0xc1aa}, /* '联' -> 32852 */ {0x8058, 0xc6b8}, /* '聘' -> 32856 */ {0x805a, 0xbedb}, /* '聚' -> 32858 */ {0x8069, 0xf1f9}, /* '聩' -> 32873 */ {0x806a, 0xb4cf}, /* '聪' -> 32874 */ {0x8071, 0xf1fa}, /* '聱' -> 32881 */ {0x807f, 0xedb2}, /* '聿' -> 32895 */ {0x8080, 0xedb1}, /* '肀' -> 32896 */ {0x8083, 0xcbe0}, /* '肃' -> 32899 */ {0x8084, 0xd2de}, /* '肄' -> 32900 */ {0x8086, 0xcbc1}, /* '肆' -> 32902 */ {0x8087, 0xd5d8}, /* '肇' -> 32903 */ {0x8089, 0xc8e2}, /* '肉' -> 32905 */ {0x808b, 0xc0df}, /* '肋' -> 32907 */ {0x808c, 0xbca1}, /* '肌' -> 32908 */ {0x8093, 0xebc1}, /* '肓' -> 32915 */ {0x8096, 0xd0a4}, /* '肖' -> 32918 */ {0x8098, 0xd6e2}, /* '肘' -> 32920 */ {0x809a, 0xb6c7}, /* '肚' -> 32922 */ {0x809b, 0xb8d8}, /* '肛' -> 32923 */ {0x809c, 0xebc0}, /* '肜' -> 32924 */ {0x809d, 0xb8ce}, /* '肝' -> 32925 */ {0x809f, 0xebbf}, /* '肟' -> 32927 */ {0x80a0, 0xb3a6}, /* '肠' -> 32928 */ {0x80a1, 0xb9c9}, /* '股' -> 32929 */ {0x80a2, 0xd6ab}, /* '肢' -> 32930 */ {0x80a4, 0xb7f4}, /* '肤' -> 32932 */ {0x80a5, 0xb7ca}, /* '肥' -> 32933 */ {0x80a9, 0xbce7}, /* '肩' -> 32937 */ {0x80aa, 0xb7be}, /* '肪' -> 32938 */ {0x80ab, 0xebc6}, /* '肫' -> 32939 */ {0x80ad, 0xebc7}, /* '肭' -> 32941 */ {0x80ae, 0xb0b9}, /* '肮' -> 32942 */ {0x80af, 0xbfcf}, /* '肯' -> 32943 */ {0x80b1, 0xebc5}, /* '肱' -> 32945 */ {0x80b2, 0xd3fd}, /* '育' -> 32946 */ {0x80b4, 0xebc8}, /* '肴' -> 32948 */ {0x80b7, 0xebc9}, /* '肷' -> 32951 */ {0x80ba, 0xb7ce}, /* '肺' -> 32954 */ {0x80bc, 0xebc2}, /* '肼' -> 32956 */ {0x80bd, 0xebc4}, /* '肽' -> 32957 */ {0x80be, 0xc9f6}, /* '肾' -> 32958 */ {0x80bf, 0xd6d7}, /* '肿' -> 32959 */ {0x80c0, 0xd5cd}, /* '胀' -> 32960 */ {0x80c1, 0xd0b2}, /* '胁' -> 32961 */ {0x80c2, 0xebcf}, /* '胂' -> 32962 */ {0x80c3, 0xceb8}, /* '胃' -> 32963 */ {0x80c4, 0xebd0}, /* '胄' -> 32964 */ {0x80c6, 0xb5a8}, /* '胆' -> 32966 */ {0x80cc, 0xb1b3}, /* '背' -> 32972 */ {0x80cd, 0xebd2}, /* '胍' -> 32973 */ {0x80ce, 0xcca5}, /* '胎' -> 32974 */ {0x80d6, 0xc5d6}, /* '胖' -> 32982 */ {0x80d7, 0xebd3}, /* '胗' -> 32983 */ {0x80d9, 0xebd1}, /* '胙' -> 32985 */ {0x80da, 0xc5df}, /* '胚' -> 32986 */ {0x80db, 0xebce}, /* '胛' -> 32987 */ {0x80dc, 0xcaa4}, /* '胜' -> 32988 */ {0x80dd, 0xebd5}, /* '胝' -> 32989 */ {0x80de, 0xb0fb}, /* '胞' -> 32990 */ {0x80e1, 0xbafa}, /* '胡' -> 32993 */ {0x80e4, 0xd8b7}, /* '胤' -> 32996 */ {0x80e5, 0xf1e3}, /* '胥' -> 32997 */ {0x80e7, 0xebca}, /* '胧' -> 32999 */ {0x80e8, 0xebcb}, /* '胨' -> 33000 */ {0x80e9, 0xebcc}, /* '胩' -> 33001 */ {0x80ea, 0xebcd}, /* '胪' -> 33002 */ {0x80eb, 0xebd6}, /* '胫' -> 33003 */ {0x80ec, 0xe6c0}, /* '胬' -> 33004 */ {0x80ed, 0xebd9}, /* '胭' -> 33005 */ {0x80ef, 0xbfe8}, /* '胯' -> 33007 */ {0x80f0, 0xd2c8}, /* '胰' -> 33008 */ {0x80f1, 0xebd7}, /* '胱' -> 33009 */ {0x80f2, 0xebdc}, /* '胲' -> 33010 */ {0x80f3, 0xb8ec}, /* '胳' -> 33011 */ {0x80f4, 0xebd8}, /* '胴' -> 33012 */ {0x80f6, 0xbdba}, /* '胶' -> 33014 */ {0x80f8, 0xd0d8}, /* '胸' -> 33016 */ {0x80fa, 0xb0b7}, /* '胺' -> 33018 */ {0x80fc, 0xebdd}, /* '胼' -> 33020 */ {0x80fd, 0xc4dc}, /* '能' -> 33021 */ {0x8102, 0xd6ac}, /* '脂' -> 33026 */ {0x8106, 0xb4e0}, /* '脆' -> 33030 */ {0x8109, 0xc2f6}, /* '脉' -> 33033 */ {0x810a, 0xbcb9}, /* '脊' -> 33034 */ {0x810d, 0xebda}, /* '脍' -> 33037 */ {0x810e, 0xebdb}, /* '脎' -> 33038 */ {0x810f, 0xd4e0}, /* '脏' -> 33039 */ {0x8110, 0xc6ea}, /* '脐' -> 33040 */ {0x8111, 0xc4d4}, /* '脑' -> 33041 */ {0x8112, 0xebdf}, /* '脒' -> 33042 */ {0x8113, 0xc5a7}, /* '脓' -> 33043 */ {0x8114, 0xd9f5}, /* '脔' -> 33044 */ {0x8116, 0xb2b1}, /* '脖' -> 33046 */ {0x8118, 0xebe4}, /* '脘' -> 33048 */ {0x811a, 0xbdc5}, /* '脚' -> 33050 */ {0x811e, 0xebe2}, /* '脞' -> 33054 */ {0x812c, 0xebe3}, /* '脬' -> 33068 */ {0x812f, 0xb8ac}, /* '脯' -> 33071 */ {0x8131, 0xcdd1}, /* '脱' -> 33073 */ {0x8132, 0xebe5}, /* '脲' -> 33074 */ {0x8136, 0xebe1}, /* '脶' -> 33078 */ {0x8138, 0xc1b3}, /* '脸' -> 33080 */ {0x813e, 0xc6a2}, /* '脾' -> 33086 */ {0x8146, 0xccf3}, /* '腆' -> 33094 */ {0x8148, 0xebe6}, /* '腈' -> 33096 */ {0x814a, 0xc0b0}, /* '腊' -> 33098 */ {0x814b, 0xd2b8}, /* '腋' -> 33099 */ {0x814c, 0xebe7}, /* '腌' -> 33100 */ {0x8150, 0xb8af}, /* '腐' -> 33104 */ {0x8151, 0xb8ad}, /* '腑' -> 33105 */ {0x8153, 0xebe8}, /* '腓' -> 33107 */ {0x8154, 0xc7bb}, /* '腔' -> 33108 */ {0x8155, 0xcdf3}, /* '腕' -> 33109 */ {0x8159, 0xebea}, /* '腙' -> 33113 */ {0x815a, 0xebeb}, /* '腚' -> 33114 */ {0x8160, 0xebed}, /* '腠' -> 33120 */ {0x8165, 0xd0c8}, /* '腥' -> 33125 */ {0x8167, 0xebf2}, /* '腧' -> 33127 */ {0x8169, 0xebee}, /* '腩' -> 33129 */ {0x816d, 0xebf1}, /* '腭' -> 33133 */ {0x816e, 0xc8f9}, /* '腮' -> 33134 */ {0x8170, 0xd1fc}, /* '腰' -> 33136 */ {0x8171, 0xebec}, /* '腱' -> 33137 */ {0x8174, 0xebe9}, /* '腴' -> 33140 */ {0x8179, 0xb8b9}, /* '腹' -> 33145 */ {0x817a, 0xcfd9}, /* '腺' -> 33146 */ {0x817b, 0xc4e5}, /* '腻' -> 33147 */ {0x817c, 0xebef}, /* '腼' -> 33148 */ {0x817d, 0xebf0}, /* '腽' -> 33149 */ {0x817e, 0xccda}, /* '腾' -> 33150 */ {0x817f, 0xcdc8}, /* '腿' -> 33151 */ {0x8180, 0xb0f2}, /* '膀' -> 33152 */ {0x8182, 0xebf6}, /* '膂' -> 33154 */ {0x8188, 0xebf5}, /* '膈' -> 33160 */ {0x818a, 0xb2b2}, /* '膊' -> 33162 */ {0x818f, 0xb8e0}, /* '膏' -> 33167 */ {0x8191, 0xebf7}, /* '膑' -> 33169 */ {0x8198, 0xb1ec}, /* '膘' -> 33176 */ {0x819b, 0xccc5}, /* '膛' -> 33179 */ {0x819c, 0xc4a4}, /* '膜' -> 33180 */ {0x819d, 0xcfa5}, /* '膝' -> 33181 */ {0x81a3, 0xebf9}, /* '膣' -> 33187 */ {0x81a6, 0xeca2}, /* '膦' -> 33190 */ {0x81a8, 0xc5f2}, /* '膨' -> 33192 */ {0x81aa, 0xebfa}, /* '膪' -> 33194 */ {0x81b3, 0xc9c5}, /* '膳' -> 33203 */ {0x81ba, 0xe2df}, /* '膺' -> 33210 */ {0x81bb, 0xebfe}, /* '膻' -> 33211 */ {0x81c0, 0xcdce}, /* '臀' -> 33216 */ {0x81c1, 0xeca1}, /* '臁' -> 33217 */ {0x81c2, 0xb1db}, /* '臂' -> 33218 */ {0x81c3, 0xd3b7}, /* '臃' -> 33219 */ {0x81c6, 0xd2dc}, /* '臆' -> 33222 */ {0x81ca, 0xebfd}, /* '臊' -> 33226 */ {0x81cc, 0xebfb}, /* '臌' -> 33228 */ {0x81e3, 0xb3bc}, /* '臣' -> 33251 */ {0x81e7, 0xeab0}, /* '臧' -> 33255 */ {0x81ea, 0xd7d4}, /* '自' -> 33258 */ {0x81ec, 0xf4ab}, /* '臬' -> 33260 */ {0x81ed, 0xb3f4}, /* '臭' -> 33261 */ {0x81f3, 0xd6c1}, /* '至' -> 33267 */ {0x81f4, 0xd6c2}, /* '致' -> 33268 */ {0x81fb, 0xd5e9}, /* '臻' -> 33275 */ {0x81fc, 0xbeca}, /* '臼' -> 33276 */ {0x81fe, 0xf4a7}, /* '臾' -> 33278 */ {0x8200, 0xd2a8}, /* '舀' -> 33280 */ {0x8201, 0xf4a8}, /* '舁' -> 33281 */ {0x8202, 0xf4a9}, /* '舂' -> 33282 */ {0x8204, 0xf4aa}, /* '舄' -> 33284 */ {0x8205, 0xbecb}, /* '舅' -> 33285 */ {0x8206, 0xd3df}, /* '舆' -> 33286 */ {0x820c, 0xc9e0}, /* '舌' -> 33292 */ {0x820d, 0xc9e1}, /* '舍' -> 33293 */ {0x8210, 0xf3c2}, /* '舐' -> 33296 */ {0x8212, 0xcae6}, /* '舒' -> 33298 */ {0x8214, 0xccf2}, /* '舔' -> 33300 */ {0x821b, 0xe2b6}, /* '舛' -> 33307 */ {0x821c, 0xcbb4}, /* '舜' -> 33308 */ {0x821e, 0xcee8}, /* '舞' -> 33310 */ {0x821f, 0xd6db}, /* '舟' -> 33311 */ {0x8221, 0xf4ad}, /* '舡' -> 33313 */ {0x8222, 0xf4ae}, /* '舢' -> 33314 */ {0x8223, 0xf4af}, /* '舣' -> 33315 */ {0x8228, 0xf4b2}, /* '舨' -> 33320 */ {0x822a, 0xbabd}, /* '航' -> 33322 */ {0x822b, 0xf4b3}, /* '舫' -> 33323 */ {0x822c, 0xb0e3}, /* '般' -> 33324 */ {0x822d, 0xf4b0}, /* '舭' -> 33325 */ {0x822f, 0xf4b1}, /* '舯' -> 33327 */ {0x8230, 0xbda2}, /* '舰' -> 33328 */ {0x8231, 0xb2d5}, /* '舱' -> 33329 */ {0x8233, 0xf4b6}, /* '舳' -> 33331 */ {0x8234, 0xf4b7}, /* '舴' -> 33332 */ {0x8235, 0xb6e6}, /* '舵' -> 33333 */ {0x8236, 0xb2b0}, /* '舶' -> 33334 */ {0x8237, 0xcfcf}, /* '舷' -> 33335 */ {0x8238, 0xf4b4}, /* '舸' -> 33336 */ {0x8239, 0xb4ac}, /* '船' -> 33337 */ {0x823b, 0xf4b5}, /* '舻' -> 33339 */ {0x823e, 0xf4b8}, /* '舾' -> 33342 */ {0x8244, 0xf4b9}, /* '艄' -> 33348 */ {0x8247, 0xcda7}, /* '艇' -> 33351 */ {0x8249, 0xf4ba}, /* '艉' -> 33353 */ {0x824b, 0xf4bb}, /* '艋' -> 33355 */ {0x824f, 0xf4bc}, /* '艏' -> 33359 */ {0x8258, 0xcbd2}, /* '艘' -> 33368 */ {0x825a, 0xf4bd}, /* '艚' -> 33370 */ {0x825f, 0xf4be}, /* '艟' -> 33375 */ {0x8268, 0xf4bf}, /* '艨' -> 33384 */ {0x826e, 0xf4de}, /* '艮' -> 33390 */ {0x826f, 0xc1bc}, /* '良' -> 33391 */ {0x8270, 0xbce8}, /* '艰' -> 33392 */ {0x8272, 0xc9ab}, /* '色' -> 33394 */ {0x8273, 0xd1de}, /* '艳' -> 33395 */ {0x8274, 0xe5f5}, /* '艴' -> 33396 */ {0x8279, 0xdcb3}, /* '艹' -> 33401 */ {0x827a, 0xd2d5}, /* '艺' -> 33402 */ {0x827d, 0xdcb4}, /* '艽' -> 33405 */ {0x827e, 0xb0ac}, /* '艾' -> 33406 */ {0x827f, 0xdcb5}, /* '艿' -> 33407 */ {0x8282, 0xbdda}, /* '节' -> 33410 */ {0x8284, 0xdcb9}, /* '芄' -> 33412 */ {0x8288, 0xd8c2}, /* '芈' -> 33416 */ {0x828a, 0xdcb7}, /* '芊' -> 33418 */ {0x828b, 0xd3f3}, /* '芋' -> 33419 */ {0x828d, 0xc9d6}, /* '芍' -> 33421 */ {0x828e, 0xdcba}, /* '芎' -> 33422 */ {0x828f, 0xdcb6}, /* '芏' -> 33423 */ {0x8291, 0xdcbb}, /* '芑' -> 33425 */ {0x8292, 0xc3a2}, /* '芒' -> 33426 */ {0x8297, 0xdcbc}, /* '芗' -> 33431 */ {0x8298, 0xdcc5}, /* '芘' -> 33432 */ {0x8299, 0xdcbd}, /* '芙' -> 33433 */ {0x829c, 0xcedf}, /* '芜' -> 33436 */ {0x829d, 0xd6a5}, /* '芝' -> 33437 */ {0x829f, 0xdccf}, /* '芟' -> 33439 */ {0x82a1, 0xdccd}, /* '芡' -> 33441 */ {0x82a4, 0xdcd2}, /* '芤' -> 33444 */ {0x82a5, 0xbde6}, /* '芥' -> 33445 */ {0x82a6, 0xc2ab}, /* '芦' -> 33446 */ {0x82a8, 0xdcb8}, /* '芨' -> 33448 */ {0x82a9, 0xdccb}, /* '芩' -> 33449 */ {0x82aa, 0xdcce}, /* '芪' -> 33450 */ {0x82ab, 0xdcbe}, /* '芫' -> 33451 */ {0x82ac, 0xb7d2}, /* '芬' -> 33452 */ {0x82ad, 0xb0c5}, /* '芭' -> 33453 */ {0x82ae, 0xdcc7}, /* '芮' -> 33454 */ {0x82af, 0xd0be}, /* '芯' -> 33455 */ {0x82b0, 0xdcc1}, /* '芰' -> 33456 */ {0x82b1, 0xbba8}, /* '花' -> 33457 */ {0x82b3, 0xb7bc}, /* '芳' -> 33459 */ {0x82b4, 0xdccc}, /* '芴' -> 33460 */ {0x82b7, 0xdcc6}, /* '芷' -> 33463 */ {0x82b8, 0xdcbf}, /* '芸' -> 33464 */ {0x82b9, 0xc7db}, /* '芹' -> 33465 */ {0x82bd, 0xd1bf}, /* '芽' -> 33469 */ {0x82be, 0xdcc0}, /* '芾' -> 33470 */ {0x82c1, 0xdcca}, /* '苁' -> 33473 */ {0x82c4, 0xdcd0}, /* '苄' -> 33476 */ {0x82c7, 0xcead}, /* '苇' -> 33479 */ {0x82c8, 0xdcc2}, /* '苈' -> 33480 */ {0x82ca, 0xdcc3}, /* '苊' -> 33482 */ {0x82cb, 0xdcc8}, /* '苋' -> 33483 */ {0x82cc, 0xdcc9}, /* '苌' -> 33484 */ {0x82cd, 0xb2d4}, /* '苍' -> 33485 */ {0x82ce, 0xdcd1}, /* '苎' -> 33486 */ {0x82cf, 0xcbd5}, /* '苏' -> 33487 */ {0x82d1, 0xd4b7}, /* '苑' -> 33489 */ {0x82d2, 0xdcdb}, /* '苒' -> 33490 */ {0x82d3, 0xdcdf}, /* '苓' -> 33491 */ {0x82d4, 0xcca6}, /* '苔' -> 33492 */ {0x82d5, 0xdce6}, /* '苕' -> 33493 */ {0x82d7, 0xc3e7}, /* '苗' -> 33495 */ {0x82d8, 0xdcdc}, /* '苘' -> 33496 */ {0x82db, 0xbfc1}, /* '苛' -> 33499 */ {0x82dc, 0xdcd9}, /* '苜' -> 33500 */ {0x82de, 0xb0fa}, /* '苞' -> 33502 */ {0x82df, 0xb9b6}, /* '苟' -> 33503 */ {0x82e0, 0xdce5}, /* '苠' -> 33504 */ {0x82e1, 0xdcd3}, /* '苡' -> 33505 */ {0x82e3, 0xdcc4}, /* '苣' -> 33507 */ {0x82e4, 0xdcd6}, /* '苤' -> 33508 */ {0x82e5, 0xc8f4}, /* '若' -> 33509 */ {0x82e6, 0xbfe0}, /* '苦' -> 33510 */ {0x82eb, 0xc9bb}, /* '苫' -> 33515 */ {0x82ef, 0xb1bd}, /* '苯' -> 33519 */ {0x82f1, 0xd3a2}, /* '英' -> 33521 */ {0x82f4, 0xdcda}, /* '苴' -> 33524 */ {0x82f7, 0xdcd5}, /* '苷' -> 33527 */ {0x82f9, 0xc6bb}, /* '苹' -> 33529 */ {0x82fb, 0xdcde}, /* '苻' -> 33531 */ {0x8301, 0xd7c2}, /* '茁' -> 33537 */ {0x8302, 0xc3af}, /* '茂' -> 33538 */ {0x8303, 0xb7b6}, /* '范' -> 33539 */ {0x8304, 0xc7d1}, /* '茄' -> 33540 */ {0x8305, 0xc3a9}, /* '茅' -> 33541 */ {0x8306, 0xdce2}, /* '茆' -> 33542 */ {0x8307, 0xdcd8}, /* '茇' -> 33543 */ {0x8308, 0xdceb}, /* '茈' -> 33544 */ {0x8309, 0xdcd4}, /* '茉' -> 33545 */ {0x830c, 0xdcdd}, /* '茌' -> 33548 */ {0x830e, 0xbea5}, /* '茎' -> 33550 */ {0x830f, 0xdcd7}, /* '茏' -> 33551 */ {0x8311, 0xdce0}, /* '茑' -> 33553 */ {0x8314, 0xdce3}, /* '茔' -> 33556 */ {0x8315, 0xdce4}, /* '茕' -> 33557 */ {0x8317, 0xdcf8}, /* '茗' -> 33559 */ {0x831a, 0xdce1}, /* '茚' -> 33562 */ {0x831b, 0xdda2}, /* '茛' -> 33563 */ {0x831c, 0xdce7}, /* '茜' -> 33564 */ {0x8327, 0xbceb}, /* '茧' -> 33575 */ {0x8328, 0xb4c4}, /* '茨' -> 33576 */ {0x832b, 0xc3a3}, /* '茫' -> 33579 */ {0x832c, 0xb2e7}, /* '茬' -> 33580 */ {0x832d, 0xdcfa}, /* '茭' -> 33581 */ {0x832f, 0xdcf2}, /* '茯' -> 33583 */ {0x8331, 0xdcef}, /* '茱' -> 33585 */ {0x8333, 0xdcfc}, /* '茳' -> 33587 */ {0x8334, 0xdcee}, /* '茴' -> 33588 */ {0x8335, 0xd2f0}, /* '茵' -> 33589 */ {0x8336, 0xb2e8}, /* '茶' -> 33590 */ {0x8338, 0xc8d7}, /* '茸' -> 33592 */ {0x8339, 0xc8e3}, /* '茹' -> 33593 */ {0x833a, 0xdcfb}, /* '茺' -> 33594 */ {0x833c, 0xdced}, /* '茼' -> 33596 */ {0x8340, 0xdcf7}, /* '荀' -> 33600 */ {0x8343, 0xdcf5}, /* '荃' -> 33603 */ {0x8346, 0xbea3}, /* '荆' -> 33606 */ {0x8347, 0xdcf4}, /* '荇' -> 33607 */ {0x8349, 0xb2dd}, /* '草' -> 33609 */ {0x834f, 0xdcf3}, /* '荏' -> 33615 */ {0x8350, 0xbcf6}, /* '荐' -> 33616 */ {0x8351, 0xdce8}, /* '荑' -> 33617 */ {0x8352, 0xbbc4}, /* '荒' -> 33618 */ {0x8354, 0xc0f3}, /* '荔' -> 33620 */ {0x835a, 0xbcd4}, /* '荚' -> 33626 */ {0x835b, 0xdce9}, /* '荛' -> 33627 */ {0x835c, 0xdcea}, /* '荜' -> 33628 */ {0x835e, 0xdcf1}, /* '荞' -> 33630 */ {0x835f, 0xdcf6}, /* '荟' -> 33631 */ {0x8360, 0xdcf9}, /* '荠' -> 33632 */ {0x8361, 0xb5b4}, /* '荡' -> 33633 */ {0x8363, 0xc8d9}, /* '荣' -> 33635 */ {0x8364, 0xbbe7}, /* '荤' -> 33636 */ {0x8365, 0xdcfe}, /* '荥' -> 33637 */ {0x8366, 0xdcfd}, /* '荦' -> 33638 */ {0x8367, 0xd3ab}, /* '荧' -> 33639 */ {0x8368, 0xdda1}, /* '荨' -> 33640 */ {0x8369, 0xdda3}, /* '荩' -> 33641 */ {0x836a, 0xdda5}, /* '荪' -> 33642 */ {0x836b, 0xd2f1}, /* '荫' -> 33643 */ {0x836c, 0xdda4}, /* '荬' -> 33644 */ {0x836d, 0xdda6}, /* '荭' -> 33645 */ {0x836e, 0xdda7}, /* '荮' -> 33646 */ {0x836f, 0xd2a9}, /* '药' -> 33647 */ {0x8377, 0xbac9}, /* '荷' -> 33655 */ {0x8378, 0xdda9}, /* '荸' -> 33656 */ {0x837b, 0xddb6}, /* '荻' -> 33659 */ {0x837c, 0xddb1}, /* '荼' -> 33660 */ {0x837d, 0xddb4}, /* '荽' -> 33661 */ {0x8385, 0xddb0}, /* '莅' -> 33669 */ {0x8386, 0xc6ce}, /* '莆' -> 33670 */ {0x8389, 0xc0f2}, /* '莉' -> 33673 */ {0x838e, 0xc9af}, /* '莎' -> 33678 */ {0x8392, 0xdcec}, /* '莒' -> 33682 */ {0x8393, 0xddae}, /* '莓' -> 33683 */ {0x8398, 0xddb7}, /* '莘' -> 33688 */ {0x839b, 0xdcf0}, /* '莛' -> 33691 */ {0x839c, 0xddaf}, /* '莜' -> 33692 */ {0x839e, 0xddb8}, /* '莞' -> 33694 */ {0x83a0, 0xddac}, /* '莠' -> 33696 */ {0x83a8, 0xddb9}, /* '莨' -> 33704 */ {0x83a9, 0xddb3}, /* '莩' -> 33705 */ {0x83aa, 0xddad}, /* '莪' -> 33706 */ {0x83ab, 0xc4aa}, /* '莫' -> 33707 */ {0x83b0, 0xdda8}, /* '莰' -> 33712 */ {0x83b1, 0xc0b3}, /* '莱' -> 33713 */ {0x83b2, 0xc1ab}, /* '莲' -> 33714 */ {0x83b3, 0xddaa}, /* '莳' -> 33715 */ {0x83b4, 0xddab}, /* '莴' -> 33716 */ {0x83b6, 0xddb2}, /* '莶' -> 33718 */ {0x83b7, 0xbbf1}, /* '获' -> 33719 */ {0x83b8, 0xddb5}, /* '莸' -> 33720 */ {0x83b9, 0xd3a8}, /* '莹' -> 33721 */ {0x83ba, 0xddba}, /* '莺' -> 33722 */ {0x83bc, 0xddbb}, /* '莼' -> 33724 */ {0x83bd, 0xc3a7}, /* '莽' -> 33725 */ {0x83c0, 0xddd2}, /* '菀' -> 33728 */ {0x83c1, 0xddbc}, /* '菁' -> 33729 */ {0x83c5, 0xddd1}, /* '菅' -> 33733 */ {0x83c7, 0xb9bd}, /* '菇' -> 33735 */ {0x83ca, 0xbed5}, /* '菊' -> 33738 */ {0x83cc, 0xbefa}, /* '菌' -> 33740 */ {0x83cf, 0xbaca}, /* '菏' -> 33743 */ {0x83d4, 0xddca}, /* '菔' -> 33748 */ {0x83d6, 0xddc5}, /* '菖' -> 33750 */ {0x83d8, 0xddbf}, /* '菘' -> 33752 */ {0x83dc, 0xb2cb}, /* '菜' -> 33756 */ {0x83dd, 0xddc3}, /* '菝' -> 33757 */ {0x83df, 0xddcb}, /* '菟' -> 33759 */ {0x83e0, 0xb2a4}, /* '菠' -> 33760 */ {0x83e1, 0xddd5}, /* '菡' -> 33761 */ {0x83e5, 0xddbe}, /* '菥' -> 33765 */ {0x83e9, 0xc6d0}, /* '菩' -> 33769 */ {0x83ea, 0xddd0}, /* '菪' -> 33770 */ {0x83f0, 0xddd4}, /* '菰' -> 33776 */ {0x83f1, 0xc1e2}, /* '菱' -> 33777 */ {0x83f2, 0xb7c6}, /* '菲' -> 33778 */ {0x83f8, 0xddce}, /* '菸' -> 33784 */ {0x83f9, 0xddcf}, /* '菹' -> 33785 */ {0x83fd, 0xddc4}, /* '菽' -> 33789 */ {0x8401, 0xddbd}, /* '萁' -> 33793 */ {0x8403, 0xddcd}, /* '萃' -> 33795 */ {0x8404, 0xccd1}, /* '萄' -> 33796 */ {0x8406, 0xddc9}, /* '萆' -> 33798 */ {0x840b, 0xddc2}, /* '萋' -> 33803 */ {0x840c, 0xc3c8}, /* '萌' -> 33804 */ {0x840d, 0xc6bc}, /* '萍' -> 33805 */ {0x840e, 0xceae}, /* '萎' -> 33806 */ {0x840f, 0xddcc}, /* '萏' -> 33807 */ {0x8411, 0xddc8}, /* '萑' -> 33809 */ {0x8418, 0xddc1}, /* '萘' -> 33816 */ {0x841c, 0xddc6}, /* '萜' -> 33820 */ {0x841d, 0xc2dc}, /* '萝' -> 33821 */ {0x8424, 0xd3a9}, /* '萤' -> 33828 */ {0x8425, 0xd3aa}, /* '营' -> 33829 */ {0x8426, 0xddd3}, /* '萦' -> 33830 */ {0x8427, 0xcff4}, /* '萧' -> 33831 */ {0x8428, 0xc8f8}, /* '萨' -> 33832 */ {0x8431, 0xdde6}, /* '萱' -> 33841 */ {0x8438, 0xddc7}, /* '萸' -> 33848 */ {0x843c, 0xdde0}, /* '萼' -> 33852 */ {0x843d, 0xc2e4}, /* '落' -> 33853 */ {0x8446, 0xdde1}, /* '葆' -> 33862 */ {0x8451, 0xddd7}, /* '葑' -> 33873 */ {0x8457, 0xd6f8}, /* '著' -> 33879 */ {0x8459, 0xddd9}, /* '葙' -> 33881 */ {0x845a, 0xddd8}, /* '葚' -> 33882 */ {0x845b, 0xb8f0}, /* '葛' -> 33883 */ {0x845c, 0xddd6}, /* '葜' -> 33884 */ {0x8461, 0xc6cf}, /* '葡' -> 33889 */ {0x8463, 0xb6ad}, /* '董' -> 33891 */ {0x8469, 0xdde2}, /* '葩' -> 33897 */ {0x846b, 0xbaf9}, /* '葫' -> 33899 */ {0x846c, 0xd4e1}, /* '葬' -> 33900 */ {0x846d, 0xdde7}, /* '葭' -> 33901 */ {0x8471, 0xb4d0}, /* '葱' -> 33905 */ {0x8473, 0xddda}, /* '葳' -> 33907 */ {0x8475, 0xbffb}, /* '葵' -> 33909 */ {0x8476, 0xdde3}, /* '葶' -> 33910 */ {0x8478, 0xdddf}, /* '葸' -> 33912 */ {0x847a, 0xdddd}, /* '葺' -> 33914 */ {0x8482, 0xb5d9}, /* '蒂' -> 33922 */ {0x8487, 0xdddb}, /* '蒇' -> 33927 */ {0x8488, 0xdddc}, /* '蒈' -> 33928 */ {0x8489, 0xddde}, /* '蒉' -> 33929 */ {0x848b, 0xbdaf}, /* '蒋' -> 33931 */ {0x848c, 0xdde4}, /* '蒌' -> 33932 */ {0x848e, 0xdde5}, /* '蒎' -> 33934 */ {0x8497, 0xddf5}, /* '蒗' -> 33943 */ {0x8499, 0xc3c9}, /* '蒙' -> 33945 */ {0x849c, 0xcbe2}, /* '蒜' -> 33948 */ {0x84a1, 0xddf2}, /* '蒡' -> 33953 */ {0x84af, 0xd8e1}, /* '蒯' -> 33967 */ {0x84b2, 0xc6d1}, /* '蒲' -> 33970 */ {0x84b4, 0xddf4}, /* '蒴' -> 33972 */ {0x84b8, 0xd5f4}, /* '蒸' -> 33976 */ {0x84b9, 0xddf3}, /* '蒹' -> 33977 */ {0x84ba, 0xddf0}, /* '蒺' -> 33978 */ {0x84bd, 0xddec}, /* '蒽' -> 33981 */ {0x84bf, 0xddef}, /* '蒿' -> 33983 */ {0x84c1, 0xdde8}, /* '蓁' -> 33985 */ {0x84c4, 0xd0ee}, /* '蓄' -> 33988 */ {0x84c9, 0xc8d8}, /* '蓉' -> 33993 */ {0x84ca, 0xddee}, /* '蓊' -> 33994 */ {0x84cd, 0xdde9}, /* '蓍' -> 33997 */ {0x84d0, 0xddea}, /* '蓐' -> 34000 */ {0x84d1, 0xcbf2}, /* '蓑' -> 34001 */ {0x84d3, 0xdded}, /* '蓓' -> 34003 */ {0x84d6, 0xb1cd}, /* '蓖' -> 34006 */ {0x84dd, 0xc0b6}, /* '蓝' -> 34013 */ {0x84df, 0xbcbb}, /* '蓟' -> 34015 */ {0x84e0, 0xddf1}, /* '蓠' -> 34016 */ {0x84e3, 0xddf7}, /* '蓣' -> 34019 */ {0x84e5, 0xddf6}, /* '蓥' -> 34021 */ {0x84e6, 0xddeb}, /* '蓦' -> 34022 */ {0x84ec, 0xc5ee}, /* '蓬' -> 34028 */ {0x84f0, 0xddfb}, /* '蓰' -> 34032 */ {0x84fc, 0xdea4}, /* '蓼' -> 34044 */ {0x84ff, 0xdea3}, /* '蓿' -> 34047 */ {0x850c, 0xddf8}, /* '蔌' -> 34060 */ {0x8511, 0xc3ef}, /* '蔑' -> 34065 */ {0x8513, 0xc2fb}, /* '蔓' -> 34067 */ {0x8517, 0xd5e1}, /* '蔗' -> 34071 */ {0x851a, 0xceb5}, /* '蔚' -> 34074 */ {0x851f, 0xddfd}, /* '蔟' -> 34079 */ {0x8521, 0xb2cc}, /* '蔡' -> 34081 */ {0x852b, 0xc4e8}, /* '蔫' -> 34091 */ {0x852c, 0xcadf}, /* '蔬' -> 34092 */ {0x8537, 0xc7be}, /* '蔷' -> 34103 */ {0x8538, 0xddfa}, /* '蔸' -> 34104 */ {0x8539, 0xddfc}, /* '蔹' -> 34105 */ {0x853a, 0xddfe}, /* '蔺' -> 34106 */ {0x853b, 0xdea2}, /* '蔻' -> 34107 */ {0x853c, 0xb0aa}, /* '蔼' -> 34108 */ {0x853d, 0xb1ce}, /* '蔽' -> 34109 */ {0x8543, 0xdeac}, /* '蕃' -> 34115 */ {0x8548, 0xdea6}, /* '蕈' -> 34120 */ {0x8549, 0xbdb6}, /* '蕉' -> 34121 */ {0x854a, 0xc8ef}, /* '蕊' -> 34122 */ {0x8556, 0xdea1}, /* '蕖' -> 34134 */ {0x8559, 0xdea5}, /* '蕙' -> 34137 */ {0x855e, 0xdea9}, /* '蕞' -> 34142 */ {0x8564, 0xdea8}, /* '蕤' -> 34148 */ {0x8568, 0xdea7}, /* '蕨' -> 34152 */ {0x8572, 0xdead}, /* '蕲' -> 34162 */ {0x8574, 0xd4cc}, /* '蕴' -> 34164 */ {0x8579, 0xdeb3}, /* '蕹' -> 34169 */ {0x857a, 0xdeaa}, /* '蕺' -> 34170 */ {0x857b, 0xdeae}, /* '蕻' -> 34171 */ {0x857e, 0xc0d9}, /* '蕾' -> 34174 */ {0x8584, 0xb1a1}, /* '薄' -> 34180 */ {0x8585, 0xdeb6}, /* '薅' -> 34181 */ {0x8587, 0xdeb1}, /* '薇' -> 34183 */ {0x858f, 0xdeb2}, /* '薏' -> 34191 */ {0x859b, 0xd1a6}, /* '薛' -> 34203 */ {0x859c, 0xdeb5}, /* '薜' -> 34204 */ {0x85a4, 0xdeaf}, /* '薤' -> 34212 */ {0x85a8, 0xdeb0}, /* '薨' -> 34216 */ {0x85aa, 0xd0bd}, /* '薪' -> 34218 */ {0x85ae, 0xdeb4}, /* '薮' -> 34222 */ {0x85af, 0xcaed}, /* '薯' -> 34223 */ {0x85b0, 0xdeb9}, /* '薰' -> 34224 */ {0x85b7, 0xdeb8}, /* '薷' -> 34231 */ {0x85b9, 0xdeb7}, /* '薹' -> 34233 */ {0x85c1, 0xdebb}, /* '藁' -> 34241 */ {0x85c9, 0xbde5}, /* '藉' -> 34249 */ {0x85cf, 0xb2d8}, /* '藏' -> 34255 */ {0x85d0, 0xc3ea}, /* '藐' -> 34256 */ {0x85d3, 0xdeba}, /* '藓' -> 34259 */ {0x85d5, 0xc5ba}, /* '藕' -> 34261 */ {0x85dc, 0xdebc}, /* '藜' -> 34268 */ {0x85e4, 0xccd9}, /* '藤' -> 34276 */ {0x85e9, 0xb7aa}, /* '藩' -> 34281 */ {0x85fb, 0xd4e5}, /* '藻' -> 34299 */ {0x85ff, 0xdebd}, /* '藿' -> 34303 */ {0x8605, 0xdebf}, /* '蘅' -> 34309 */ {0x8611, 0xc4a2}, /* '蘑' -> 34321 */ {0x8616, 0xdec1}, /* '蘖' -> 34326 */ {0x8627, 0xdebe}, /* '蘧' -> 34343 */ {0x8629, 0xdec0}, /* '蘩' -> 34345 */ {0x8638, 0xd5ba}, /* '蘸' -> 34360 */ {0x863c, 0xdec2}, /* '蘼' -> 34364 */ {0x864d, 0xf2ae}, /* '虍' -> 34381 */ {0x864e, 0xbba2}, /* '虎' -> 34382 */ {0x864f, 0xc2b2}, /* '虏' -> 34383 */ {0x8650, 0xc5b0}, /* '虐' -> 34384 */ {0x8651, 0xc2c7}, /* '虑' -> 34385 */ {0x8654, 0xf2af}, /* '虔' -> 34388 */ {0x865a, 0xd0e9}, /* '虚' -> 34394 */ {0x865e, 0xd3dd}, /* '虞' -> 34398 */ {0x8662, 0xebbd}, /* '虢' -> 34402 */ {0x866b, 0xb3e6}, /* '虫' -> 34411 */ {0x866c, 0xf2b0}, /* '虬' -> 34412 */ {0x866e, 0xf2b1}, /* '虮' -> 34414 */ {0x8671, 0xcaad}, /* '虱' -> 34417 */ {0x8679, 0xbae7}, /* '虹' -> 34425 */ {0x867a, 0xf2b3}, /* '虺' -> 34426 */ {0x867b, 0xf2b5}, /* '虻' -> 34427 */ {0x867c, 0xf2b4}, /* '虼' -> 34428 */ {0x867d, 0xcbe4}, /* '虽' -> 34429 */ {0x867e, 0xcfba}, /* '虾' -> 34430 */ {0x867f, 0xf2b2}, /* '虿' -> 34431 */ {0x8680, 0xcab4}, /* '蚀' -> 34432 */ {0x8681, 0xd2cf}, /* '蚁' -> 34433 */ {0x8682, 0xc2ec}, /* '蚂' -> 34434 */ {0x868a, 0xcec3}, /* '蚊' -> 34442 */ {0x868b, 0xf2b8}, /* '蚋' -> 34443 */ {0x868c, 0xb0f6}, /* '蚌' -> 34444 */ {0x868d, 0xf2b7}, /* '蚍' -> 34445 */ {0x8693, 0xf2be}, /* '蚓' -> 34451 */ {0x8695, 0xb2cf}, /* '蚕' -> 34453 */ {0x869c, 0xd1c1}, /* '蚜' -> 34460 */ {0x869d, 0xf2ba}, /* '蚝' -> 34461 */ {0x86a3, 0xf2bc}, /* '蚣' -> 34467 */ {0x86a4, 0xd4e9}, /* '蚤' -> 34468 */ {0x86a7, 0xf2bb}, /* '蚧' -> 34471 */ {0x86a8, 0xf2b6}, /* '蚨' -> 34472 */ {0x86a9, 0xf2bf}, /* '蚩' -> 34473 */ {0x86aa, 0xf2bd}, /* '蚪' -> 34474 */ {0x86ac, 0xf2b9}, /* '蚬' -> 34476 */ {0x86af, 0xf2c7}, /* '蚯' -> 34479 */ {0x86b0, 0xf2c4}, /* '蚰' -> 34480 */ {0x86b1, 0xf2c6}, /* '蚱' -> 34481 */ {0x86b4, 0xf2ca}, /* '蚴' -> 34484 */ {0x86b5, 0xf2c2}, /* '蚵' -> 34485 */ {0x86b6, 0xf2c0}, /* '蚶' -> 34486 */ {0x86ba, 0xf2c5}, /* '蚺' -> 34490 */ {0x86c0, 0xd6fb}, /* '蛀' -> 34496 */ {0x86c4, 0xf2c1}, /* '蛄' -> 34500 */ {0x86c6, 0xc7f9}, /* '蛆' -> 34502 */ {0x86c7, 0xc9df}, /* '蛇' -> 34503 */ {0x86c9, 0xf2c8}, /* '蛉' -> 34505 */ {0x86ca, 0xb9c6}, /* '蛊' -> 34506 */ {0x86cb, 0xb5b0}, /* '蛋' -> 34507 */ {0x86ce, 0xf2c3}, /* '蛎' -> 34510 */ {0x86cf, 0xf2c9}, /* '蛏' -> 34511 */ {0x86d0, 0xf2d0}, /* '蛐' -> 34512 */ {0x86d1, 0xf2d6}, /* '蛑' -> 34513 */ {0x86d4, 0xbbd7}, /* '蛔' -> 34516 */ {0x86d8, 0xf2d5}, /* '蛘' -> 34520 */ {0x86d9, 0xcddc}, /* '蛙' -> 34521 */ {0x86db, 0xd6eb}, /* '蛛' -> 34523 */ {0x86de, 0xf2d2}, /* '蛞' -> 34526 */ {0x86df, 0xf2d4}, /* '蛟' -> 34527 */ {0x86e4, 0xb8f2}, /* '蛤' -> 34532 */ {0x86e9, 0xf2cb}, /* '蛩' -> 34537 */ {0x86ed, 0xf2ce}, /* '蛭' -> 34541 */ {0x86ee, 0xc2f9}, /* '蛮' -> 34542 */ {0x86f0, 0xd5dd}, /* '蛰' -> 34544 */ {0x86f1, 0xf2cc}, /* '蛱' -> 34545 */ {0x86f2, 0xf2cd}, /* '蛲' -> 34546 */ {0x86f3, 0xf2cf}, /* '蛳' -> 34547 */ {0x86f4, 0xf2d3}, /* '蛴' -> 34548 */ {0x86f8, 0xf2d9}, /* '蛸' -> 34552 */ {0x86f9, 0xd3bc}, /* '蛹' -> 34553 */ {0x86fe, 0xb6ea}, /* '蛾' -> 34558 */ {0x8700, 0xcaf1}, /* '蜀' -> 34560 */ {0x8702, 0xb7e4}, /* '蜂' -> 34562 */ {0x8703, 0xf2d7}, /* '蜃' -> 34563 */ {0x8707, 0xf2d8}, /* '蜇' -> 34567 */ {0x8708, 0xf2da}, /* '蜈' -> 34568 */ {0x8709, 0xf2dd}, /* '蜉' -> 34569 */ {0x870a, 0xf2db}, /* '蜊' -> 34570 */ {0x870d, 0xf2dc}, /* '蜍' -> 34573 */ {0x8712, 0xd1d1}, /* '蜒' -> 34578 */ {0x8713, 0xf2d1}, /* '蜓' -> 34579 */ {0x8715, 0xcdc9}, /* '蜕' -> 34581 */ {0x8717, 0xcecf}, /* '蜗' -> 34583 */ {0x8718, 0xd6a9}, /* '蜘' -> 34584 */ {0x871a, 0xf2e3}, /* '蜚' -> 34586 */ {0x871c, 0xc3db}, /* '蜜' -> 34588 */ {0x871e, 0xf2e0}, /* '蜞' -> 34590 */ {0x8721, 0xc0af}, /* '蜡' -> 34593 */ {0x8722, 0xf2ec}, /* '蜢' -> 34594 */ {0x8723, 0xf2de}, /* '蜣' -> 34595 */ {0x8725, 0xf2e1}, /* '蜥' -> 34597 */ {0x8729, 0xf2e8}, /* '蜩' -> 34601 */ {0x872e, 0xf2e2}, /* '蜮' -> 34606 */ {0x8731, 0xf2e7}, /* '蜱' -> 34609 */ {0x8734, 0xf2e6}, /* '蜴' -> 34612 */ {0x8737, 0xf2e9}, /* '蜷' -> 34615 */ {0x873b, 0xf2df}, /* '蜻' -> 34619 */ {0x873e, 0xf2e4}, /* '蜾' -> 34622 */ {0x873f, 0xf2ea}, /* '蜿' -> 34623 */ {0x8747, 0xd3ac}, /* '蝇' -> 34631 */ {0x8748, 0xf2e5}, /* '蝈' -> 34632 */ {0x8749, 0xb2f5}, /* '蝉' -> 34633 */ {0x874c, 0xf2f2}, /* '蝌' -> 34636 */ {0x874e, 0xd0ab}, /* '蝎' -> 34638 */ {0x8753, 0xf2f5}, /* '蝓' -> 34643 */ {0x8757, 0xbbc8}, /* '蝗' -> 34647 */ {0x8759, 0xf2f9}, /* '蝙' -> 34649 */ {0x8760, 0xf2f0}, /* '蝠' -> 34656 */ {0x8763, 0xf2f6}, /* '蝣' -> 34659 */ {0x8764, 0xf2f8}, /* '蝤' -> 34660 */ {0x8765, 0xf2fa}, /* '蝥' -> 34661 */ {0x876e, 0xf2f3}, /* '蝮' -> 34670 */ {0x8770, 0xf2f1}, /* '蝰' -> 34672 */ {0x8774, 0xbafb}, /* '蝴' -> 34676 */ {0x8776, 0xb5fb}, /* '蝶' -> 34678 */ {0x877b, 0xf2ef}, /* '蝻' -> 34683 */ {0x877c, 0xf2f7}, /* '蝼' -> 34684 */ {0x877d, 0xf2ed}, /* '蝽' -> 34685 */ {0x877e, 0xf2ee}, /* '蝾' -> 34686 */ {0x8782, 0xf2eb}, /* '螂' -> 34690 */ {0x8783, 0xf3a6}, /* '螃' -> 34691 */ {0x8785, 0xf3a3}, /* '螅' -> 34693 */ {0x8788, 0xf3a2}, /* '螈' -> 34696 */ {0x878b, 0xf2f4}, /* '螋' -> 34699 */ {0x878d, 0xc8da}, /* '融' -> 34701 */ {0x8793, 0xf2fb}, /* '螓' -> 34707 */ {0x8797, 0xf3a5}, /* '螗' -> 34711 */ {0x879f, 0xc3f8}, /* '螟' -> 34719 */ {0x87a8, 0xf2fd}, /* '螨' -> 34728 */ {0x87ab, 0xf3a7}, /* '螫' -> 34731 */ {0x87ac, 0xf3a9}, /* '螬' -> 34732 */ {0x87ad, 0xf3a4}, /* '螭' -> 34733 */ {0x87af, 0xf2fc}, /* '螯' -> 34735 */ {0x87b3, 0xf3ab}, /* '螳' -> 34739 */ {0x87b5, 0xf3aa}, /* '螵' -> 34741 */ {0x87ba, 0xc2dd}, /* '螺' -> 34746 */ {0x87bd, 0xf3ae}, /* '螽' -> 34749 */ {0x87c0, 0xf3b0}, /* '蟀' -> 34752 */ {0x87c6, 0xf3a1}, /* '蟆' -> 34758 */ {0x87ca, 0xf3b1}, /* '蟊' -> 34762 */ {0x87cb, 0xf3ac}, /* '蟋' -> 34763 */ {0x87d1, 0xf3af}, /* '蟑' -> 34769 */ {0x87d2, 0xf2fe}, /* '蟒' -> 34770 */ {0x87d3, 0xf3ad}, /* '蟓' -> 34771 */ {0x87db, 0xf3b2}, /* '蟛' -> 34779 */ {0x87e0, 0xf3b4}, /* '蟠' -> 34784 */ {0x87e5, 0xf3a8}, /* '蟥' -> 34789 */ {0x87ea, 0xf3b3}, /* '蟪' -> 34794 */ {0x87ee, 0xf3b5}, /* '蟮' -> 34798 */ {0x87f9, 0xd0b7}, /* '蟹' -> 34809 */ {0x87fe, 0xf3b8}, /* '蟾' -> 34814 */ {0x8803, 0xd9f9}, /* '蠃' -> 34819 */ {0x880a, 0xf3b9}, /* '蠊' -> 34826 */ {0x8813, 0xf3b7}, /* '蠓' -> 34835 */ {0x8815, 0xc8e4}, /* '蠕' -> 34837 */ {0x8816, 0xf3b6}, /* '蠖' -> 34838 */ {0x881b, 0xf3ba}, /* '蠛' -> 34843 */ {0x8821, 0xf3bb}, /* '蠡' -> 34849 */ {0x8822, 0xb4c0}, /* '蠢' -> 34850 */ {0x8832, 0xeec3}, /* '蠲' -> 34866 */ {0x8839, 0xf3bc}, /* '蠹' -> 34873 */ {0x883c, 0xf3bd}, /* '蠼' -> 34876 */ {0x8840, 0xd1aa}, /* '血' -> 34880 */ {0x8844, 0xf4ac}, /* '衄' -> 34884 */ {0x8845, 0xd0c6}, /* '衅' -> 34885 */ {0x884c, 0xd0d0}, /* '行' -> 34892 */ {0x884d, 0xd1dc}, /* '衍' -> 34893 */ {0x8854, 0xcfce}, /* '衔' -> 34900 */ {0x8857, 0xbdd6}, /* '街' -> 34903 */ {0x8859, 0xd1c3}, /* '衙' -> 34905 */ {0x8861, 0xbae2}, /* '衡' -> 34913 */ {0x8862, 0xe1e9}, /* '衢' -> 34914 */ {0x8863, 0xd2c2}, /* '衣' -> 34915 */ {0x8864, 0xf1c2}, /* '衤' -> 34916 */ {0x8865, 0xb2b9}, /* '补' -> 34917 */ {0x8868, 0xb1ed}, /* '表' -> 34920 */ {0x8869, 0xf1c3}, /* '衩' -> 34921 */ {0x886b, 0xc9c0}, /* '衫' -> 34923 */ {0x886c, 0xb3c4}, /* '衬' -> 34924 */ {0x886e, 0xd9f2}, /* '衮' -> 34926 */ {0x8870, 0xcba5}, /* '衰' -> 34928 */ {0x8872, 0xf1c4}, /* '衲' -> 34930 */ {0x8877, 0xd6d4}, /* '衷' -> 34935 */ {0x887d, 0xf1c5}, /* '衽' -> 34941 */ {0x887e, 0xf4c0}, /* '衾' -> 34942 */ {0x887f, 0xf1c6}, /* '衿' -> 34943 */ {0x8881, 0xd4ac}, /* '袁' -> 34945 */ {0x8882, 0xf1c7}, /* '袂' -> 34946 */ {0x8884, 0xb0c0}, /* '袄' -> 34948 */ {0x8885, 0xf4c1}, /* '袅' -> 34949 */ {0x8888, 0xf4c2}, /* '袈' -> 34952 */ {0x888b, 0xb4fc}, /* '袋' -> 34955 */ {0x888d, 0xc5db}, /* '袍' -> 34957 */ {0x8892, 0xccbb}, /* '袒' -> 34962 */ {0x8896, 0xd0e4}, /* '袖' -> 34966 */ {0x889c, 0xcde0}, /* '袜' -> 34972 */ {0x88a2, 0xf1c8}, /* '袢' -> 34978 */ {0x88a4, 0xd9f3}, /* '袤' -> 34980 */ {0x88ab, 0xb1bb}, /* '被' -> 34987 */ {0x88ad, 0xcfae}, /* '袭' -> 34989 */ {0x88b1, 0xb8a4}, /* '袱' -> 34993 */ {0x88b7, 0xf1ca}, /* '袷' -> 34999 */ {0x88bc, 0xf1cb}, /* '袼' -> 35004 */ {0x88c1, 0xb2c3}, /* '裁' -> 35009 */ {0x88c2, 0xc1d1}, /* '裂' -> 35010 */ {0x88c5, 0xd7b0}, /* '装' -> 35013 */ {0x88c6, 0xf1c9}, /* '裆' -> 35014 */ {0x88c9, 0xf1cc}, /* '裉' -> 35017 */ {0x88ce, 0xf1ce}, /* '裎' -> 35022 */ {0x88d2, 0xd9f6}, /* '裒' -> 35026 */ {0x88d4, 0xd2e1}, /* '裔' -> 35028 */ {0x88d5, 0xd4a3}, /* '裕' -> 35029 */ {0x88d8, 0xf4c3}, /* '裘' -> 35032 */ {0x88d9, 0xc8b9}, /* '裙' -> 35033 */ {0x88df, 0xf4c4}, /* '裟' -> 35039 */ {0x88e2, 0xf1cd}, /* '裢' -> 35042 */ {0x88e3, 0xf1cf}, /* '裣' -> 35043 */ {0x88e4, 0xbfe3}, /* '裤' -> 35044 */ {0x88e5, 0xf1d0}, /* '裥' -> 35045 */ {0x88e8, 0xf1d4}, /* '裨' -> 35048 */ {0x88f0, 0xf1d6}, /* '裰' -> 35056 */ {0x88f1, 0xf1d1}, /* '裱' -> 35057 */ {0x88f3, 0xc9d1}, /* '裳' -> 35059 */ {0x88f4, 0xc5e1}, /* '裴' -> 35060 */ {0x88f8, 0xc2e3}, /* '裸' -> 35064 */ {0x88f9, 0xb9fc}, /* '裹' -> 35065 */ {0x88fc, 0xf1d3}, /* '裼' -> 35068 */ {0x88fe, 0xf1d5}, /* '裾' -> 35070 */ {0x8902, 0xb9d3}, /* '褂' -> 35074 */ {0x890a, 0xf1db}, /* '褊' -> 35082 */ {0x8910, 0xbad6}, /* '褐' -> 35088 */ {0x8912, 0xb0fd}, /* '褒' -> 35090 */ {0x8913, 0xf1d9}, /* '褓' -> 35091 */ {0x8919, 0xf1d8}, /* '褙' -> 35097 */ {0x891a, 0xf1d2}, /* '褚' -> 35098 */ {0x891b, 0xf1da}, /* '褛' -> 35099 */ {0x8921, 0xf1d7}, /* '褡' -> 35105 */ {0x8925, 0xc8ec}, /* '褥' -> 35109 */ {0x892a, 0xcdca}, /* '褪' -> 35114 */ {0x892b, 0xf1dd}, /* '褫' -> 35115 */ {0x8930, 0xe5bd}, /* '褰' -> 35120 */ {0x8934, 0xf1dc}, /* '褴' -> 35124 */ {0x8936, 0xf1de}, /* '褶' -> 35126 */ {0x8941, 0xf1df}, /* '襁' -> 35137 */ {0x8944, 0xcfe5}, /* '襄' -> 35140 */ {0x895e, 0xf4c5}, /* '襞' -> 35166 */ {0x895f, 0xbdf3}, /* '襟' -> 35167 */ {0x8966, 0xf1e0}, /* '襦' -> 35174 */ {0x897b, 0xf1e1}, /* '襻' -> 35195 */ {0x897f, 0xcef7}, /* '西' -> 35199 */ {0x8981, 0xd2aa}, /* '要' -> 35201 */ {0x8983, 0xf1fb}, /* '覃' -> 35203 */ {0x8986, 0xb8b2}, /* '覆' -> 35206 */ {0x89c1, 0xbcfb}, /* '见' -> 35265 */ {0x89c2, 0xb9db}, /* '观' -> 35266 */ {0x89c4, 0xb9e6}, /* '规' -> 35268 */ {0x89c5, 0xc3d9}, /* '觅' -> 35269 */ {0x89c6, 0xcad3}, /* '视' -> 35270 */ {0x89c7, 0xeae8}, /* '觇' -> 35271 */ {0x89c8, 0xc0c0}, /* '览' -> 35272 */ {0x89c9, 0xbef5}, /* '觉' -> 35273 */ {0x89ca, 0xeae9}, /* '觊' -> 35274 */ {0x89cb, 0xeaea}, /* '觋' -> 35275 */ {0x89cc, 0xeaeb}, /* '觌' -> 35276 */ {0x89ce, 0xeaec}, /* '觎' -> 35278 */ {0x89cf, 0xeaed}, /* '觏' -> 35279 */ {0x89d0, 0xeaee}, /* '觐' -> 35280 */ {0x89d1, 0xeaef}, /* '觑' -> 35281 */ {0x89d2, 0xbdc7}, /* '角' -> 35282 */ {0x89d6, 0xf5fb}, /* '觖' -> 35286 */ {0x89da, 0xf5fd}, /* '觚' -> 35290 */ {0x89dc, 0xf5fe}, /* '觜' -> 35292 */ {0x89de, 0xf5fc}, /* '觞' -> 35294 */ {0x89e3, 0xbde2}, /* '解' -> 35299 */ {0x89e5, 0xf6a1}, /* '觥' -> 35301 */ {0x89e6, 0xb4a5}, /* '触' -> 35302 */ {0x89eb, 0xf6a2}, /* '觫' -> 35307 */ {0x89ef, 0xf6a3}, /* '觯' -> 35311 */ {0x89f3, 0xecb2}, /* '觳' -> 35315 */ {0x8a00, 0xd1d4}, /* '言' -> 35328 */ {0x8a07, 0xd9ea}, /* '訇' -> 35335 */ {0x8a3e, 0xf6a4}, /* '訾' -> 35390 */ {0x8a48, 0xeeba}, /* '詈' -> 35400 */ {0x8a79, 0xd5b2}, /* '詹' -> 35449 */ {0x8a89, 0xd3fe}, /* '誉' -> 35465 */ {0x8a8a, 0xccdc}, /* '誊' -> 35466 */ {0x8a93, 0xcac4}, /* '誓' -> 35475 */ {0x8b07, 0xe5c0}, /* '謇' -> 35591 */ {0x8b26, 0xf6a5}, /* '謦' -> 35622 */ {0x8b66, 0xbeaf}, /* '警' -> 35686 */ {0x8b6c, 0xc6a9}, /* '譬' -> 35692 */ {0x8ba0, 0xdaa5}, /* '讠' -> 35744 */ {0x8ba1, 0xbcc6}, /* '计' -> 35745 */ {0x8ba2, 0xb6a9}, /* '订' -> 35746 */ {0x8ba3, 0xb8bc}, /* '讣' -> 35747 */ {0x8ba4, 0xc8cf}, /* '认' -> 35748 */ {0x8ba5, 0xbca5}, /* '讥' -> 35749 */ {0x8ba6, 0xdaa6}, /* '讦' -> 35750 */ {0x8ba7, 0xdaa7}, /* '讧' -> 35751 */ {0x8ba8, 0xccd6}, /* '讨' -> 35752 */ {0x8ba9, 0xc8c3}, /* '让' -> 35753 */ {0x8baa, 0xdaa8}, /* '讪' -> 35754 */ {0x8bab, 0xc6fd}, /* '讫' -> 35755 */ {0x8bad, 0xd1b5}, /* '训' -> 35757 */ {0x8bae, 0xd2e9}, /* '议' -> 35758 */ {0x8baf, 0xd1b6}, /* '讯' -> 35759 */ {0x8bb0, 0xbcc7}, /* '记' -> 35760 */ {0x8bb2, 0xbdb2}, /* '讲' -> 35762 */ {0x8bb3, 0xbbe4}, /* '讳' -> 35763 */ {0x8bb4, 0xdaa9}, /* '讴' -> 35764 */ {0x8bb5, 0xdaaa}, /* '讵' -> 35765 */ {0x8bb6, 0xd1c8}, /* '讶' -> 35766 */ {0x8bb7, 0xdaab}, /* '讷' -> 35767 */ {0x8bb8, 0xd0ed}, /* '许' -> 35768 */ {0x8bb9, 0xb6ef}, /* '讹' -> 35769 */ {0x8bba, 0xc2db}, /* '论' -> 35770 */ {0x8bbc, 0xcbcf}, /* '讼' -> 35772 */ {0x8bbd, 0xb7ed}, /* '讽' -> 35773 */ {0x8bbe, 0xc9e8}, /* '设' -> 35774 */ {0x8bbf, 0xb7c3}, /* '访' -> 35775 */ {0x8bc0, 0xbef7}, /* '诀' -> 35776 */ {0x8bc1, 0xd6a4}, /* '证' -> 35777 */ {0x8bc2, 0xdaac}, /* '诂' -> 35778 */ {0x8bc3, 0xdaad}, /* '诃' -> 35779 */ {0x8bc4, 0xc6c0}, /* '评' -> 35780 */ {0x8bc5, 0xd7e7}, /* '诅' -> 35781 */ {0x8bc6, 0xcab6}, /* '识' -> 35782 */ {0x8bc8, 0xd5a9}, /* '诈' -> 35784 */ {0x8bc9, 0xcbdf}, /* '诉' -> 35785 */ {0x8bca, 0xd5ef}, /* '诊' -> 35786 */ {0x8bcb, 0xdaae}, /* '诋' -> 35787 */ {0x8bcc, 0xd6df}, /* '诌' -> 35788 */ {0x8bcd, 0xb4ca}, /* '词' -> 35789 */ {0x8bce, 0xdab0}, /* '诎' -> 35790 */ {0x8bcf, 0xdaaf}, /* '诏' -> 35791 */ {0x8bd1, 0xd2eb}, /* '译' -> 35793 */ {0x8bd2, 0xdab1}, /* '诒' -> 35794 */ {0x8bd3, 0xdab2}, /* '诓' -> 35795 */ {0x8bd4, 0xdab3}, /* '诔' -> 35796 */ {0x8bd5, 0xcad4}, /* '试' -> 35797 */ {0x8bd6, 0xdab4}, /* '诖' -> 35798 */ {0x8bd7, 0xcaab}, /* '诗' -> 35799 */ {0x8bd8, 0xdab5}, /* '诘' -> 35800 */ {0x8bd9, 0xdab6}, /* '诙' -> 35801 */ {0x8bda, 0xb3cf}, /* '诚' -> 35802 */ {0x8bdb, 0xd6ef}, /* '诛' -> 35803 */ {0x8bdc, 0xdab7}, /* '诜' -> 35804 */ {0x8bdd, 0xbbb0}, /* '话' -> 35805 */ {0x8bde, 0xb5ae}, /* '诞' -> 35806 */ {0x8bdf, 0xdab8}, /* '诟' -> 35807 */ {0x8be0, 0xdab9}, /* '诠' -> 35808 */ {0x8be1, 0xb9ee}, /* '诡' -> 35809 */ {0x8be2, 0xd1af}, /* '询' -> 35810 */ {0x8be3, 0xd2e8}, /* '诣' -> 35811 */ {0x8be4, 0xdaba}, /* '诤' -> 35812 */ {0x8be5, 0xb8c3}, /* '该' -> 35813 */ {0x8be6, 0xcfea}, /* '详' -> 35814 */ {0x8be7, 0xb2ef}, /* '诧' -> 35815 */ {0x8be8, 0xdabb}, /* '诨' -> 35816 */ {0x8be9, 0xdabc}, /* '诩' -> 35817 */ {0x8beb, 0xbdeb}, /* '诫' -> 35819 */ {0x8bec, 0xcedc}, /* '诬' -> 35820 */ {0x8bed, 0xd3ef}, /* '语' -> 35821 */ {0x8bee, 0xdabd}, /* '诮' -> 35822 */ {0x8bef, 0xcef3}, /* '误' -> 35823 */ {0x8bf0, 0xdabe}, /* '诰' -> 35824 */ {0x8bf1, 0xd3d5}, /* '诱' -> 35825 */ {0x8bf2, 0xbbe5}, /* '诲' -> 35826 */ {0x8bf3, 0xdabf}, /* '诳' -> 35827 */ {0x8bf4, 0xcbb5}, /* '说' -> 35828 */ {0x8bf5, 0xcbd0}, /* '诵' -> 35829 */ {0x8bf6, 0xdac0}, /* '诶' -> 35830 */ {0x8bf7, 0xc7eb}, /* '请' -> 35831 */ {0x8bf8, 0xd6ee}, /* '诸' -> 35832 */ {0x8bf9, 0xdac1}, /* '诹' -> 35833 */ {0x8bfa, 0xc5b5}, /* '诺' -> 35834 */ {0x8bfb, 0xb6c1}, /* '读' -> 35835 */ {0x8bfc, 0xdac2}, /* '诼' -> 35836 */ {0x8bfd, 0xb7cc}, /* '诽' -> 35837 */ {0x8bfe, 0xbfce}, /* '课' -> 35838 */ {0x8bff, 0xdac3}, /* '诿' -> 35839 */ {0x8c00, 0xdac4}, /* '谀' -> 35840 */ {0x8c01, 0xcbad}, /* '谁' -> 35841 */ {0x8c02, 0xdac5}, /* '谂' -> 35842 */ {0x8c03, 0xb5f7}, /* '调' -> 35843 */ {0x8c04, 0xdac6}, /* '谄' -> 35844 */ {0x8c05, 0xc1c2}, /* '谅' -> 35845 */ {0x8c06, 0xd7bb}, /* '谆' -> 35846 */ {0x8c07, 0xdac7}, /* '谇' -> 35847 */ {0x8c08, 0xccb8}, /* '谈' -> 35848 */ {0x8c0a, 0xd2ea}, /* '谊' -> 35850 */ {0x8c0b, 0xc4b1}, /* '谋' -> 35851 */ {0x8c0c, 0xdac8}, /* '谌' -> 35852 */ {0x8c0d, 0xb5fd}, /* '谍' -> 35853 */ {0x8c0e, 0xbbd1}, /* '谎' -> 35854 */ {0x8c0f, 0xdac9}, /* '谏' -> 35855 */ {0x8c10, 0xd0b3}, /* '谐' -> 35856 */ {0x8c11, 0xdaca}, /* '谑' -> 35857 */ {0x8c12, 0xdacb}, /* '谒' -> 35858 */ {0x8c13, 0xcebd}, /* '谓' -> 35859 */ {0x8c14, 0xdacc}, /* '谔' -> 35860 */ {0x8c15, 0xdacd}, /* '谕' -> 35861 */ {0x8c16, 0xdace}, /* '谖' -> 35862 */ {0x8c17, 0xb2f7}, /* '谗' -> 35863 */ {0x8c18, 0xdad1}, /* '谘' -> 35864 */ {0x8c19, 0xdacf}, /* '谙' -> 35865 */ {0x8c1a, 0xd1e8}, /* '谚' -> 35866 */ {0x8c1b, 0xdad0}, /* '谛' -> 35867 */ {0x8c1c, 0xc3d5}, /* '谜' -> 35868 */ {0x8c1d, 0xdad2}, /* '谝' -> 35869 */ {0x8c1f, 0xdad3}, /* '谟' -> 35871 */ {0x8c20, 0xdad4}, /* '谠' -> 35872 */ {0x8c21, 0xdad5}, /* '谡' -> 35873 */ {0x8c22, 0xd0bb}, /* '谢' -> 35874 */ {0x8c23, 0xd2a5}, /* '谣' -> 35875 */ {0x8c24, 0xb0f9}, /* '谤' -> 35876 */ {0x8c25, 0xdad6}, /* '谥' -> 35877 */ {0x8c26, 0xc7ab}, /* '谦' -> 35878 */ {0x8c27, 0xdad7}, /* '谧' -> 35879 */ {0x8c28, 0xbdf7}, /* '谨' -> 35880 */ {0x8c29, 0xc3a1}, /* '谩' -> 35881 */ {0x8c2a, 0xdad8}, /* '谪' -> 35882 */ {0x8c2b, 0xdad9}, /* '谫' -> 35883 */ {0x8c2c, 0xc3fd}, /* '谬' -> 35884 */ {0x8c2d, 0xccb7}, /* '谭' -> 35885 */ {0x8c2e, 0xdada}, /* '谮' -> 35886 */ {0x8c2f, 0xdadb}, /* '谯' -> 35887 */ {0x8c30, 0xc0be}, /* '谰' -> 35888 */ {0x8c31, 0xc6d7}, /* '谱' -> 35889 */ {0x8c32, 0xdadc}, /* '谲' -> 35890 */ {0x8c33, 0xdadd}, /* '谳' -> 35891 */ {0x8c34, 0xc7b4}, /* '谴' -> 35892 */ {0x8c35, 0xdade}, /* '谵' -> 35893 */ {0x8c36, 0xdadf}, /* '谶' -> 35894 */ {0x8c37, 0xb9c8}, /* '谷' -> 35895 */ {0x8c41, 0xbbed}, /* '豁' -> 35905 */ {0x8c46, 0xb6b9}, /* '豆' -> 35910 */ {0x8c47, 0xf4f8}, /* '豇' -> 35911 */ {0x8c49, 0xf4f9}, /* '豉' -> 35913 */ {0x8c4c, 0xcde3}, /* '豌' -> 35916 */ {0x8c55, 0xf5b9}, /* '豕' -> 35925 */ {0x8c5a, 0xebe0}, /* '豚' -> 35930 */ {0x8c61, 0xcff3}, /* '象' -> 35937 */ {0x8c62, 0xbbbf}, /* '豢' -> 35938 */ {0x8c6a, 0xbac0}, /* '豪' -> 35946 */ {0x8c6b, 0xd4a5}, /* '豫' -> 35947 */ {0x8c73, 0xe1d9}, /* '豳' -> 35955 */ {0x8c78, 0xf5f4}, /* '豸' -> 35960 */ {0x8c79, 0xb1aa}, /* '豹' -> 35961 */ {0x8c7a, 0xb2f2}, /* '豺' -> 35962 */ {0x8c82, 0xf5f5}, /* '貂' -> 35970 */ {0x8c85, 0xf5f7}, /* '貅' -> 35973 */ {0x8c89, 0xbad1}, /* '貉' -> 35977 */ {0x8c8a, 0xf5f6}, /* '貊' -> 35978 */ {0x8c8c, 0xc3b2}, /* '貌' -> 35980 */ {0x8c94, 0xf5f9}, /* '貔' -> 35988 */ {0x8c98, 0xf5f8}, /* '貘' -> 35992 */ {0x8d1d, 0xb1b4}, /* '贝' -> 36125 */ {0x8d1e, 0xd5ea}, /* '贞' -> 36126 */ {0x8d1f, 0xb8ba}, /* '负' -> 36127 */ {0x8d21, 0xb9b1}, /* '贡' -> 36129 */ {0x8d22, 0xb2c6}, /* '财' -> 36130 */ {0x8d23, 0xd4f0}, /* '责' -> 36131 */ {0x8d24, 0xcfcd}, /* '贤' -> 36132 */ {0x8d25, 0xb0dc}, /* '败' -> 36133 */ {0x8d26, 0xd5cb}, /* '账' -> 36134 */ {0x8d27, 0xbbf5}, /* '货' -> 36135 */ {0x8d28, 0xd6ca}, /* '质' -> 36136 */ {0x8d29, 0xb7b7}, /* '贩' -> 36137 */ {0x8d2a, 0xccb0}, /* '贪' -> 36138 */ {0x8d2b, 0xc6b6}, /* '贫' -> 36139 */ {0x8d2c, 0xb1e1}, /* '贬' -> 36140 */ {0x8d2d, 0xb9ba}, /* '购' -> 36141 */ {0x8d2e, 0xd6fc}, /* '贮' -> 36142 */ {0x8d2f, 0xb9e1}, /* '贯' -> 36143 */ {0x8d30, 0xb7a1}, /* '贰' -> 36144 */ {0x8d31, 0xbcfa}, /* '贱' -> 36145 */ {0x8d32, 0xeada}, /* '贲' -> 36146 */ {0x8d33, 0xeadb}, /* '贳' -> 36147 */ {0x8d34, 0xccf9}, /* '贴' -> 36148 */ {0x8d35, 0xb9f3}, /* '贵' -> 36149 */ {0x8d36, 0xeadc}, /* '贶' -> 36150 */ {0x8d37, 0xb4fb}, /* '贷' -> 36151 */ {0x8d38, 0xc3b3}, /* '贸' -> 36152 */ {0x8d39, 0xb7d1}, /* '费' -> 36153 */ {0x8d3a, 0xbad8}, /* '贺' -> 36154 */ {0x8d3b, 0xeadd}, /* '贻' -> 36155 */ {0x8d3c, 0xd4f4}, /* '贼' -> 36156 */ {0x8d3d, 0xeade}, /* '贽' -> 36157 */ {0x8d3e, 0xbcd6}, /* '贾' -> 36158 */ {0x8d3f, 0xbbdf}, /* '贿' -> 36159 */ {0x8d40, 0xeadf}, /* '赀' -> 36160 */ {0x8d41, 0xc1de}, /* '赁' -> 36161 */ {0x8d42, 0xc2b8}, /* '赂' -> 36162 */ {0x8d43, 0xd4df}, /* '赃' -> 36163 */ {0x8d44, 0xd7ca}, /* '资' -> 36164 */ {0x8d45, 0xeae0}, /* '赅' -> 36165 */ {0x8d46, 0xeae1}, /* '赆' -> 36166 */ {0x8d47, 0xeae4}, /* '赇' -> 36167 */ {0x8d48, 0xeae2}, /* '赈' -> 36168 */ {0x8d49, 0xeae3}, /* '赉' -> 36169 */ {0x8d4a, 0xc9de}, /* '赊' -> 36170 */ {0x8d4b, 0xb8b3}, /* '赋' -> 36171 */ {0x8d4c, 0xb6c4}, /* '赌' -> 36172 */ {0x8d4d, 0xeae5}, /* '赍' -> 36173 */ {0x8d4e, 0xcaea}, /* '赎' -> 36174 */ {0x8d4f, 0xc9cd}, /* '赏' -> 36175 */ {0x8d50, 0xb4cd}, /* '赐' -> 36176 */ {0x8d53, 0xe2d9}, /* '赓' -> 36179 */ {0x8d54, 0xc5e2}, /* '赔' -> 36180 */ {0x8d55, 0xeae6}, /* '赕' -> 36181 */ {0x8d56, 0xc0b5}, /* '赖' -> 36182 */ {0x8d58, 0xd7b8}, /* '赘' -> 36184 */ {0x8d59, 0xeae7}, /* '赙' -> 36185 */ {0x8d5a, 0xd7ac}, /* '赚' -> 36186 */ {0x8d5b, 0xc8fc}, /* '赛' -> 36187 */ {0x8d5c, 0xd8d3}, /* '赜' -> 36188 */ {0x8d5d, 0xd8cd}, /* '赝' -> 36189 */ {0x8d5e, 0xd4de}, /* '赞' -> 36190 */ {0x8d60, 0xd4f9}, /* '赠' -> 36192 */ {0x8d61, 0xc9c4}, /* '赡' -> 36193 */ {0x8d62, 0xd3ae}, /* '赢' -> 36194 */ {0x8d63, 0xb8d3}, /* '赣' -> 36195 */ {0x8d64, 0xb3e0}, /* '赤' -> 36196 */ {0x8d66, 0xc9e2}, /* '赦' -> 36198 */ {0x8d67, 0xf4f6}, /* '赧' -> 36199 */ {0x8d6b, 0xbad5}, /* '赫' -> 36203 */ {0x8d6d, 0xf4f7}, /* '赭' -> 36205 */ {0x8d70, 0xd7df}, /* '走' -> 36208 */ {0x8d73, 0xf4f1}, /* '赳' -> 36211 */ {0x8d74, 0xb8b0}, /* '赴' -> 36212 */ {0x8d75, 0xd5d4}, /* '赵' -> 36213 */ {0x8d76, 0xb8cf}, /* '赶' -> 36214 */ {0x8d77, 0xc6f0}, /* '起' -> 36215 */ {0x8d81, 0xb3c3}, /* '趁' -> 36225 */ {0x8d84, 0xf4f2}, /* '趄' -> 36228 */ {0x8d85, 0xb3ac}, /* '超' -> 36229 */ {0x8d8a, 0xd4bd}, /* '越' -> 36234 */ {0x8d8b, 0xc7f7}, /* '趋' -> 36235 */ {0x8d91, 0xf4f4}, /* '趑' -> 36241 */ {0x8d94, 0xf4f3}, /* '趔' -> 36244 */ {0x8d9f, 0xcccb}, /* '趟' -> 36255 */ {0x8da3, 0xc8a4}, /* '趣' -> 36259 */ {0x8db1, 0xf4f5}, /* '趱' -> 36273 */ {0x8db3, 0xd7e3}, /* '足' -> 36275 */ {0x8db4, 0xc5bf}, /* '趴' -> 36276 */ {0x8db5, 0xf5c0}, /* '趵' -> 36277 */ {0x8db8, 0xf5bb}, /* '趸' -> 36280 */ {0x8dba, 0xf5c3}, /* '趺' -> 36282 */ {0x8dbc, 0xf5c2}, /* '趼' -> 36284 */ {0x8dbe, 0xd6ba}, /* '趾' -> 36286 */ {0x8dbf, 0xf5c1}, /* '趿' -> 36287 */ {0x8dc3, 0xd4be}, /* '跃' -> 36291 */ {0x8dc4, 0xf5c4}, /* '跄' -> 36292 */ {0x8dc6, 0xf5cc}, /* '跆' -> 36294 */ {0x8dcb, 0xb0cf}, /* '跋' -> 36299 */ {0x8dcc, 0xb5f8}, /* '跌' -> 36300 */ {0x8dce, 0xf5c9}, /* '跎' -> 36302 */ {0x8dcf, 0xf5ca}, /* '跏' -> 36303 */ {0x8dd1, 0xc5dc}, /* '跑' -> 36305 */ {0x8dd6, 0xf5c5}, /* '跖' -> 36310 */ {0x8dd7, 0xf5c6}, /* '跗' -> 36311 */ {0x8dda, 0xf5c7}, /* '跚' -> 36314 */ {0x8ddb, 0xf5cb}, /* '跛' -> 36315 */ {0x8ddd, 0xbee0}, /* '距' -> 36317 */ {0x8dde, 0xf5c8}, /* '跞' -> 36318 */ {0x8ddf, 0xb8fa}, /* '跟' -> 36319 */ {0x8de3, 0xf5d0}, /* '跣' -> 36323 */ {0x8de4, 0xf5d3}, /* '跤' -> 36324 */ {0x8de8, 0xbfe7}, /* '跨' -> 36328 */ {0x8dea, 0xb9f2}, /* '跪' -> 36330 */ {0x8deb, 0xf5bc}, /* '跫' -> 36331 */ {0x8dec, 0xf5cd}, /* '跬' -> 36332 */ {0x8def, 0xc2b7}, /* '路' -> 36335 */ {0x8df3, 0xccf8}, /* '跳' -> 36339 */ {0x8df5, 0xbcf9}, /* '践' -> 36341 */ {0x8df7, 0xf5ce}, /* '跷' -> 36343 */ {0x8df8, 0xf5cf}, /* '跸' -> 36344 */ {0x8df9, 0xf5d1}, /* '跹' -> 36345 */ {0x8dfa, 0xb6e5}, /* '跺' -> 36346 */ {0x8dfb, 0xf5d2}, /* '跻' -> 36347 */ {0x8dfd, 0xf5d5}, /* '跽' -> 36349 */ {0x8e05, 0xf5bd}, /* '踅' -> 36357 */ {0x8e09, 0xf5d4}, /* '踉' -> 36361 */ {0x8e0a, 0xd3bb}, /* '踊' -> 36362 */ {0x8e0c, 0xb3ec}, /* '踌' -> 36364 */ {0x8e0f, 0xcca4}, /* '踏' -> 36367 */ {0x8e14, 0xf5d6}, /* '踔' -> 36372 */ {0x8e1d, 0xf5d7}, /* '踝' -> 36381 */ {0x8e1e, 0xbee1}, /* '踞' -> 36382 */ {0x8e1f, 0xf5d8}, /* '踟' -> 36383 */ {0x8e22, 0xccdf}, /* '踢' -> 36386 */ {0x8e23, 0xf5db}, /* '踣' -> 36387 */ {0x8e29, 0xb2c8}, /* '踩' -> 36393 */ {0x8e2a, 0xd7d9}, /* '踪' -> 36394 */ {0x8e2c, 0xf5d9}, /* '踬' -> 36396 */ {0x8e2e, 0xf5da}, /* '踮' -> 36398 */ {0x8e2f, 0xf5dc}, /* '踯' -> 36399 */ {0x8e31, 0xf5e2}, /* '踱' -> 36401 */ {0x8e35, 0xf5e0}, /* '踵' -> 36405 */ {0x8e39, 0xf5df}, /* '踹' -> 36409 */ {0x8e3a, 0xf5dd}, /* '踺' -> 36410 */ {0x8e3d, 0xf5e1}, /* '踽' -> 36413 */ {0x8e40, 0xf5de}, /* '蹀' -> 36416 */ {0x8e41, 0xf5e4}, /* '蹁' -> 36417 */ {0x8e42, 0xf5e5}, /* '蹂' -> 36418 */ {0x8e44, 0xcce3}, /* '蹄' -> 36420 */ {0x8e47, 0xe5bf}, /* '蹇' -> 36423 */ {0x8e48, 0xb5b8}, /* '蹈' -> 36424 */ {0x8e49, 0xf5e3}, /* '蹉' -> 36425 */ {0x8e4a, 0xf5e8}, /* '蹊' -> 36426 */ {0x8e4b, 0xcca3}, /* '蹋' -> 36427 */ {0x8e51, 0xf5e6}, /* '蹑' -> 36433 */ {0x8e52, 0xf5e7}, /* '蹒' -> 36434 */ {0x8e59, 0xf5be}, /* '蹙' -> 36441 */ {0x8e66, 0xb1c4}, /* '蹦' -> 36454 */ {0x8e69, 0xf5bf}, /* '蹩' -> 36457 */ {0x8e6c, 0xb5c5}, /* '蹬' -> 36460 */ {0x8e6d, 0xb2e4}, /* '蹭' -> 36461 */ {0x8e6f, 0xf5ec}, /* '蹯' -> 36463 */ {0x8e70, 0xf5e9}, /* '蹰' -> 36464 */ {0x8e72, 0xb6d7}, /* '蹲' -> 36466 */ {0x8e74, 0xf5ed}, /* '蹴' -> 36468 */ {0x8e76, 0xf5ea}, /* '蹶' -> 36470 */ {0x8e7c, 0xf5eb}, /* '蹼' -> 36476 */ {0x8e7f, 0xb4da}, /* '蹿' -> 36479 */ {0x8e81, 0xd4ea}, /* '躁' -> 36481 */ {0x8e85, 0xf5ee}, /* '躅' -> 36485 */ {0x8e87, 0xb3f9}, /* '躇' -> 36487 */ {0x8e8f, 0xf5ef}, /* '躏' -> 36495 */ {0x8e90, 0xf5f1}, /* '躐' -> 36496 */ {0x8e94, 0xf5f0}, /* '躔' -> 36500 */ {0x8e9c, 0xf5f2}, /* '躜' -> 36508 */ {0x8e9e, 0xf5f3}, /* '躞' -> 36510 */ {0x8eab, 0xc9ed}, /* '身' -> 36523 */ {0x8eac, 0xb9aa}, /* '躬' -> 36524 */ {0x8eaf, 0xc7fb}, /* '躯' -> 36527 */ {0x8eb2, 0xb6e3}, /* '躲' -> 36530 */ {0x8eba, 0xccc9}, /* '躺' -> 36538 */ {0x8ece, 0xeaa6}, /* '軎' -> 36558 */ {0x8f66, 0xb3b5}, /* '车' -> 36710 */ {0x8f67, 0xd4fe}, /* '轧' -> 36711 */ {0x8f68, 0xb9ec}, /* '轨' -> 36712 */ {0x8f69, 0xd0f9}, /* '轩' -> 36713 */ {0x8f6b, 0xe9ed}, /* '轫' -> 36715 */ {0x8f6c, 0xd7aa}, /* '转' -> 36716 */ {0x8f6d, 0xe9ee}, /* '轭' -> 36717 */ {0x8f6e, 0xc2d6}, /* '轮' -> 36718 */ {0x8f6f, 0xc8ed}, /* '软' -> 36719 */ {0x8f70, 0xbae4}, /* '轰' -> 36720 */ {0x8f71, 0xe9ef}, /* '轱' -> 36721 */ {0x8f72, 0xe9f0}, /* '轲' -> 36722 */ {0x8f73, 0xe9f1}, /* '轳' -> 36723 */ {0x8f74, 0xd6e1}, /* '轴' -> 36724 */ {0x8f75, 0xe9f2}, /* '轵' -> 36725 */ {0x8f76, 0xe9f3}, /* '轶' -> 36726 */ {0x8f77, 0xe9f5}, /* '轷' -> 36727 */ {0x8f78, 0xe9f4}, /* '轸' -> 36728 */ {0x8f79, 0xe9f6}, /* '轹' -> 36729 */ {0x8f7a, 0xe9f7}, /* '轺' -> 36730 */ {0x8f7b, 0xc7e1}, /* '轻' -> 36731 */ {0x8f7c, 0xe9f8}, /* '轼' -> 36732 */ {0x8f7d, 0xd4d8}, /* '载' -> 36733 */ {0x8f7e, 0xe9f9}, /* '轾' -> 36734 */ {0x8f7f, 0xbdce}, /* '轿' -> 36735 */ {0x8f81, 0xe9fa}, /* '辁' -> 36737 */ {0x8f82, 0xe9fb}, /* '辂' -> 36738 */ {0x8f83, 0xbdcf}, /* '较' -> 36739 */ {0x8f84, 0xe9fc}, /* '辄' -> 36740 */ {0x8f85, 0xb8a8}, /* '辅' -> 36741 */ {0x8f86, 0xc1be}, /* '辆' -> 36742 */ {0x8f87, 0xe9fd}, /* '辇' -> 36743 */ {0x8f88, 0xb1b2}, /* '辈' -> 36744 */ {0x8f89, 0xbbd4}, /* '辉' -> 36745 */ {0x8f8a, 0xb9f5}, /* '辊' -> 36746 */ {0x8f8b, 0xe9fe}, /* '辋' -> 36747 */ {0x8f8d, 0xeaa1}, /* '辍' -> 36749 */ {0x8f8e, 0xeaa2}, /* '辎' -> 36750 */ {0x8f8f, 0xeaa3}, /* '辏' -> 36751 */ {0x8f90, 0xb7f8}, /* '辐' -> 36752 */ {0x8f91, 0xbcad}, /* '辑' -> 36753 */ {0x8f93, 0xcae4}, /* '输' -> 36755 */ {0x8f94, 0xe0ce}, /* '辔' -> 36756 */ {0x8f95, 0xd4af}, /* '辕' -> 36757 */ {0x8f96, 0xcfbd}, /* '辖' -> 36758 */ {0x8f97, 0xd5b7}, /* '辗' -> 36759 */ {0x8f98, 0xeaa4}, /* '辘' -> 36760 */ {0x8f99, 0xd5de}, /* '辙' -> 36761 */ {0x8f9a, 0xeaa5}, /* '辚' -> 36762 */ {0x8f9b, 0xd0c1}, /* '辛' -> 36763 */ {0x8f9c, 0xb9bc}, /* '辜' -> 36764 */ {0x8f9e, 0xb4c7}, /* '辞' -> 36766 */ {0x8f9f, 0xb1d9}, /* '辟' -> 36767 */ {0x8fa3, 0xc0b1}, /* '辣' -> 36771 */ {0x8fa8, 0xb1e6}, /* '辨' -> 36776 */ {0x8fa9, 0xb1e7}, /* '辩' -> 36777 */ {0x8fab, 0xb1e8}, /* '辫' -> 36779 */ {0x8fb0, 0xb3bd}, /* '辰' -> 36784 */ {0x8fb1, 0xc8e8}, /* '辱' -> 36785 */ {0x8fb6, 0xe5c1}, /* '辶' -> 36790 */ {0x8fb9, 0xb1df}, /* '边' -> 36793 */ {0x8fbd, 0xc1c9}, /* '辽' -> 36797 */ {0x8fbe, 0xb4ef}, /* '达' -> 36798 */ {0x8fc1, 0xc7a8}, /* '迁' -> 36801 */ {0x8fc2, 0xd3d8}, /* '迂' -> 36802 */ {0x8fc4, 0xc6f9}, /* '迄' -> 36804 */ {0x8fc5, 0xd1b8}, /* '迅' -> 36805 */ {0x8fc7, 0xb9fd}, /* '过' -> 36807 */ {0x8fc8, 0xc2f5}, /* '迈' -> 36808 */ {0x8fce, 0xd3ad}, /* '迎' -> 36814 */ {0x8fd0, 0xd4cb}, /* '运' -> 36816 */ {0x8fd1, 0xbdfc}, /* '近' -> 36817 */ {0x8fd3, 0xe5c2}, /* '迓' -> 36819 */ {0x8fd4, 0xb7b5}, /* '返' -> 36820 */ {0x8fd5, 0xe5c3}, /* '迕' -> 36821 */ {0x8fd8, 0xbbb9}, /* '还' -> 36824 */ {0x8fd9, 0xd5e2}, /* '这' -> 36825 */ {0x8fdb, 0xbdf8}, /* '进' -> 36827 */ {0x8fdc, 0xd4b6}, /* '远' -> 36828 */ {0x8fdd, 0xcea5}, /* '违' -> 36829 */ {0x8fde, 0xc1ac}, /* '连' -> 36830 */ {0x8fdf, 0xb3d9}, /* '迟' -> 36831 */ {0x8fe2, 0xccf6}, /* '迢' -> 36834 */ {0x8fe4, 0xe5c6}, /* '迤' -> 36836 */ {0x8fe5, 0xe5c4}, /* '迥' -> 36837 */ {0x8fe6, 0xe5c8}, /* '迦' -> 36838 */ {0x8fe8, 0xe5ca}, /* '迨' -> 36840 */ {0x8fe9, 0xe5c7}, /* '迩' -> 36841 */ {0x8fea, 0xb5cf}, /* '迪' -> 36842 */ {0x8feb, 0xc6c8}, /* '迫' -> 36843 */ {0x8fed, 0xb5fc}, /* '迭' -> 36845 */ {0x8fee, 0xe5c5}, /* '迮' -> 36846 */ {0x8ff0, 0xcaf6}, /* '述' -> 36848 */ {0x8ff3, 0xe5c9}, /* '迳' -> 36851 */ {0x8ff7, 0xc3d4}, /* '迷' -> 36855 */ {0x8ff8, 0xb1c5}, /* '迸' -> 36856 */ {0x8ff9, 0xbca3}, /* '迹' -> 36857 */ {0x8ffd, 0xd7b7}, /* '追' -> 36861 */ {0x9000, 0xcdcb}, /* '退' -> 36864 */ {0x9001, 0xcbcd}, /* '送' -> 36865 */ {0x9002, 0xcaca}, /* '适' -> 36866 */ {0x9003, 0xccd3}, /* '逃' -> 36867 */ {0x9004, 0xe5cc}, /* '逄' -> 36868 */ {0x9005, 0xe5cb}, /* '逅' -> 36869 */ {0x9006, 0xc4e6}, /* '逆' -> 36870 */ {0x9009, 0xd1a1}, /* '选' -> 36873 */ {0x900a, 0xd1b7}, /* '逊' -> 36874 */ {0x900b, 0xe5cd}, /* '逋' -> 36875 */ {0x900d, 0xe5d0}, /* '逍' -> 36877 */ {0x900f, 0xcdb8}, /* '透' -> 36879 */ {0x9010, 0xd6f0}, /* '逐' -> 36880 */ {0x9011, 0xe5cf}, /* '逑' -> 36881 */ {0x9012, 0xb5dd}, /* '递' -> 36882 */ {0x9014, 0xcdbe}, /* '途' -> 36884 */ {0x9016, 0xe5d1}, /* '逖' -> 36886 */ {0x9017, 0xb6ba}, /* '逗' -> 36887 */ {0x901a, 0xcda8}, /* '通' -> 36890 */ {0x901b, 0xb9e4}, /* '逛' -> 36891 */ {0x901d, 0xcac5}, /* '逝' -> 36893 */ {0x901e, 0xb3d1}, /* '逞' -> 36894 */ {0x901f, 0xcbd9}, /* '速' -> 36895 */ {0x9020, 0xd4ec}, /* '造' -> 36896 */ {0x9021, 0xe5d2}, /* '逡' -> 36897 */ {0x9022, 0xb7ea}, /* '逢' -> 36898 */ {0x9026, 0xe5ce}, /* '逦' -> 36902 */ {0x902d, 0xe5d5}, /* '逭' -> 36909 */ {0x902e, 0xb4fe}, /* '逮' -> 36910 */ {0x902f, 0xe5d6}, /* '逯' -> 36911 */ {0x9035, 0xe5d3}, /* '逵' -> 36917 */ {0x9036, 0xe5d4}, /* '逶' -> 36918 */ {0x9038, 0xd2dd}, /* '逸' -> 36920 */ {0x903b, 0xc2df}, /* '逻' -> 36923 */ {0x903c, 0xb1c6}, /* '逼' -> 36924 */ {0x903e, 0xd3e2}, /* '逾' -> 36926 */ {0x9041, 0xb6dd}, /* '遁' -> 36929 */ {0x9042, 0xcbec}, /* '遂' -> 36930 */ {0x9044, 0xe5d7}, /* '遄' -> 36932 */ {0x9047, 0xd3f6}, /* '遇' -> 36935 */ {0x904d, 0xb1e9}, /* '遍' -> 36941 */ {0x904f, 0xb6f4}, /* '遏' -> 36943 */ {0x9050, 0xe5da}, /* '遐' -> 36944 */ {0x9051, 0xe5d8}, /* '遑' -> 36945 */ {0x9052, 0xe5d9}, /* '遒' -> 36946 */ {0x9053, 0xb5c0}, /* '道' -> 36947 */ {0x9057, 0xd2c5}, /* '遗' -> 36951 */ {0x9058, 0xe5dc}, /* '遘' -> 36952 */ {0x905b, 0xe5de}, /* '遛' -> 36955 */ {0x9062, 0xe5dd}, /* '遢' -> 36962 */ {0x9063, 0xc7b2}, /* '遣' -> 36963 */ {0x9065, 0xd2a3}, /* '遥' -> 36965 */ {0x9068, 0xe5db}, /* '遨' -> 36968 */ {0x906d, 0xd4e2}, /* '遭' -> 36973 */ {0x906e, 0xd5da}, /* '遮' -> 36974 */ {0x9074, 0xe5e0}, /* '遴' -> 36980 */ {0x9075, 0xd7f1}, /* '遵' -> 36981 */ {0x907d, 0xe5e1}, /* '遽' -> 36989 */ {0x907f, 0xb1dc}, /* '避' -> 36991 */ {0x9080, 0xd1fb}, /* '邀' -> 36992 */ {0x9082, 0xe5e2}, /* '邂' -> 36994 */ {0x9083, 0xe5e4}, /* '邃' -> 36995 */ {0x9088, 0xe5e3}, /* '邈' -> 37000 */ {0x908b, 0xe5e5}, /* '邋' -> 37003 */ {0x9091, 0xd2d8}, /* '邑' -> 37009 */ {0x9093, 0xb5cb}, /* '邓' -> 37011 */ {0x9095, 0xe7df}, /* '邕' -> 37013 */ {0x9097, 0xdaf5}, /* '邗' -> 37015 */ {0x9099, 0xdaf8}, /* '邙' -> 37017 */ {0x909b, 0xdaf6}, /* '邛' -> 37019 */ {0x909d, 0xdaf7}, /* '邝' -> 37021 */ {0x90a1, 0xdafa}, /* '邡' -> 37025 */ {0x90a2, 0xd0cf}, /* '邢' -> 37026 */ {0x90a3, 0xc4c7}, /* '那' -> 37027 */ {0x90a6, 0xb0ee}, /* '邦' -> 37030 */ {0x90aa, 0xd0b0}, /* '邪' -> 37034 */ {0x90ac, 0xdaf9}, /* '邬' -> 37036 */ {0x90ae, 0xd3ca}, /* '邮' -> 37038 */ {0x90af, 0xbaaa}, /* '邯' -> 37039 */ {0x90b0, 0xdba2}, /* '邰' -> 37040 */ {0x90b1, 0xc7f1}, /* '邱' -> 37041 */ {0x90b3, 0xdafc}, /* '邳' -> 37043 */ {0x90b4, 0xdafb}, /* '邴' -> 37044 */ {0x90b5, 0xc9db}, /* '邵' -> 37045 */ {0x90b6, 0xdafd}, /* '邶' -> 37046 */ {0x90b8, 0xdba1}, /* '邸' -> 37048 */ {0x90b9, 0xd7de}, /* '邹' -> 37049 */ {0x90ba, 0xdafe}, /* '邺' -> 37050 */ {0x90bb, 0xc1da}, /* '邻' -> 37051 */ {0x90be, 0xdba5}, /* '邾' -> 37054 */ {0x90c1, 0xd3f4}, /* '郁' -> 37057 */ {0x90c4, 0xdba7}, /* '郄' -> 37060 */ {0x90c5, 0xdba4}, /* '郅' -> 37061 */ {0x90c7, 0xdba8}, /* '郇' -> 37063 */ {0x90ca, 0xbdbc}, /* '郊' -> 37066 */ {0x90ce, 0xc0c9}, /* '郎' -> 37070 */ {0x90cf, 0xdba3}, /* '郏' -> 37071 */ {0x90d0, 0xdba6}, /* '郐' -> 37072 */ {0x90d1, 0xd6a3}, /* '郑' -> 37073 */ {0x90d3, 0xdba9}, /* '郓' -> 37075 */ {0x90d7, 0xdbad}, /* '郗' -> 37079 */ {0x90db, 0xdbae}, /* '郛' -> 37083 */ {0x90dc, 0xdbac}, /* '郜' -> 37084 */ {0x90dd, 0xbac2}, /* '郝' -> 37085 */ {0x90e1, 0xbfa4}, /* '郡' -> 37089 */ {0x90e2, 0xdbab}, /* '郢' -> 37090 */ {0x90e6, 0xdbaa}, /* '郦' -> 37094 */ {0x90e7, 0xd4c7}, /* '郧' -> 37095 */ {0x90e8, 0xb2bf}, /* '部' -> 37096 */ {0x90eb, 0xdbaf}, /* '郫' -> 37099 */ {0x90ed, 0xb9f9}, /* '郭' -> 37101 */ {0x90ef, 0xdbb0}, /* '郯' -> 37103 */ {0x90f4, 0xb3bb}, /* '郴' -> 37108 */ {0x90f8, 0xb5a6}, /* '郸' -> 37112 */ {0x90fd, 0xb6bc}, /* '都' -> 37117 */ {0x90fe, 0xdbb1}, /* '郾' -> 37118 */ {0x9102, 0xb6f5}, /* '鄂' -> 37122 */ {0x9104, 0xdbb2}, /* '鄄' -> 37124 */ {0x9119, 0xb1c9}, /* '鄙' -> 37145 */ {0x911e, 0xdbb4}, /* '鄞' -> 37150 */ {0x9122, 0xdbb3}, /* '鄢' -> 37154 */ {0x9123, 0xdbb5}, /* '鄣' -> 37155 */ {0x912f, 0xdbb7}, /* '鄯' -> 37167 */ {0x9131, 0xdbb6}, /* '鄱' -> 37169 */ {0x9139, 0xdbb8}, /* '鄹' -> 37177 */ {0x9143, 0xdbb9}, /* '酃' -> 37187 */ {0x9146, 0xdbba}, /* '酆' -> 37190 */ {0x9149, 0xd3cf}, /* '酉' -> 37193 */ {0x914a, 0xf4fa}, /* '酊' -> 37194 */ {0x914b, 0xc7f5}, /* '酋' -> 37195 */ {0x914c, 0xd7c3}, /* '酌' -> 37196 */ {0x914d, 0xc5e4}, /* '配' -> 37197 */ {0x914e, 0xf4fc}, /* '酎' -> 37198 */ {0x914f, 0xf4fd}, /* '酏' -> 37199 */ {0x9150, 0xf4fb}, /* '酐' -> 37200 */ {0x9152, 0xbec6}, /* '酒' -> 37202 */ {0x9157, 0xd0ef}, /* '酗' -> 37207 */ {0x915a, 0xb7d3}, /* '酚' -> 37210 */ {0x915d, 0xd4cd}, /* '酝' -> 37213 */ {0x915e, 0xccaa}, /* '酞' -> 37214 */ {0x9161, 0xf5a2}, /* '酡' -> 37217 */ {0x9162, 0xf5a1}, /* '酢' -> 37218 */ {0x9163, 0xbaa8}, /* '酣' -> 37219 */ {0x9164, 0xf4fe}, /* '酤' -> 37220 */ {0x9165, 0xcbd6}, /* '酥' -> 37221 */ {0x9169, 0xf5a4}, /* '酩' -> 37225 */ {0x916a, 0xc0d2}, /* '酪' -> 37226 */ {0x916c, 0xb3ea}, /* '酬' -> 37228 */ {0x916e, 0xcdaa}, /* '酮' -> 37230 */ {0x916f, 0xf5a5}, /* '酯' -> 37231 */ {0x9170, 0xf5a3}, /* '酰' -> 37232 */ {0x9171, 0xbdb4}, /* '酱' -> 37233 */ {0x9172, 0xf5a8}, /* '酲' -> 37234 */ {0x9174, 0xf5a9}, /* '酴' -> 37236 */ {0x9175, 0xbdcd}, /* '酵' -> 37237 */ {0x9176, 0xc3b8}, /* '酶' -> 37238 */ {0x9177, 0xbfe1}, /* '酷' -> 37239 */ {0x9178, 0xcbe1}, /* '酸' -> 37240 */ {0x9179, 0xf5aa}, /* '酹' -> 37241 */ {0x917d, 0xf5a6}, /* '酽' -> 37245 */ {0x917e, 0xf5a7}, /* '酾' -> 37246 */ {0x917f, 0xc4f0}, /* '酿' -> 37247 */ {0x9185, 0xf5ac}, /* '醅' -> 37253 */ {0x9187, 0xb4bc}, /* '醇' -> 37255 */ {0x9189, 0xd7ed}, /* '醉' -> 37257 */ {0x918b, 0xb4d7}, /* '醋' -> 37259 */ {0x918c, 0xf5ab}, /* '醌' -> 37260 */ {0x918d, 0xf5ae}, /* '醍' -> 37261 */ {0x9190, 0xf5ad}, /* '醐' -> 37264 */ {0x9191, 0xf5af}, /* '醑' -> 37265 */ {0x9192, 0xd0d1}, /* '醒' -> 37266 */ {0x919a, 0xc3d1}, /* '醚' -> 37274 */ {0x919b, 0xc8a9}, /* '醛' -> 37275 */ {0x91a2, 0xf5b0}, /* '醢' -> 37282 */ {0x91a3, 0xf5b1}, /* '醣' -> 37283 */ {0x91aa, 0xf5b2}, /* '醪' -> 37290 */ {0x91ad, 0xf5b3}, /* '醭' -> 37293 */ {0x91ae, 0xf5b4}, /* '醮' -> 37294 */ {0x91af, 0xf5b5}, /* '醯' -> 37295 */ {0x91b4, 0xf5b7}, /* '醴' -> 37300 */ {0x91b5, 0xf5b6}, /* '醵' -> 37301 */ {0x91ba, 0xf5b8}, /* '醺' -> 37306 */ {0x91c7, 0xb2c9}, /* '采' -> 37319 */ {0x91c9, 0xd3d4}, /* '釉' -> 37321 */ {0x91ca, 0xcacd}, /* '释' -> 37322 */ {0x91cc, 0xc0ef}, /* '里' -> 37324 */ {0x91cd, 0xd6d8}, /* '重' -> 37325 */ {0x91ce, 0xd2b0}, /* '野' -> 37326 */ {0x91cf, 0xc1bf}, /* '量' -> 37327 */ {0x91d1, 0xbdf0}, /* '金' -> 37329 */ {0x91dc, 0xb8aa}, /* '釜' -> 37340 */ {0x9274, 0xbcf8}, /* '鉴' -> 37492 */ {0x928e, 0xf6c6}, /* '銎' -> 37518 */ {0x92ae, 0xf6c7}, /* '銮' -> 37550 */ {0x92c8, 0xf6c8}, /* '鋈' -> 37576 */ {0x933e, 0xf6c9}, /* '錾' -> 37694 */ {0x936a, 0xf6ca}, /* '鍪' -> 37738 */ {0x938f, 0xf6cc}, /* '鎏' -> 37775 */ {0x93ca, 0xf6cb}, /* '鏊' -> 37834 */ {0x93d6, 0xf7e9}, /* '鏖' -> 37846 */ {0x943e, 0xf6cd}, /* '鐾' -> 37950 */ {0x946b, 0xf6ce}, /* '鑫' -> 37995 */ {0x9485, 0xeec4}, /* '钅' -> 38021 */ {0x9486, 0xeec5}, /* '钆' -> 38022 */ {0x9487, 0xeec6}, /* '钇' -> 38023 */ {0x9488, 0xd5eb}, /* '针' -> 38024 */ {0x9489, 0xb6a4}, /* '钉' -> 38025 */ {0x948a, 0xeec8}, /* '钊' -> 38026 */ {0x948b, 0xeec7}, /* '钋' -> 38027 */ {0x948c, 0xeec9}, /* '钌' -> 38028 */ {0x948d, 0xeeca}, /* '钍' -> 38029 */ {0x948e, 0xc7a5}, /* '钎' -> 38030 */ {0x948f, 0xeecb}, /* '钏' -> 38031 */ {0x9490, 0xeecc}, /* '钐' -> 38032 */ {0x9492, 0xb7b0}, /* '钒' -> 38034 */ {0x9493, 0xb5f6}, /* '钓' -> 38035 */ {0x9494, 0xeecd}, /* '钔' -> 38036 */ {0x9495, 0xeecf}, /* '钕' -> 38037 */ {0x9497, 0xeece}, /* '钗' -> 38039 */ {0x9499, 0xb8c6}, /* '钙' -> 38041 */ {0x949a, 0xeed0}, /* '钚' -> 38042 */ {0x949b, 0xeed1}, /* '钛' -> 38043 */ {0x949c, 0xeed2}, /* '钜' -> 38044 */ {0x949d, 0xb6db}, /* '钝' -> 38045 */ {0x949e, 0xb3ae}, /* '钞' -> 38046 */ {0x949f, 0xd6d3}, /* '钟' -> 38047 */ {0x94a0, 0xc4c6}, /* '钠' -> 38048 */ {0x94a1, 0xb1b5}, /* '钡' -> 38049 */ {0x94a2, 0xb8d6}, /* '钢' -> 38050 */ {0x94a3, 0xeed3}, /* '钣' -> 38051 */ {0x94a4, 0xeed4}, /* '钤' -> 38052 */ {0x94a5, 0xd4bf}, /* '钥' -> 38053 */ {0x94a6, 0xc7d5}, /* '钦' -> 38054 */ {0x94a7, 0xbefb}, /* '钧' -> 38055 */ {0x94a8, 0xced9}, /* '钨' -> 38056 */ {0x94a9, 0xb9b3}, /* '钩' -> 38057 */ {0x94aa, 0xeed6}, /* '钪' -> 38058 */ {0x94ab, 0xeed5}, /* '钫' -> 38059 */ {0x94ac, 0xeed8}, /* '钬' -> 38060 */ {0x94ad, 0xeed7}, /* '钭' -> 38061 */ {0x94ae, 0xc5a5}, /* '钮' -> 38062 */ {0x94af, 0xeed9}, /* '钯' -> 38063 */ {0x94b0, 0xeeda}, /* '钰' -> 38064 */ {0x94b1, 0xc7ae}, /* '钱' -> 38065 */ {0x94b2, 0xeedb}, /* '钲' -> 38066 */ {0x94b3, 0xc7af}, /* '钳' -> 38067 */ {0x94b4, 0xeedc}, /* '钴' -> 38068 */ {0x94b5, 0xb2a7}, /* '钵' -> 38069 */ {0x94b6, 0xeedd}, /* '钶' -> 38070 */ {0x94b7, 0xeede}, /* '钷' -> 38071 */ {0x94b8, 0xeedf}, /* '钸' -> 38072 */ {0x94b9, 0xeee0}, /* '钹' -> 38073 */ {0x94ba, 0xeee1}, /* '钺' -> 38074 */ {0x94bb, 0xd7ea}, /* '钻' -> 38075 */ {0x94bc, 0xeee2}, /* '钼' -> 38076 */ {0x94bd, 0xeee3}, /* '钽' -> 38077 */ {0x94be, 0xbcd8}, /* '钾' -> 38078 */ {0x94bf, 0xeee4}, /* '钿' -> 38079 */ {0x94c0, 0xd3cb}, /* '铀' -> 38080 */ {0x94c1, 0xccfa}, /* '铁' -> 38081 */ {0x94c2, 0xb2ac}, /* '铂' -> 38082 */ {0x94c3, 0xc1e5}, /* '铃' -> 38083 */ {0x94c4, 0xeee5}, /* '铄' -> 38084 */ {0x94c5, 0xc7a6}, /* '铅' -> 38085 */ {0x94c6, 0xc3ad}, /* '铆' -> 38086 */ {0x94c8, 0xeee6}, /* '铈' -> 38088 */ {0x94c9, 0xeee7}, /* '铉' -> 38089 */ {0x94ca, 0xeee8}, /* '铊' -> 38090 */ {0x94cb, 0xeee9}, /* '铋' -> 38091 */ {0x94cc, 0xeeea}, /* '铌' -> 38092 */ {0x94cd, 0xeeeb}, /* '铍' -> 38093 */ {0x94ce, 0xeeec}, /* '铎' -> 38094 */ {0x94d0, 0xeeed}, /* '铐' -> 38096 */ {0x94d1, 0xeeee}, /* '铑' -> 38097 */ {0x94d2, 0xeeef}, /* '铒' -> 38098 */ {0x94d5, 0xeef0}, /* '铕' -> 38101 */ {0x94d6, 0xeef1}, /* '铖' -> 38102 */ {0x94d7, 0xeef2}, /* '铗' -> 38103 */ {0x94d8, 0xeef4}, /* '铘' -> 38104 */ {0x94d9, 0xeef3}, /* '铙' -> 38105 */ {0x94db, 0xeef5}, /* '铛' -> 38107 */ {0x94dc, 0xcdad}, /* '铜' -> 38108 */ {0x94dd, 0xc2c1}, /* '铝' -> 38109 */ {0x94de, 0xeef6}, /* '铞' -> 38110 */ {0x94df, 0xeef7}, /* '铟' -> 38111 */ {0x94e0, 0xeef8}, /* '铠' -> 38112 */ {0x94e1, 0xd5a1}, /* '铡' -> 38113 */ {0x94e2, 0xeef9}, /* '铢' -> 38114 */ {0x94e3, 0xcfb3}, /* '铣' -> 38115 */ {0x94e4, 0xeefa}, /* '铤' -> 38116 */ {0x94e5, 0xeefb}, /* '铥' -> 38117 */ {0x94e7, 0xeefc}, /* '铧' -> 38119 */ {0x94e8, 0xeefd}, /* '铨' -> 38120 */ {0x94e9, 0xefa1}, /* '铩' -> 38121 */ {0x94ea, 0xeefe}, /* '铪' -> 38122 */ {0x94eb, 0xefa2}, /* '铫' -> 38123 */ {0x94ec, 0xb8f5}, /* '铬' -> 38124 */ {0x94ed, 0xc3fa}, /* '铭' -> 38125 */ {0x94ee, 0xefa3}, /* '铮' -> 38126 */ {0x94ef, 0xefa4}, /* '铯' -> 38127 */ {0x94f0, 0xbdc2}, /* '铰' -> 38128 */ {0x94f1, 0xd2bf}, /* '铱' -> 38129 */ {0x94f2, 0xb2f9}, /* '铲' -> 38130 */ {0x94f3, 0xefa5}, /* '铳' -> 38131 */ {0x94f4, 0xefa6}, /* '铴' -> 38132 */ {0x94f5, 0xefa7}, /* '铵' -> 38133 */ {0x94f6, 0xd2f8}, /* '银' -> 38134 */ {0x94f7, 0xefa8}, /* '铷' -> 38135 */ {0x94f8, 0xd6fd}, /* '铸' -> 38136 */ {0x94f9, 0xefa9}, /* '铹' -> 38137 */ {0x94fa, 0xc6cc}, /* '铺' -> 38138 */ {0x94fc, 0xefaa}, /* '铼' -> 38140 */ {0x94fd, 0xefab}, /* '铽' -> 38141 */ {0x94fe, 0xc1b4}, /* '链' -> 38142 */ {0x94ff, 0xefac}, /* '铿' -> 38143 */ {0x9500, 0xcffa}, /* '销' -> 38144 */ {0x9501, 0xcbf8}, /* '锁' -> 38145 */ {0x9502, 0xefae}, /* '锂' -> 38146 */ {0x9503, 0xefad}, /* '锃' -> 38147 */ {0x9504, 0xb3fa}, /* '锄' -> 38148 */ {0x9505, 0xb9f8}, /* '锅' -> 38149 */ {0x9506, 0xefaf}, /* '锆' -> 38150 */ {0x9507, 0xefb0}, /* '锇' -> 38151 */ {0x9508, 0xd0e2}, /* '锈' -> 38152 */ {0x9509, 0xefb1}, /* '锉' -> 38153 */ {0x950a, 0xefb2}, /* '锊' -> 38154 */ {0x950b, 0xb7e6}, /* '锋' -> 38155 */ {0x950c, 0xd0bf}, /* '锌' -> 38156 */ {0x950d, 0xefb3}, /* '锍' -> 38157 */ {0x950e, 0xefb4}, /* '锎' -> 38158 */ {0x950f, 0xefb5}, /* '锏' -> 38159 */ {0x9510, 0xc8f1}, /* '锐' -> 38160 */ {0x9511, 0xcce0}, /* '锑' -> 38161 */ {0x9512, 0xefb6}, /* '锒' -> 38162 */ {0x9513, 0xefb7}, /* '锓' -> 38163 */ {0x9514, 0xefb8}, /* '锔' -> 38164 */ {0x9515, 0xefb9}, /* '锕' -> 38165 */ {0x9516, 0xefba}, /* '锖' -> 38166 */ {0x9517, 0xd5e0}, /* '锗' -> 38167 */ {0x9518, 0xefbb}, /* '锘' -> 38168 */ {0x9519, 0xb4ed}, /* '错' -> 38169 */ {0x951a, 0xc3aa}, /* '锚' -> 38170 */ {0x951b, 0xefbc}, /* '锛' -> 38171 */ {0x951d, 0xefbd}, /* '锝' -> 38173 */ {0x951e, 0xefbe}, /* '锞' -> 38174 */ {0x951f, 0xefbf}, /* '锟' -> 38175 */ {0x9521, 0xcefd}, /* '锡' -> 38177 */ {0x9522, 0xefc0}, /* '锢' -> 38178 */ {0x9523, 0xc2e0}, /* '锣' -> 38179 */ {0x9524, 0xb4b8}, /* '锤' -> 38180 */ {0x9525, 0xd7b6}, /* '锥' -> 38181 */ {0x9526, 0xbdf5}, /* '锦' -> 38182 */ {0x9528, 0xcfc7}, /* '锨' -> 38184 */ {0x9529, 0xefc3}, /* '锩' -> 38185 */ {0x952a, 0xefc1}, /* '锪' -> 38186 */ {0x952b, 0xefc2}, /* '锫' -> 38187 */ {0x952c, 0xefc4}, /* '锬' -> 38188 */ {0x952d, 0xb6a7}, /* '锭' -> 38189 */ {0x952e, 0xbcfc}, /* '键' -> 38190 */ {0x952f, 0xbee2}, /* '锯' -> 38191 */ {0x9530, 0xc3cc}, /* '锰' -> 38192 */ {0x9531, 0xefc5}, /* '锱' -> 38193 */ {0x9532, 0xefc6}, /* '锲' -> 38194 */ {0x9534, 0xefc7}, /* '锴' -> 38196 */ {0x9535, 0xefcf}, /* '锵' -> 38197 */ {0x9536, 0xefc8}, /* '锶' -> 38198 */ {0x9537, 0xefc9}, /* '锷' -> 38199 */ {0x9538, 0xefca}, /* '锸' -> 38200 */ {0x9539, 0xc7c2}, /* '锹' -> 38201 */ {0x953a, 0xeff1}, /* '锺' -> 38202 */ {0x953b, 0xb6cd}, /* '锻' -> 38203 */ {0x953c, 0xefcb}, /* '锼' -> 38204 */ {0x953e, 0xefcc}, /* '锾' -> 38206 */ {0x953f, 0xefcd}, /* '锿' -> 38207 */ {0x9540, 0xb6c6}, /* '镀' -> 38208 */ {0x9541, 0xc3be}, /* '镁' -> 38209 */ {0x9542, 0xefce}, /* '镂' -> 38210 */ {0x9544, 0xefd0}, /* '镄' -> 38212 */ {0x9545, 0xefd1}, /* '镅' -> 38213 */ {0x9546, 0xefd2}, /* '镆' -> 38214 */ {0x9547, 0xd5f2}, /* '镇' -> 38215 */ {0x9549, 0xefd3}, /* '镉' -> 38217 */ {0x954a, 0xc4f7}, /* '镊' -> 38218 */ {0x954c, 0xefd4}, /* '镌' -> 38220 */ {0x954d, 0xc4f8}, /* '镍' -> 38221 */ {0x954e, 0xefd5}, /* '镎' -> 38222 */ {0x954f, 0xefd6}, /* '镏' -> 38223 */ {0x9550, 0xb8e4}, /* '镐' -> 38224 */ {0x9551, 0xb0f7}, /* '镑' -> 38225 */ {0x9552, 0xefd7}, /* '镒' -> 38226 */ {0x9553, 0xefd8}, /* '镓' -> 38227 */ {0x9554, 0xefd9}, /* '镔' -> 38228 */ {0x9556, 0xefda}, /* '镖' -> 38230 */ {0x9557, 0xefdb}, /* '镗' -> 38231 */ {0x9558, 0xefdc}, /* '镘' -> 38232 */ {0x9559, 0xefdd}, /* '镙' -> 38233 */ {0x955b, 0xefde}, /* '镛' -> 38235 */ {0x955c, 0xbeb5}, /* '镜' -> 38236 */ {0x955d, 0xefe1}, /* '镝' -> 38237 */ {0x955e, 0xefdf}, /* '镞' -> 38238 */ {0x955f, 0xefe0}, /* '镟' -> 38239 */ {0x9561, 0xefe2}, /* '镡' -> 38241 */ {0x9562, 0xefe3}, /* '镢' -> 38242 */ {0x9563, 0xc1cd}, /* '镣' -> 38243 */ {0x9564, 0xefe4}, /* '镤' -> 38244 */ {0x9565, 0xefe5}, /* '镥' -> 38245 */ {0x9566, 0xefe6}, /* '镦' -> 38246 */ {0x9567, 0xefe7}, /* '镧' -> 38247 */ {0x9568, 0xefe8}, /* '镨' -> 38248 */ {0x9569, 0xefe9}, /* '镩' -> 38249 */ {0x956a, 0xefea}, /* '镪' -> 38250 */ {0x956b, 0xefeb}, /* '镫' -> 38251 */ {0x956c, 0xefec}, /* '镬' -> 38252 */ {0x956d, 0xc0d8}, /* '镭' -> 38253 */ {0x956f, 0xefed}, /* '镯' -> 38255 */ {0x9570, 0xc1ad}, /* '镰' -> 38256 */ {0x9571, 0xefee}, /* '镱' -> 38257 */ {0x9572, 0xefef}, /* '镲' -> 38258 */ {0x9573, 0xeff0}, /* '镳' -> 38259 */ {0x9576, 0xcfe2}, /* '镶' -> 38262 */ {0x957f, 0xb3a4}, /* '长' -> 38271 */ {0x95e8, 0xc3c5}, /* '门' -> 38376 */ {0x95e9, 0xe3c5}, /* '闩' -> 38377 */ {0x95ea, 0xc9c1}, /* '闪' -> 38378 */ {0x95eb, 0xe3c6}, /* '闫' -> 38379 */ {0x95ed, 0xb1d5}, /* '闭' -> 38381 */ {0x95ee, 0xceca}, /* '问' -> 38382 */ {0x95ef, 0xb4b3}, /* '闯' -> 38383 */ {0x95f0, 0xc8f2}, /* '闰' -> 38384 */ {0x95f1, 0xe3c7}, /* '闱' -> 38385 */ {0x95f2, 0xcfd0}, /* '闲' -> 38386 */ {0x95f3, 0xe3c8}, /* '闳' -> 38387 */ {0x95f4, 0xbce4}, /* '间' -> 38388 */ {0x95f5, 0xe3c9}, /* '闵' -> 38389 */ {0x95f6, 0xe3ca}, /* '闶' -> 38390 */ {0x95f7, 0xc3c6}, /* '闷' -> 38391 */ {0x95f8, 0xd5a2}, /* '闸' -> 38392 */ {0x95f9, 0xc4d6}, /* '闹' -> 38393 */ {0x95fa, 0xb9eb}, /* '闺' -> 38394 */ {0x95fb, 0xcec5}, /* '闻' -> 38395 */ {0x95fc, 0xe3cb}, /* '闼' -> 38396 */ {0x95fd, 0xc3f6}, /* '闽' -> 38397 */ {0x95fe, 0xe3cc}, /* '闾' -> 38398 */ {0x9600, 0xb7a7}, /* '阀' -> 38400 */ {0x9601, 0xb8f3}, /* '阁' -> 38401 */ {0x9602, 0xbad2}, /* '阂' -> 38402 */ {0x9603, 0xe3cd}, /* '阃' -> 38403 */ {0x9604, 0xe3ce}, /* '阄' -> 38404 */ {0x9605, 0xd4c4}, /* '阅' -> 38405 */ {0x9606, 0xe3cf}, /* '阆' -> 38406 */ {0x9608, 0xe3d0}, /* '阈' -> 38408 */ {0x9609, 0xd1cb}, /* '阉' -> 38409 */ {0x960a, 0xe3d1}, /* '阊' -> 38410 */ {0x960b, 0xe3d2}, /* '阋' -> 38411 */ {0x960c, 0xe3d3}, /* '阌' -> 38412 */ {0x960d, 0xe3d4}, /* '阍' -> 38413 */ {0x960e, 0xd1d6}, /* '阎' -> 38414 */ {0x960f, 0xe3d5}, /* '阏' -> 38415 */ {0x9610, 0xb2fb}, /* '阐' -> 38416 */ {0x9611, 0xc0bb}, /* '阑' -> 38417 */ {0x9612, 0xe3d6}, /* '阒' -> 38418 */ {0x9614, 0xc0ab}, /* '阔' -> 38420 */ {0x9615, 0xe3d7}, /* '阕' -> 38421 */ {0x9616, 0xe3d8}, /* '阖' -> 38422 */ {0x9617, 0xe3d9}, /* '阗' -> 38423 */ {0x9619, 0xe3da}, /* '阙' -> 38425 */ {0x961a, 0xe3db}, /* '阚' -> 38426 */ {0x961c, 0xb8b7}, /* '阜' -> 38428 */ {0x961d, 0xdae2}, /* '阝' -> 38429 */ {0x961f, 0xb6d3}, /* '队' -> 38431 */ {0x9621, 0xdae4}, /* '阡' -> 38433 */ {0x9622, 0xdae3}, /* '阢' -> 38434 */ {0x962a, 0xdae6}, /* '阪' -> 38442 */ {0x962e, 0xc8ee}, /* '阮' -> 38446 */ {0x9631, 0xdae5}, /* '阱' -> 38449 */ {0x9632, 0xb7c0}, /* '防' -> 38450 */ {0x9633, 0xd1f4}, /* '阳' -> 38451 */ {0x9634, 0xd2f5}, /* '阴' -> 38452 */ {0x9635, 0xd5f3}, /* '阵' -> 38453 */ {0x9636, 0xbdd7}, /* '阶' -> 38454 */ {0x963b, 0xd7e8}, /* '阻' -> 38459 */ {0x963c, 0xdae8}, /* '阼' -> 38460 */ {0x963d, 0xdae7}, /* '阽' -> 38461 */ {0x963f, 0xb0a2}, /* '阿' -> 38463 */ {0x9640, 0xcdd3}, /* '陀' -> 38464 */ {0x9642, 0xdae9}, /* '陂' -> 38466 */ {0x9644, 0xb8bd}, /* '附' -> 38468 */ {0x9645, 0xbcca}, /* '际' -> 38469 */ {0x9646, 0xc2bd}, /* '陆' -> 38470 */ {0x9647, 0xc2a4}, /* '陇' -> 38471 */ {0x9648, 0xb3c2}, /* '陈' -> 38472 */ {0x9649, 0xdaea}, /* '陉' -> 38473 */ {0x964b, 0xc2aa}, /* '陋' -> 38475 */ {0x964c, 0xc4b0}, /* '陌' -> 38476 */ {0x964d, 0xbdb5}, /* '降' -> 38477 */ {0x9650, 0xcfde}, /* '限' -> 38480 */ {0x9654, 0xdaeb}, /* '陔' -> 38484 */ {0x9655, 0xc9c2}, /* '陕' -> 38485 */ {0x965b, 0xb1dd}, /* '陛' -> 38491 */ {0x965f, 0xdaec}, /* '陟' -> 38495 */ {0x9661, 0xb6b8}, /* '陡' -> 38497 */ {0x9662, 0xd4ba}, /* '院' -> 38498 */ {0x9664, 0xb3fd}, /* '除' -> 38500 */ {0x9667, 0xdaed}, /* '陧' -> 38503 */ {0x9668, 0xd4c9}, /* '陨' -> 38504 */ {0x9669, 0xcfd5}, /* '险' -> 38505 */ {0x966a, 0xc5e3}, /* '陪' -> 38506 */ {0x966c, 0xdaee}, /* '陬' -> 38508 */ {0x9672, 0xdaef}, /* '陲' -> 38514 */ {0x9674, 0xdaf0}, /* '陴' -> 38516 */ {0x9675, 0xc1ea}, /* '陵' -> 38517 */ {0x9676, 0xccd5}, /* '陶' -> 38518 */ {0x9677, 0xcfdd}, /* '陷' -> 38519 */ {0x9685, 0xd3e7}, /* '隅' -> 38533 */ {0x9686, 0xc2a1}, /* '隆' -> 38534 */ {0x9688, 0xdaf1}, /* '隈' -> 38536 */ {0x968b, 0xcbe5}, /* '隋' -> 38539 */ {0x968d, 0xdaf2}, /* '隍' -> 38541 */ {0x968f, 0xcbe6}, /* '随' -> 38543 */ {0x9690, 0xd2fe}, /* '隐' -> 38544 */ {0x9694, 0xb8f4}, /* '隔' -> 38548 */ {0x9697, 0xdaf3}, /* '隗' -> 38551 */ {0x9698, 0xb0af}, /* '隘' -> 38552 */ {0x9699, 0xcfb6}, /* '隙' -> 38553 */ {0x969c, 0xd5cf}, /* '障' -> 38556 */ {0x96a7, 0xcbed}, /* '隧' -> 38567 */ {0x96b0, 0xdaf4}, /* '隰' -> 38576 */ {0x96b3, 0xe3c4}, /* '隳' -> 38579 */ {0x96b6, 0xc1a5}, /* '隶' -> 38582 */ {0x96b9, 0xf6bf}, /* '隹' -> 38585 */ {0x96bc, 0xf6c0}, /* '隼' -> 38588 */ {0x96bd, 0xf6c1}, /* '隽' -> 38589 */ {0x96be, 0xc4d1}, /* '难' -> 38590 */ {0x96c0, 0xc8b8}, /* '雀' -> 38592 */ {0x96c1, 0xd1e3}, /* '雁' -> 38593 */ {0x96c4, 0xd0db}, /* '雄' -> 38596 */ {0x96c5, 0xd1c5}, /* '雅' -> 38597 */ {0x96c6, 0xbcaf}, /* '集' -> 38598 */ {0x96c7, 0xb9cd}, /* '雇' -> 38599 */ {0x96c9, 0xeff4}, /* '雉' -> 38601 */ {0x96cc, 0xb4c6}, /* '雌' -> 38604 */ {0x96cd, 0xd3ba}, /* '雍' -> 38605 */ {0x96ce, 0xf6c2}, /* '雎' -> 38606 */ {0x96cf, 0xb3fb}, /* '雏' -> 38607 */ {0x96d2, 0xf6c3}, /* '雒' -> 38610 */ {0x96d5, 0xb5f1}, /* '雕' -> 38613 */ {0x96e0, 0xf6c5}, /* '雠' -> 38624 */ {0x96e8, 0xd3ea}, /* '雨' -> 38632 */ {0x96e9, 0xf6a7}, /* '雩' -> 38633 */ {0x96ea, 0xd1a9}, /* '雪' -> 38634 */ {0x96ef, 0xf6a9}, /* '雯' -> 38639 */ {0x96f3, 0xf6a8}, /* '雳' -> 38643 */ {0x96f6, 0xc1e3}, /* '零' -> 38646 */ {0x96f7, 0xc0d7}, /* '雷' -> 38647 */ {0x96f9, 0xb1a2}, /* '雹' -> 38649 */ {0x96fe, 0xceed}, /* '雾' -> 38654 */ {0x9700, 0xd0e8}, /* '需' -> 38656 */ {0x9701, 0xf6ab}, /* '霁' -> 38657 */ {0x9704, 0xcff6}, /* '霄' -> 38660 */ {0x9706, 0xf6aa}, /* '霆' -> 38662 */ {0x9707, 0xd5f0}, /* '震' -> 38663 */ {0x9708, 0xf6ac}, /* '霈' -> 38664 */ {0x9709, 0xc3b9}, /* '霉' -> 38665 */ {0x970d, 0xbbf4}, /* '霍' -> 38669 */ {0x970e, 0xf6ae}, /* '霎' -> 38670 */ {0x970f, 0xf6ad}, /* '霏' -> 38671 */ {0x9713, 0xc4de}, /* '霓' -> 38675 */ {0x9716, 0xc1d8}, /* '霖' -> 38678 */ {0x971c, 0xcbaa}, /* '霜' -> 38684 */ {0x971e, 0xcfbc}, /* '霞' -> 38686 */ {0x972a, 0xf6af}, /* '霪' -> 38698 */ {0x972d, 0xf6b0}, /* '霭' -> 38701 */ {0x9730, 0xf6b1}, /* '霰' -> 38704 */ {0x9732, 0xc2b6}, /* '露' -> 38706 */ {0x9738, 0xb0d4}, /* '霸' -> 38712 */ {0x9739, 0xc5f9}, /* '霹' -> 38713 */ {0x973e, 0xf6b2}, /* '霾' -> 38718 */ {0x9752, 0xc7e0}, /* '青' -> 38738 */ {0x9753, 0xf6a6}, /* '靓' -> 38739 */ {0x9756, 0xbeb8}, /* '靖' -> 38742 */ {0x9759, 0xbeb2}, /* '静' -> 38745 */ {0x975b, 0xb5e5}, /* '靛' -> 38747 */ {0x975e, 0xb7c7}, /* '非' -> 38750 */ {0x9760, 0xbfbf}, /* '靠' -> 38752 */ {0x9761, 0xc3d2}, /* '靡' -> 38753 */ {0x9762, 0xc3e6}, /* '面' -> 38754 */ {0x9765, 0xd8cc}, /* '靥' -> 38757 */ {0x9769, 0xb8ef}, /* '革' -> 38761 */ {0x9773, 0xbdf9}, /* '靳' -> 38771 */ {0x9774, 0xd1a5}, /* '靴' -> 38772 */ {0x9776, 0xb0d0}, /* '靶' -> 38774 */ {0x977c, 0xf7b0}, /* '靼' -> 38780 */ {0x9785, 0xf7b1}, /* '鞅' -> 38789 */ {0x978b, 0xd0ac}, /* '鞋' -> 38795 */ {0x978d, 0xb0b0}, /* '鞍' -> 38797 */ {0x9791, 0xf7b2}, /* '鞑' -> 38801 */ {0x9792, 0xf7b3}, /* '鞒' -> 38802 */ {0x9794, 0xf7b4}, /* '鞔' -> 38804 */ {0x9798, 0xc7ca}, /* '鞘' -> 38808 */ {0x97a0, 0xbecf}, /* '鞠' -> 38816 */ {0x97a3, 0xf7b7}, /* '鞣' -> 38819 */ {0x97ab, 0xf7b6}, /* '鞫' -> 38827 */ {0x97ad, 0xb1de}, /* '鞭' -> 38829 */ {0x97af, 0xf7b5}, /* '鞯' -> 38831 */ {0x97b2, 0xf7b8}, /* '鞲' -> 38834 */ {0x97b4, 0xf7b9}, /* '鞴' -> 38836 */ {0x97e6, 0xcea4}, /* '韦' -> 38886 */ {0x97e7, 0xc8cd}, /* '韧' -> 38887 */ {0x97e9, 0xbaab}, /* '韩' -> 38889 */ {0x97ea, 0xe8b8}, /* '韪' -> 38890 */ {0x97eb, 0xe8b9}, /* '韫' -> 38891 */ {0x97ec, 0xe8ba}, /* '韬' -> 38892 */ {0x97ed, 0xbec2}, /* '韭' -> 38893 */ {0x97f3, 0xd2f4}, /* '音' -> 38899 */ {0x97f5, 0xd4cf}, /* '韵' -> 38901 */ {0x97f6, 0xc9d8}, /* '韶' -> 38902 */ {0x9875, 0xd2b3}, /* '页' -> 39029 */ {0x9876, 0xb6a5}, /* '顶' -> 39030 */ {0x9877, 0xc7ea}, /* '顷' -> 39031 */ {0x9878, 0xf1fc}, /* '顸' -> 39032 */ {0x9879, 0xcfee}, /* '项' -> 39033 */ {0x987a, 0xcbb3}, /* '顺' -> 39034 */ {0x987b, 0xd0eb}, /* '须' -> 39035 */ {0x987c, 0xe7ef}, /* '顼' -> 39036 */ {0x987d, 0xcde7}, /* '顽' -> 39037 */ {0x987e, 0xb9cb}, /* '顾' -> 39038 */ {0x987f, 0xb6d9}, /* '顿' -> 39039 */ {0x9880, 0xf1fd}, /* '颀' -> 39040 */ {0x9881, 0xb0e4}, /* '颁' -> 39041 */ {0x9882, 0xcbcc}, /* '颂' -> 39042 */ {0x9883, 0xf1fe}, /* '颃' -> 39043 */ {0x9884, 0xd4a4}, /* '预' -> 39044 */ {0x9885, 0xc2ad}, /* '颅' -> 39045 */ {0x9886, 0xc1ec}, /* '领' -> 39046 */ {0x9887, 0xc6c4}, /* '颇' -> 39047 */ {0x9888, 0xbeb1}, /* '颈' -> 39048 */ {0x9889, 0xf2a1}, /* '颉' -> 39049 */ {0x988a, 0xbcd5}, /* '颊' -> 39050 */ {0x988c, 0xf2a2}, /* '颌' -> 39052 */ {0x988d, 0xf2a3}, /* '颍' -> 39053 */ {0x988f, 0xf2a4}, /* '颏' -> 39055 */ {0x9890, 0xd2c3}, /* '颐' -> 39056 */ {0x9891, 0xc6b5}, /* '频' -> 39057 */ {0x9893, 0xcdc7}, /* '颓' -> 39059 */ {0x9894, 0xf2a5}, /* '颔' -> 39060 */ {0x9896, 0xd3b1}, /* '颖' -> 39062 */ {0x9897, 0xbfc5}, /* '颗' -> 39063 */ {0x9898, 0xcce2}, /* '题' -> 39064 */ {0x989a, 0xf2a6}, /* '颚' -> 39066 */ {0x989b, 0xf2a7}, /* '颛' -> 39067 */ {0x989c, 0xd1d5}, /* '颜' -> 39068 */ {0x989d, 0xb6ee}, /* '额' -> 39069 */ {0x989e, 0xf2a8}, /* '颞' -> 39070 */ {0x989f, 0xf2a9}, /* '颟' -> 39071 */ {0x98a0, 0xb5df}, /* '颠' -> 39072 */ {0x98a1, 0xf2aa}, /* '颡' -> 39073 */ {0x98a2, 0xf2ab}, /* '颢' -> 39074 */ {0x98a4, 0xb2fc}, /* '颤' -> 39076 */ {0x98a5, 0xf2ac}, /* '颥' -> 39077 */ {0x98a6, 0xf2ad}, /* '颦' -> 39078 */ {0x98a7, 0xc8a7}, /* '颧' -> 39079 */ {0x98ce, 0xb7e7}, /* '风' -> 39118 */ {0x98d1, 0xeca9}, /* '飑' -> 39121 */ {0x98d2, 0xecaa}, /* '飒' -> 39122 */ {0x98d3, 0xecab}, /* '飓' -> 39123 */ {0x98d5, 0xecac}, /* '飕' -> 39125 */ {0x98d8, 0xc6ae}, /* '飘' -> 39128 */ {0x98d9, 0xecad}, /* '飙' -> 39129 */ {0x98da, 0xecae}, /* '飚' -> 39130 */ {0x98de, 0xb7c9}, /* '飞' -> 39134 */ {0x98df, 0xcab3}, /* '食' -> 39135 */ {0x98e7, 0xe2b8}, /* '飧' -> 39143 */ {0x98e8, 0xf7cf}, /* '飨' -> 39144 */ {0x990d, 0xf7d0}, /* '餍' -> 39181 */ {0x9910, 0xb2cd}, /* '餐' -> 39184 */ {0x992e, 0xf7d1}, /* '餮' -> 39214 */ {0x9954, 0xf7d3}, /* '饔' -> 39252 */ {0x9955, 0xf7d2}, /* '饕' -> 39253 */ {0x9963, 0xe2bb}, /* '饣' -> 39267 */ {0x9965, 0xbca2}, /* '饥' -> 39269 */ {0x9967, 0xe2bc}, /* '饧' -> 39271 */ {0x9968, 0xe2bd}, /* '饨' -> 39272 */ {0x9969, 0xe2be}, /* '饩' -> 39273 */ {0x996a, 0xe2bf}, /* '饪' -> 39274 */ {0x996b, 0xe2c0}, /* '饫' -> 39275 */ {0x996c, 0xe2c1}, /* '饬' -> 39276 */ {0x996d, 0xb7b9}, /* '饭' -> 39277 */ {0x996e, 0xd2fb}, /* '饮' -> 39278 */ {0x996f, 0xbda4}, /* '饯' -> 39279 */ {0x9970, 0xcace}, /* '饰' -> 39280 */ {0x9971, 0xb1a5}, /* '饱' -> 39281 */ {0x9972, 0xcbc7}, /* '饲' -> 39282 */ {0x9974, 0xe2c2}, /* '饴' -> 39284 */ {0x9975, 0xb6fc}, /* '饵' -> 39285 */ {0x9976, 0xc8c4}, /* '饶' -> 39286 */ {0x9977, 0xe2c3}, /* '饷' -> 39287 */ {0x997a, 0xbdc8}, /* '饺' -> 39290 */ {0x997c, 0xb1fd}, /* '饼' -> 39292 */ {0x997d, 0xe2c4}, /* '饽' -> 39293 */ {0x997f, 0xb6f6}, /* '饿' -> 39295 */ {0x9980, 0xe2c5}, /* '馀' -> 39296 */ {0x9981, 0xc4d9}, /* '馁' -> 39297 */ {0x9984, 0xe2c6}, /* '馄' -> 39300 */ {0x9985, 0xcfda}, /* '馅' -> 39301 */ {0x9986, 0xb9dd}, /* '馆' -> 39302 */ {0x9987, 0xe2c7}, /* '馇' -> 39303 */ {0x9988, 0xc0a1}, /* '馈' -> 39304 */ {0x998a, 0xe2c8}, /* '馊' -> 39306 */ {0x998b, 0xb2f6}, /* '馋' -> 39307 */ {0x998d, 0xe2c9}, /* '馍' -> 39309 */ {0x998f, 0xc1f3}, /* '馏' -> 39311 */ {0x9990, 0xe2ca}, /* '馐' -> 39312 */ {0x9991, 0xe2cb}, /* '馑' -> 39313 */ {0x9992, 0xc2f8}, /* '馒' -> 39314 */ {0x9993, 0xe2cc}, /* '馓' -> 39315 */ {0x9994, 0xe2cd}, /* '馔' -> 39316 */ {0x9995, 0xe2ce}, /* '馕' -> 39317 */ {0x9996, 0xcad7}, /* '首' -> 39318 */ {0x9997, 0xd8b8}, /* '馗' -> 39319 */ {0x9998, 0xd9e5}, /* '馘' -> 39320 */ {0x9999, 0xcfe3}, /* '香' -> 39321 */ {0x99a5, 0xf0a5}, /* '馥' -> 39333 */ {0x99a8, 0xdcb0}, /* '馨' -> 39336 */ {0x9a6c, 0xc2ed}, /* '马' -> 39532 */ {0x9a6d, 0xd4a6}, /* '驭' -> 39533 */ {0x9a6e, 0xcdd4}, /* '驮' -> 39534 */ {0x9a6f, 0xd1b1}, /* '驯' -> 39535 */ {0x9a70, 0xb3db}, /* '驰' -> 39536 */ {0x9a71, 0xc7fd}, /* '驱' -> 39537 */ {0x9a73, 0xb2b5}, /* '驳' -> 39539 */ {0x9a74, 0xc2bf}, /* '驴' -> 39540 */ {0x9a75, 0xe6e0}, /* '驵' -> 39541 */ {0x9a76, 0xcabb}, /* '驶' -> 39542 */ {0x9a77, 0xe6e1}, /* '驷' -> 39543 */ {0x9a78, 0xe6e2}, /* '驸' -> 39544 */ {0x9a79, 0xbed4}, /* '驹' -> 39545 */ {0x9a7a, 0xe6e3}, /* '驺' -> 39546 */ {0x9a7b, 0xd7a4}, /* '驻' -> 39547 */ {0x9a7c, 0xcdd5}, /* '驼' -> 39548 */ {0x9a7d, 0xe6e5}, /* '驽' -> 39549 */ {0x9a7e, 0xbcdd}, /* '驾' -> 39550 */ {0x9a7f, 0xe6e4}, /* '驿' -> 39551 */ {0x9a80, 0xe6e6}, /* '骀' -> 39552 */ {0x9a81, 0xe6e7}, /* '骁' -> 39553 */ {0x9a82, 0xc2ee}, /* '骂' -> 39554 */ {0x9a84, 0xbdbe}, /* '骄' -> 39556 */ {0x9a85, 0xe6e8}, /* '骅' -> 39557 */ {0x9a86, 0xc2e6}, /* '骆' -> 39558 */ {0x9a87, 0xbaa7}, /* '骇' -> 39559 */ {0x9a88, 0xe6e9}, /* '骈' -> 39560 */ {0x9a8a, 0xe6ea}, /* '骊' -> 39562 */ {0x9a8b, 0xb3d2}, /* '骋' -> 39563 */ {0x9a8c, 0xd1e9}, /* '验' -> 39564 */ {0x9a8f, 0xbfa5}, /* '骏' -> 39567 */ {0x9a90, 0xe6eb}, /* '骐' -> 39568 */ {0x9a91, 0xc6ef}, /* '骑' -> 39569 */ {0x9a92, 0xe6ec}, /* '骒' -> 39570 */ {0x9a93, 0xe6ed}, /* '骓' -> 39571 */ {0x9a96, 0xe6ee}, /* '骖' -> 39574 */ {0x9a97, 0xc6ad}, /* '骗' -> 39575 */ {0x9a98, 0xe6ef}, /* '骘' -> 39576 */ {0x9a9a, 0xc9a7}, /* '骚' -> 39578 */ {0x9a9b, 0xe6f0}, /* '骛' -> 39579 */ {0x9a9c, 0xe6f1}, /* '骜' -> 39580 */ {0x9a9d, 0xe6f2}, /* '骝' -> 39581 */ {0x9a9e, 0xe5b9}, /* '骞' -> 39582 */ {0x9a9f, 0xe6f3}, /* '骟' -> 39583 */ {0x9aa0, 0xe6f4}, /* '骠' -> 39584 */ {0x9aa1, 0xc2e2}, /* '骡' -> 39585 */ {0x9aa2, 0xe6f5}, /* '骢' -> 39586 */ {0x9aa3, 0xe6f6}, /* '骣' -> 39587 */ {0x9aa4, 0xd6e8}, /* '骤' -> 39588 */ {0x9aa5, 0xe6f7}, /* '骥' -> 39589 */ {0x9aa7, 0xe6f8}, /* '骧' -> 39591 */ {0x9aa8, 0xb9c7}, /* '骨' -> 39592 */ {0x9ab0, 0xf7bb}, /* '骰' -> 39600 */ {0x9ab1, 0xf7ba}, /* '骱' -> 39601 */ {0x9ab6, 0xf7be}, /* '骶' -> 39606 */ {0x9ab7, 0xf7bc}, /* '骷' -> 39607 */ {0x9ab8, 0xbaa1}, /* '骸' -> 39608 */ {0x9aba, 0xf7bf}, /* '骺' -> 39610 */ {0x9abc, 0xf7c0}, /* '骼' -> 39612 */ {0x9ac0, 0xf7c2}, /* '髀' -> 39616 */ {0x9ac1, 0xf7c1}, /* '髁' -> 39617 */ {0x9ac2, 0xf7c4}, /* '髂' -> 39618 */ {0x9ac5, 0xf7c3}, /* '髅' -> 39621 */ {0x9acb, 0xf7c5}, /* '髋' -> 39627 */ {0x9acc, 0xf7c6}, /* '髌' -> 39628 */ {0x9ad1, 0xf7c7}, /* '髑' -> 39633 */ {0x9ad3, 0xcbe8}, /* '髓' -> 39635 */ {0x9ad8, 0xb8df}, /* '高' -> 39640 */ {0x9adf, 0xf7d4}, /* '髟' -> 39647 */ {0x9ae1, 0xf7d5}, /* '髡' -> 39649 */ {0x9ae6, 0xf7d6}, /* '髦' -> 39654 */ {0x9aeb, 0xf7d8}, /* '髫' -> 39659 */ {0x9aed, 0xf7da}, /* '髭' -> 39661 */ {0x9aef, 0xf7d7}, /* '髯' -> 39663 */ {0x9af9, 0xf7db}, /* '髹' -> 39673 */ {0x9afb, 0xf7d9}, /* '髻' -> 39675 */ {0x9b03, 0xd7d7}, /* '鬃' -> 39683 */ {0x9b08, 0xf7dc}, /* '鬈' -> 39688 */ {0x9b0f, 0xf7dd}, /* '鬏' -> 39695 */ {0x9b13, 0xf7de}, /* '鬓' -> 39699 */ {0x9b1f, 0xf7df}, /* '鬟' -> 39711 */ {0x9b23, 0xf7e0}, /* '鬣' -> 39715 */ {0x9b2f, 0xdbcb}, /* '鬯' -> 39727 */ {0x9b32, 0xd8aa}, /* '鬲' -> 39730 */ {0x9b3b, 0xe5f7}, /* '鬻' -> 39739 */ {0x9b3c, 0xb9ed}, /* '鬼' -> 39740 */ {0x9b41, 0xbffd}, /* '魁' -> 39745 */ {0x9b42, 0xbbea}, /* '魂' -> 39746 */ {0x9b43, 0xf7c9}, /* '魃' -> 39747 */ {0x9b44, 0xc6c7}, /* '魄' -> 39748 */ {0x9b45, 0xf7c8}, /* '魅' -> 39749 */ {0x9b47, 0xf7ca}, /* '魇' -> 39751 */ {0x9b48, 0xf7cc}, /* '魈' -> 39752 */ {0x9b49, 0xf7cb}, /* '魉' -> 39753 */ {0x9b4d, 0xf7cd}, /* '魍' -> 39757 */ {0x9b4f, 0xceba}, /* '魏' -> 39759 */ {0x9b51, 0xf7ce}, /* '魑' -> 39761 */ {0x9b54, 0xc4a7}, /* '魔' -> 39764 */ {0x9c7c, 0xd3e3}, /* '鱼' -> 40060 */ {0x9c7f, 0xf6cf}, /* '鱿' -> 40063 */ {0x9c81, 0xc2b3}, /* '鲁' -> 40065 */ {0x9c82, 0xf6d0}, /* '鲂' -> 40066 */ {0x9c85, 0xf6d1}, /* '鲅' -> 40069 */ {0x9c86, 0xf6d2}, /* '鲆' -> 40070 */ {0x9c87, 0xf6d3}, /* '鲇' -> 40071 */ {0x9c88, 0xf6d4}, /* '鲈' -> 40072 */ {0x9c8b, 0xf6d6}, /* '鲋' -> 40075 */ {0x9c8d, 0xb1ab}, /* '鲍' -> 40077 */ {0x9c8e, 0xf6d7}, /* '鲎' -> 40078 */ {0x9c90, 0xf6d8}, /* '鲐' -> 40080 */ {0x9c91, 0xf6d9}, /* '鲑' -> 40081 */ {0x9c92, 0xf6da}, /* '鲒' -> 40082 */ {0x9c94, 0xf6db}, /* '鲔' -> 40084 */ {0x9c95, 0xf6dc}, /* '鲕' -> 40085 */ {0x9c9a, 0xf6dd}, /* '鲚' -> 40090 */ {0x9c9b, 0xf6de}, /* '鲛' -> 40091 */ {0x9c9c, 0xcfca}, /* '鲜' -> 40092 */ {0x9c9e, 0xf6df}, /* '鲞' -> 40094 */ {0x9c9f, 0xf6e0}, /* '鲟' -> 40095 */ {0x9ca0, 0xf6e1}, /* '鲠' -> 40096 */ {0x9ca1, 0xf6e2}, /* '鲡' -> 40097 */ {0x9ca2, 0xf6e3}, /* '鲢' -> 40098 */ {0x9ca3, 0xf6e4}, /* '鲣' -> 40099 */ {0x9ca4, 0xc0f0}, /* '鲤' -> 40100 */ {0x9ca5, 0xf6e5}, /* '鲥' -> 40101 */ {0x9ca6, 0xf6e6}, /* '鲦' -> 40102 */ {0x9ca7, 0xf6e7}, /* '鲧' -> 40103 */ {0x9ca8, 0xf6e8}, /* '鲨' -> 40104 */ {0x9ca9, 0xf6e9}, /* '鲩' -> 40105 */ {0x9cab, 0xf6ea}, /* '鲫' -> 40107 */ {0x9cad, 0xf6eb}, /* '鲭' -> 40109 */ {0x9cae, 0xf6ec}, /* '鲮' -> 40110 */ {0x9cb0, 0xf6ed}, /* '鲰' -> 40112 */ {0x9cb1, 0xf6ee}, /* '鲱' -> 40113 */ {0x9cb2, 0xf6ef}, /* '鲲' -> 40114 */ {0x9cb3, 0xf6f0}, /* '鲳' -> 40115 */ {0x9cb4, 0xf6f1}, /* '鲴' -> 40116 */ {0x9cb5, 0xf6f2}, /* '鲵' -> 40117 */ {0x9cb6, 0xf6f3}, /* '鲶' -> 40118 */ {0x9cb7, 0xf6f4}, /* '鲷' -> 40119 */ {0x9cb8, 0xbea8}, /* '鲸' -> 40120 */ {0x9cba, 0xf6f5}, /* '鲺' -> 40122 */ {0x9cbb, 0xf6f6}, /* '鲻' -> 40123 */ {0x9cbc, 0xf6f7}, /* '鲼' -> 40124 */ {0x9cbd, 0xf6f8}, /* '鲽' -> 40125 */ {0x9cc3, 0xc8fa}, /* '鳃' -> 40131 */ {0x9cc4, 0xf6f9}, /* '鳄' -> 40132 */ {0x9cc5, 0xf6fa}, /* '鳅' -> 40133 */ {0x9cc6, 0xf6fb}, /* '鳆' -> 40134 */ {0x9cc7, 0xf6fc}, /* '鳇' -> 40135 */ {0x9cca, 0xf6fd}, /* '鳊' -> 40138 */ {0x9ccb, 0xf6fe}, /* '鳋' -> 40139 */ {0x9ccc, 0xf7a1}, /* '鳌' -> 40140 */ {0x9ccd, 0xf7a2}, /* '鳍' -> 40141 */ {0x9cce, 0xf7a3}, /* '鳎' -> 40142 */ {0x9ccf, 0xf7a4}, /* '鳏' -> 40143 */ {0x9cd0, 0xf7a5}, /* '鳐' -> 40144 */ {0x9cd3, 0xf7a6}, /* '鳓' -> 40147 */ {0x9cd4, 0xf7a7}, /* '鳔' -> 40148 */ {0x9cd5, 0xf7a8}, /* '鳕' -> 40149 */ {0x9cd6, 0xb1ee}, /* '鳖' -> 40150 */ {0x9cd7, 0xf7a9}, /* '鳗' -> 40151 */ {0x9cd8, 0xf7aa}, /* '鳘' -> 40152 */ {0x9cd9, 0xf7ab}, /* '鳙' -> 40153 */ {0x9cdc, 0xf7ac}, /* '鳜' -> 40156 */ {0x9cdd, 0xf7ad}, /* '鳝' -> 40157 */ {0x9cde, 0xc1db}, /* '鳞' -> 40158 */ {0x9cdf, 0xf7ae}, /* '鳟' -> 40159 */ {0x9ce2, 0xf7af}, /* '鳢' -> 40162 */ {0x9e1f, 0xc4f1}, /* '鸟' -> 40479 */ {0x9e20, 0xf0af}, /* '鸠' -> 40480 */ {0x9e21, 0xbca6}, /* '鸡' -> 40481 */ {0x9e22, 0xf0b0}, /* '鸢' -> 40482 */ {0x9e23, 0xc3f9}, /* '鸣' -> 40483 */ {0x9e25, 0xc5b8}, /* '鸥' -> 40485 */ {0x9e26, 0xd1bb}, /* '鸦' -> 40486 */ {0x9e28, 0xf0b1}, /* '鸨' -> 40488 */ {0x9e29, 0xf0b2}, /* '鸩' -> 40489 */ {0x9e2a, 0xf0b3}, /* '鸪' -> 40490 */ {0x9e2b, 0xf0b4}, /* '鸫' -> 40491 */ {0x9e2c, 0xf0b5}, /* '鸬' -> 40492 */ {0x9e2d, 0xd1bc}, /* '鸭' -> 40493 */ {0x9e2f, 0xd1ec}, /* '鸯' -> 40495 */ {0x9e31, 0xf0b7}, /* '鸱' -> 40497 */ {0x9e32, 0xf0b6}, /* '鸲' -> 40498 */ {0x9e33, 0xd4a7}, /* '鸳' -> 40499 */ {0x9e35, 0xcdd2}, /* '鸵' -> 40501 */ {0x9e36, 0xf0b8}, /* '鸶' -> 40502 */ {0x9e37, 0xf0ba}, /* '鸷' -> 40503 */ {0x9e38, 0xf0b9}, /* '鸸' -> 40504 */ {0x9e39, 0xf0bb}, /* '鸹' -> 40505 */ {0x9e3a, 0xf0bc}, /* '鸺' -> 40506 */ {0x9e3d, 0xb8eb}, /* '鸽' -> 40509 */ {0x9e3e, 0xf0bd}, /* '鸾' -> 40510 */ {0x9e3f, 0xbae8}, /* '鸿' -> 40511 */ {0x9e41, 0xf0be}, /* '鹁' -> 40513 */ {0x9e42, 0xf0bf}, /* '鹂' -> 40514 */ {0x9e43, 0xbee9}, /* '鹃' -> 40515 */ {0x9e44, 0xf0c0}, /* '鹄' -> 40516 */ {0x9e45, 0xb6ec}, /* '鹅' -> 40517 */ {0x9e46, 0xf0c1}, /* '鹆' -> 40518 */ {0x9e47, 0xf0c2}, /* '鹇' -> 40519 */ {0x9e48, 0xf0c3}, /* '鹈' -> 40520 */ {0x9e49, 0xf0c4}, /* '鹉' -> 40521 */ {0x9e4a, 0xc8b5}, /* '鹊' -> 40522 */ {0x9e4b, 0xf0c5}, /* '鹋' -> 40523 */ {0x9e4c, 0xf0c6}, /* '鹌' -> 40524 */ {0x9e4e, 0xf0c7}, /* '鹎' -> 40526 */ {0x9e4f, 0xc5f4}, /* '鹏' -> 40527 */ {0x9e51, 0xf0c8}, /* '鹑' -> 40529 */ {0x9e55, 0xf0c9}, /* '鹕' -> 40533 */ {0x9e57, 0xf0ca}, /* '鹗' -> 40535 */ {0x9e58, 0xf7bd}, /* '鹘' -> 40536 */ {0x9e5a, 0xf0cb}, /* '鹚' -> 40538 */ {0x9e5b, 0xf0cc}, /* '鹛' -> 40539 */ {0x9e5c, 0xf0cd}, /* '鹜' -> 40540 */ {0x9e5e, 0xf0ce}, /* '鹞' -> 40542 */ {0x9e63, 0xf0cf}, /* '鹣' -> 40547 */ {0x9e64, 0xbad7}, /* '鹤' -> 40548 */ {0x9e66, 0xf0d0}, /* '鹦' -> 40550 */ {0x9e67, 0xf0d1}, /* '鹧' -> 40551 */ {0x9e68, 0xf0d2}, /* '鹨' -> 40552 */ {0x9e69, 0xf0d3}, /* '鹩' -> 40553 */ {0x9e6a, 0xf0d4}, /* '鹪' -> 40554 */ {0x9e6b, 0xf0d5}, /* '鹫' -> 40555 */ {0x9e6c, 0xf0d6}, /* '鹬' -> 40556 */ {0x9e6d, 0xf0d8}, /* '鹭' -> 40557 */ {0x9e70, 0xd3a5}, /* '鹰' -> 40560 */ {0x9e71, 0xf0d7}, /* '鹱' -> 40561 */ {0x9e73, 0xf0d9}, /* '鹳' -> 40563 */ {0x9e7e, 0xf5ba}, /* '鹾' -> 40574 */ {0x9e7f, 0xc2b9}, /* '鹿' -> 40575 */ {0x9e82, 0xf7e4}, /* '麂' -> 40578 */ {0x9e87, 0xf7e5}, /* '麇' -> 40583 */ {0x9e88, 0xf7e6}, /* '麈' -> 40584 */ {0x9e8b, 0xf7e7}, /* '麋' -> 40587 */ {0x9e92, 0xf7e8}, /* '麒' -> 40594 */ {0x9e93, 0xc2b4}, /* '麓' -> 40595 */ {0x9e9d, 0xf7ea}, /* '麝' -> 40605 */ {0x9e9f, 0xf7eb}, /* '麟' -> 40607 */ {0x9ea6, 0xc2f3}, /* '麦' -> 40614 */ {0x9eb4, 0xf4f0}, /* '麴' -> 40628 */ {0x9eb8, 0xf4ef}, /* '麸' -> 40632 */ {0x9ebb, 0xc2e9}, /* '麻' -> 40635 */ {0x9ebd, 0xf7e1}, /* '麽' -> 40637 */ {0x9ebe, 0xf7e2}, /* '麾' -> 40638 */ {0x9ec4, 0xbbc6}, /* '黄' -> 40644 */ {0x9ec9, 0xd9e4}, /* '黉' -> 40649 */ {0x9ecd, 0xcaf2}, /* '黍' -> 40653 */ {0x9ece, 0xc0e8}, /* '黎' -> 40654 */ {0x9ecf, 0xf0a4}, /* '黏' -> 40655 */ {0x9ed1, 0xbada}, /* '黑' -> 40657 */ {0x9ed4, 0xc7ad}, /* '黔' -> 40660 */ {0x9ed8, 0xc4ac}, /* '默' -> 40664 */ {0x9edb, 0xf7ec}, /* '黛' -> 40667 */ {0x9edc, 0xf7ed}, /* '黜' -> 40668 */ {0x9edd, 0xf7ee}, /* '黝' -> 40669 */ {0x9edf, 0xf7f0}, /* '黟' -> 40671 */ {0x9ee0, 0xf7ef}, /* '黠' -> 40672 */ {0x9ee2, 0xf7f1}, /* '黢' -> 40674 */ {0x9ee5, 0xf7f4}, /* '黥' -> 40677 */ {0x9ee7, 0xf7f3}, /* '黧' -> 40679 */ {0x9ee9, 0xf7f2}, /* '黩' -> 40681 */ {0x9eea, 0xf7f5}, /* '黪' -> 40682 */ {0x9eef, 0xf7f6}, /* '黯' -> 40687 */ {0x9ef9, 0xede9}, /* '黹' -> 40697 */ {0x9efb, 0xedea}, /* '黻' -> 40699 */ {0x9efc, 0xedeb}, /* '黼' -> 40700 */ {0x9efe, 0xf6bc}, /* '黾' -> 40702 */ {0x9f0b, 0xf6bd}, /* '鼋' -> 40715 */ {0x9f0d, 0xf6be}, /* '鼍' -> 40717 */ {0x9f0e, 0xb6a6}, /* '鼎' -> 40718 */ {0x9f10, 0xd8be}, /* '鼐' -> 40720 */ {0x9f13, 0xb9c4}, /* '鼓' -> 40723 */ {0x9f17, 0xd8bb}, /* '鼗' -> 40727 */ {0x9f19, 0xdcb1}, /* '鼙' -> 40729 */ {0x9f20, 0xcaf3}, /* '鼠' -> 40736 */ {0x9f22, 0xf7f7}, /* '鼢' -> 40738 */ {0x9f2c, 0xf7f8}, /* '鼬' -> 40748 */ {0x9f2f, 0xf7f9}, /* '鼯' -> 40751 */ {0x9f37, 0xf7fb}, /* '鼷' -> 40759 */ {0x9f39, 0xf7fa}, /* '鼹' -> 40761 */ {0x9f3b, 0xb1c7}, /* '鼻' -> 40763 */ {0x9f3d, 0xf7fc}, /* '鼽' -> 40765 */ {0x9f3e, 0xf7fd}, /* '鼾' -> 40766 */ {0x9f44, 0xf7fe}, /* '齄' -> 40772 */ {0x9f50, 0xc6eb}, /* '齐' -> 40784 */ {0x9f51, 0xecb4}, /* '齑' -> 40785 */ {0x9f7f, 0xb3dd}, /* '齿' -> 40831 */ {0x9f80, 0xf6b3}, /* '龀' -> 40832 */ {0x9f83, 0xf6b4}, /* '龃' -> 40835 */ {0x9f84, 0xc1e4}, /* '龄' -> 40836 */ {0x9f85, 0xf6b5}, /* '龅' -> 40837 */ {0x9f86, 0xf6b6}, /* '龆' -> 40838 */ {0x9f87, 0xf6b7}, /* '龇' -> 40839 */ {0x9f88, 0xf6b8}, /* '龈' -> 40840 */ {0x9f89, 0xf6b9}, /* '龉' -> 40841 */ {0x9f8a, 0xf6ba}, /* '龊' -> 40842 */ {0x9f8b, 0xc8a3}, /* '龋' -> 40843 */ {0x9f8c, 0xf6bb}, /* '龌' -> 40844 */ {0x9f99, 0xc1fa}, /* '龙' -> 40857 */ {0x9f9a, 0xb9a8}, /* '龚' -> 40858 */ {0x9f9b, 0xede8}, /* '龛' -> 40859 */ {0x9f9f, 0xb9ea}, /* '龟' -> 40863 */ {0x9fa0, 0xd9df}, /* '龠' -> 40864 */ {0xff01, 0xa3a1}, /* '!' -> 65281 */ {0xff02, 0xa3a2}, /* '"' -> 65282 */ {0xff03, 0xa3a3}, /* '#' -> 65283 */ {0xff04, 0xa1e7}, /* '$' -> 65284 */ {0xff05, 0xa3a5}, /* '%' -> 65285 */ {0xff06, 0xa3a6}, /* '&' -> 65286 */ {0xff07, 0xa3a7}, /* ''' -> 65287 */ {0xff08, 0xa3a8}, /* '(' -> 65288 */ {0xff09, 0xa3a9}, /* ')' -> 65289 */ {0xff0a, 0xa3aa}, /* '*' -> 65290 */ {0xff0b, 0xa3ab}, /* '+' -> 65291 */ {0xff0c, 0xa3ac}, /* ',' -> 65292 */ {0xff0d, 0xa3ad}, /* '-' -> 65293 */ {0xff0e, 0xa3ae}, /* '.' -> 65294 */ {0xff0f, 0xa3af}, /* '/' -> 65295 */ {0xff10, 0xa3b0}, /* '0' -> 65296 */ {0xff11, 0xa3b1}, /* '1' -> 65297 */ {0xff12, 0xa3b2}, /* '2' -> 65298 */ {0xff13, 0xa3b3}, /* '3' -> 65299 */ {0xff14, 0xa3b4}, /* '4' -> 65300 */ {0xff15, 0xa3b5}, /* '5' -> 65301 */ {0xff16, 0xa3b6}, /* '6' -> 65302 */ {0xff17, 0xa3b7}, /* '7' -> 65303 */ {0xff18, 0xa3b8}, /* '8' -> 65304 */ {0xff19, 0xa3b9}, /* '9' -> 65305 */ {0xff1a, 0xa3ba}, /* ':' -> 65306 */ {0xff1b, 0xa3bb}, /* ';' -> 65307 */ {0xff1c, 0xa3bc}, /* '<' -> 65308 */ {0xff1d, 0xa3bd}, /* '=' -> 65309 */ {0xff1e, 0xa3be}, /* '>' -> 65310 */ {0xff1f, 0xa3bf}, /* '?' -> 65311 */ {0xff20, 0xa3c0}, /* '@' -> 65312 */ {0xff21, 0xa3c1}, /* 'a' -> 65313 */ {0xff22, 0xa3c2}, /* 'b' -> 65314 */ {0xff23, 0xa3c3}, /* 'c' -> 65315 */ {0xff24, 0xa3c4}, /* 'd' -> 65316 */ {0xff25, 0xa3c5}, /* 'e' -> 65317 */ {0xff26, 0xa3c6}, /* 'f' -> 65318 */ {0xff27, 0xa3c7}, /* 'g' -> 65319 */ {0xff28, 0xa3c8}, /* 'h' -> 65320 */ {0xff29, 0xa3c9}, /* 'i' -> 65321 */ {0xff2a, 0xa3ca}, /* 'j' -> 65322 */ {0xff2b, 0xa3cb}, /* 'k' -> 65323 */ {0xff2c, 0xa3cc}, /* 'l' -> 65324 */ {0xff2d, 0xa3cd}, /* 'm' -> 65325 */ {0xff2e, 0xa3ce}, /* 'n' -> 65326 */ {0xff2f, 0xa3cf}, /* 'o' -> 65327 */ {0xff30, 0xa3d0}, /* 'p' -> 65328 */ {0xff31, 0xa3d1}, /* 'q' -> 65329 */ {0xff32, 0xa3d2}, /* 'r' -> 65330 */ {0xff33, 0xa3d3}, /* 's' -> 65331 */ {0xff34, 0xa3d4}, /* 't' -> 65332 */ {0xff35, 0xa3d5}, /* 'u' -> 65333 */ {0xff36, 0xa3d6}, /* 'v' -> 65334 */ {0xff37, 0xa3d7}, /* 'w' -> 65335 */ {0xff38, 0xa3d8}, /* 'x' -> 65336 */ {0xff39, 0xa3d9}, /* 'y' -> 65337 */ {0xff3a, 0xa3da}, /* 'z' -> 65338 */ {0xff3b, 0xa3db}, /* '[' -> 65339 */ {0xff3c, 0xa3dc}, /* '\' -> 65340 */ {0xff3d, 0xa3dd}, /* ']' -> 65341 */ {0xff3e, 0xa3de}, /* '^' -> 65342 */ {0xff3f, 0xa3df}, /* '_' -> 65343 */ {0xff40, 0xa3e0}, /* '`' -> 65344 */ {0xff41, 0xa3e1}, /* 'a' -> 65345 */ {0xff42, 0xa3e2}, /* 'b' -> 65346 */ {0xff43, 0xa3e3}, /* 'c' -> 65347 */ {0xff44, 0xa3e4}, /* 'd' -> 65348 */ {0xff45, 0xa3e5}, /* 'e' -> 65349 */ {0xff46, 0xa3e6}, /* 'f' -> 65350 */ {0xff47, 0xa3e7}, /* 'g' -> 65351 */ {0xff48, 0xa3e8}, /* 'h' -> 65352 */ {0xff49, 0xa3e9}, /* 'i' -> 65353 */ {0xff4a, 0xa3ea}, /* 'j' -> 65354 */ {0xff4b, 0xa3eb}, /* 'k' -> 65355 */ {0xff4c, 0xa3ec}, /* 'l' -> 65356 */ {0xff4d, 0xa3ed}, /* 'm' -> 65357 */ {0xff4e, 0xa3ee}, /* 'n' -> 65358 */ {0xff4f, 0xa3ef}, /* 'o' -> 65359 */ {0xff50, 0xa3f0}, /* 'p' -> 65360 */ {0xff51, 0xa3f1}, /* 'q' -> 65361 */ {0xff52, 0xa3f2}, /* 'r' -> 65362 */ {0xff53, 0xa3f3}, /* 's' -> 65363 */ {0xff54, 0xa3f4}, /* 't' -> 65364 */ {0xff55, 0xa3f5}, /* 'u' -> 65365 */ {0xff56, 0xa3f6}, /* 'v' -> 65366 */ {0xff57, 0xa3f7}, /* 'w' -> 65367 */ {0xff58, 0xa3f8}, /* 'x' -> 65368 */ {0xff59, 0xa3f9}, /* 'y' -> 65369 */ {0xff5a, 0xa3fa}, /* 'z' -> 65370 */ {0xff5b, 0xa3fb}, /* '{' -> 65371 */ {0xff5c, 0xa3fc}, /* '|' -> 65372 */ {0xff5d, 0xa3fd}, /* '}' -> 65373 */ {0xff5e, 0xa1ab}, /* '~' -> 65374 */ {0xffe0, 0xa1e9}, /* '¢' -> 65504 */ {0xffe1, 0xa1ea}, /* '£' -> 65505 */ {0xffe3, 0xa3fe}, /* ' ̄' -> 65507 */ {0xffe5, 0xa3a4} /* '¥' -> 65509 */ }; tb_size_t g_charset_gb2312_to_ucs4_table_size = sizeof(g_charset_gb2312_to_ucs4_table_data); tb_size_t g_charset_ucs4_to_gb2312_table_size = sizeof(g_charset_ucs4_to_gb2312_table_data); tbox-1.6.7/src/tbox/charset/iso8859.c 0000664 0000000 0000000 00000003455 14142237372 0017205 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file iso8859.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_iso8859_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_iso8859_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { tb_byte_t b = tb_static_stream_read_u8(sstream); if (b < 0xa0) *ch = b; else { // @note: need lookup characters table tb_trace_d("iso8859: unknown character: %x", b); *ch = 0; } return 1; } tb_long_t tb_charset_iso8859_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_iso8859_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { if (ch <= 0xa0) tb_static_stream_writ_u8(sstream, (tb_uint8_t)ch); else { // @note: need lookup characters table tb_trace_d("iso8859: unknown character: %x", ch); } return 1; } tbox-1.6.7/src/tbox/charset/prefix.h 0000664 0000000 0000000 00000001577 14142237372 0017362 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_CHARSET_PREFIX_H #define TB_CHARSET_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #endif tbox-1.6.7/src/tbox/charset/ucs2.c 0000664 0000000 0000000 00000003144 14142237372 0016724 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file ucs2.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_ucs2_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_ucs2_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { *ch = be? tb_static_stream_read_u16_be(sstream) : tb_static_stream_read_u16_le(sstream); return 1; } tb_long_t tb_charset_ucs2_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_ucs2_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { if (ch > 0xffff) ch = 0xfffd; if (be) tb_static_stream_writ_u16_be(sstream, ch); else tb_static_stream_writ_u16_le(sstream, ch); return 1; } tbox-1.6.7/src/tbox/charset/ucs4.c 0000664 0000000 0000000 00000003104 14142237372 0016722 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file ucs4.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_ucs4_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_ucs4_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { *ch = be ? tb_static_stream_read_u32_be(sstream) : tb_static_stream_read_u32_le(sstream); return 1; } tb_long_t tb_charset_ucs4_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_ucs4_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { if (be) tb_static_stream_writ_u32_be(sstream, ch); else tb_static_stream_writ_u32_le(sstream, ch); return 1; } tbox-1.6.7/src/tbox/charset/utf16.c 0000664 0000000 0000000 00000006443 14142237372 0017022 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file utf16.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_utf16_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_utf16_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { // init tb_byte_t const* p = tb_static_stream_pos(sstream); tb_byte_t const* q = p; tb_size_t n = tb_static_stream_left(sstream); // not enough? break it tb_check_return_val(n > 1, -1); // the first character tb_uint32_t c = be? tb_bits_get_u16_be(p) : tb_bits_get_u16_le(p); p += 2; // large? if (c >= 0xd800 && c <= 0xdbff) { // not enough? break it tb_check_return_val(n > 3, -1); // the next character tb_uint32_t c2 = be? tb_bits_get_u16_be(p) : tb_bits_get_u16_le(p); if (c2 >= 0xdc00 && c2 <= 0xdfff) { c = ((c - 0xd800) << 10) + (c2 - 0xdc00) + 0x0010000; p += 2; } }; // next if (p > q) tb_static_stream_skip(sstream, p - q); // set character *ch = c; // ok? return p > q? 1 : 0; } tb_long_t tb_charset_utf16_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_utf16_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { // init tb_size_t n = tb_static_stream_left(sstream); if (ch <= 0x0000ffff) { // not enough? break it tb_check_return_val(n > 1, -1); // set character if (be) tb_static_stream_writ_u16_be(sstream, ch); else tb_static_stream_writ_u16_le(sstream, ch); } else if (ch > 0x0010ffff) { // not enough? break it tb_check_return_val(n > 1, -1); // set character if (be) tb_static_stream_writ_u16_be(sstream, 0x0000fffd); else tb_static_stream_writ_u16_le(sstream, 0x0000fffd); } else { // not enough? break it tb_check_return_val(n > 3, -1); // set character ch -= 0x0010000; if (be) { tb_static_stream_writ_u16_be(sstream, (ch >> 10) + 0xd800); tb_static_stream_writ_u16_be(sstream, (ch & 0x3ff) + 0xdc00); } else { tb_static_stream_writ_u16_le(sstream, (ch >> 10) + 0xd800); tb_static_stream_writ_u16_le(sstream, (ch & 0x3ff) + 0xdc00); } } // ok return 1; } tbox-1.6.7/src/tbox/charset/utf32.c 0000664 0000000 0000000 00000003111 14142237372 0017005 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file utf32.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_long_t tb_charset_utf32_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_utf32_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { *ch = be ? tb_static_stream_read_u32_be(sstream) : tb_static_stream_read_u32_le(sstream); return 1; } tb_long_t tb_charset_utf32_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_utf32_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { if (be) tb_static_stream_writ_u32_be(sstream, ch); else tb_static_stream_writ_u32_le(sstream, ch); return 1; } tbox-1.6.7/src/tbox/charset/utf8.c 0000664 0000000 0000000 00000015022 14142237372 0016734 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file utf8.c * @ingroup charset * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../stream/stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ /* * 0x00000000 - 0x0000007f: 0xxxxxxx * 0x00000080 - 0x000007ff: 110xxxxx 10xxxxxx * 0x00000800 - 0x0000ffff: 1110xxxx 10xxxxxx 10xxxxxx * 0x00010000 - 0x001fffff: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx * 0x00200000 - 0x03ffffff: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx * 0x04000000 - 0x7fffffff: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ tb_long_t tb_charset_utf8_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch); tb_long_t tb_charset_utf8_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch) { // init tb_byte_t const* p = tb_static_stream_pos(sstream); tb_byte_t const* q = p; tb_size_t n = tb_static_stream_left(sstream); // 0x00000000 - 0x0000007f if (!(*p & 0x80)) { // not enough? break it tb_check_return_val(n, -1); // get character *ch = *p++; } // 0x00000080 - 0x000007ff else if ((*p & 0xe0) == 0xc0) { // not enough? break it tb_check_return_val(n > 1, -1); // get character *ch = ((((tb_uint32_t)(p[0] & 0x1f)) << 6) | (p[1] & 0x3f)); p += 2; } // 0x00000800 - 0x0000ffff else if ((*p & 0xf0) == 0xe0) { // not enough? break it tb_check_return_val(n > 2, -1); // get character *ch = ((((tb_uint32_t)(p[0] & 0x0f)) << 12) | (((tb_uint32_t)(p[1] & 0x3f)) << 6) | (p[2] & 0x3f)); p += 3; } // 0x00010000 - 0x001fffff else if ((*p & 0xf8) == 0xf0) { // not enough? break it tb_check_return_val(n > 3, -1); // get character *ch = ((((tb_uint32_t)(p[0] & 0x07)) << 18) | (((tb_uint32_t)(p[1] & 0x3f)) << 12) | (((tb_uint32_t)(p[2] & 0x3f)) << 6) | (p[3] & 0x3f)); p += 4; } // 0x00200000 - 0x03ffffff else if ((*p & 0xfc) == 0xf8) { // not enough? break it tb_check_return_val(n > 4, -1); // get character *ch = ((((tb_uint32_t)(p[0] & 0x03)) << 24) | (((tb_uint32_t)(p[1] & 0x3f)) << 18) | (((tb_uint32_t)(p[2] & 0x3f)) << 12) | (((tb_uint32_t)(p[3] & 0x3f)) << 6) | (p[4] & 0x3f)); p += 5; } // 0x04000000 - 0x7fffffff else if ((*p & 0xfe) == 0xfc) { // not enough? break it tb_check_return_val(n > 5, -1); // get character *ch = ((((tb_uint32_t)(p[0] & 0x01)) << 30) | (((tb_uint32_t)(p[1] & 0x3f)) << 24) | (((tb_uint32_t)(p[2] & 0x3f)) << 18) | (((tb_uint32_t)(p[3] & 0x3f)) << 12) | (((tb_uint32_t)(p[4] & 0x3f)) << 6) | (p[5] & 0x3f)); p += 6; } else { // invalid character tb_trace_d("invalid utf8 character: %x", *p); // skip it tb_static_stream_skip(sstream, 1); // no character return 0; } // next if (p > q) tb_static_stream_skip(sstream, p - q); // ok? return p > q? 1 : 0; } tb_long_t tb_charset_utf8_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch); tb_long_t tb_charset_utf8_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch) { // init tb_byte_t* p = (tb_byte_t*)tb_static_stream_pos(sstream); tb_byte_t* q = p; tb_size_t n = tb_static_stream_left(sstream); // 0x00000000 - 0x0000007f if (ch <= 0x0000007f) { // not enough? break it tb_check_return_val(n, -1); // set character *p++ = ch; } // 0x00000080 - 0x000007ff else if (ch <= 0x000007ff) { // not enough? break it tb_check_return_val(n > 1, -1); // set character // 110xxxxx 10xxxxxx // xxx xxxxxxxx *p++ = ((ch >> 6) & 0x1f) | 0xc0; *p++ = (ch & 0x3f) | 0x80; } // 0x00000800 - 0x0000ffff else if (ch <= 0x0000ffff) { // not enough? break it tb_check_return_val(n > 2, -1); // set character // 1110xxxx 10xxxxxx 10xxxxxx // xxxxxxxx xxxxxxxx *p++ = ((ch >> 12) & 0x0f) | 0xe0; *p++ = ((ch >> 6) & 0x3f) | 0x80; *p++ = (ch & 0x3f) | 0x80; } // 0x00010000 - 0x001fffff else if (ch <= 0x001fffff) { // not enough? break it tb_check_return_val(n > 3, -1); // set character // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // xxxxx xxxxxxxx xxxxxxxx *p++ = ((ch >> 18) & 0x07) | 0xf0; *p++ = ((ch >> 12) & 0x3f) | 0x80; *p++ = ((ch >> 6) & 0x3f) | 0x80; *p++ = (ch & 0x3f) | 0x80; } // 0x00200000 - 0x03ffffff else if (ch <= 0x03ffffff) { // not enough? break it tb_check_return_val(n > 4, -1); // set character // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // xx xxxxxxxx xxxxxxxx xxxxxxxx *p++ = ((ch >> 24) & 0x03) | 0xf8; *p++ = ((ch >> 18) & 0x3f) | 0x80; *p++ = ((ch >> 12) & 0x3f) | 0x80; *p++ = ((ch >> 6) & 0x3f) | 0x80; *p++ = (ch & 0x3f) | 0x80; } // 0x04000000 - 0x7fffffff else if (ch <= 0x7fffffff) { // not enough? break it tb_check_return_val(n > 5, -1); // set character // 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx *p++ = ((ch >> 30) & 0x01) | 0xfc; *p++ = ((ch >> 24) & 0x3f) | 0x80; *p++ = ((ch >> 18) & 0x3f) | 0x80; *p++ = ((ch >> 12) & 0x3f) | 0x80; *p++ = ((ch >> 6) & 0x3f) | 0x80; *p++ = (ch & 0x3f) | 0x80; } // next if (p > q) tb_static_stream_skip(sstream, p - q); // ok? return p > q? 1 : 0; } tbox-1.6.7/src/tbox/config.h 0000664 0000000 0000000 00000001575 14142237372 0015677 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file config.h * */ #ifndef TB_TBOX_CONFIG_H #define TB_TBOX_CONFIG_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "tbox.config.h" #endif tbox-1.6.7/src/tbox/container/ 0000775 0000000 0000000 00000000000 14142237372 0016233 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/container/array_iterator.c 0000664 0000000 0000000 00000023425 14142237372 0021434 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file array_iterator.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../libc/libc.h" #include "../utils/utils.h" #include "../memory/memory.h" #include "../object/object.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation for pointer element */ static tb_size_t tb_array_iterator_ptr_size(tb_iterator_ref_t iterator) { // check tb_assert(iterator); // the size return ((tb_array_iterator_ref_t)iterator)->count; } static tb_size_t tb_array_iterator_ptr_head(tb_iterator_ref_t iterator) { return 0; } static tb_size_t tb_array_iterator_ptr_tail(tb_iterator_ref_t iterator) { // check tb_assert(iterator); // the tail return ((tb_array_iterator_ref_t)iterator)->count; } static tb_size_t tb_array_iterator_ptr_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count); // the next return itor + 1; } static tb_size_t tb_array_iterator_ptr_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && itor); // the prev return itor - 1; } static tb_pointer_t tb_array_iterator_ptr_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count); // the item return ((tb_pointer_t*)((tb_array_iterator_ref_t)iterator)->items)[itor]; } static tb_void_t tb_array_iterator_ptr_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count); // copy ((tb_cpointer_t*)((tb_array_iterator_ref_t)iterator)->items)[itor] = item; } static tb_long_t tb_array_iterator_ptr_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { return (litem < ritem)? -1 : (litem > ritem); } /* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation for memory element */ static tb_pointer_t tb_array_iterator_mem_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count); // the item return (tb_pointer_t)((tb_byte_t*)((tb_array_iterator_ref_t)iterator)->items + itor * iterator->step); } static tb_void_t tb_array_iterator_mem_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count); // copy tb_memcpy((tb_byte_t*)((tb_array_iterator_ref_t)iterator)->items + itor * iterator->step, item, iterator->step); } static tb_long_t tb_array_iterator_mem_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert(litem && ritem); // compare it return tb_memcmp(litem, ritem, iterator->step); } /* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation for c-string element */ static tb_long_t tb_array_iterator_str_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert(litem && ritem); // compare it return tb_strcmp((tb_char_t const*)litem, (tb_char_t const*)ritem); } static tb_long_t tb_array_iterator_istr_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert(litem && ritem); // compare it return tb_stricmp((tb_char_t const*)litem, (tb_char_t const*)ritem); } /* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation for long element */ static tb_long_t tb_array_iterator_long_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { return ((tb_long_t)litem < (tb_long_t)ritem)? -1 : ((tb_long_t)litem > (tb_long_t)ritem); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_iterator_ref_t tb_array_iterator_init_ptr(tb_array_iterator_ref_t iterator, tb_pointer_t* items, tb_size_t count) { // check tb_assert(iterator && items && count); // init operation static tb_iterator_op_t op = { tb_array_iterator_ptr_size , tb_array_iterator_ptr_head , tb_null , tb_array_iterator_ptr_tail , tb_array_iterator_ptr_prev , tb_array_iterator_ptr_next , tb_array_iterator_ptr_item , tb_array_iterator_ptr_comp , tb_array_iterator_ptr_copy , tb_null , tb_null }; // init iterator iterator->base.priv = tb_null; iterator->base.step = sizeof(tb_pointer_t); iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; iterator->base.op = &op; iterator->items = items; iterator->count = count; // ok return (tb_iterator_ref_t)iterator; } tb_iterator_ref_t tb_array_iterator_init_mem(tb_array_iterator_ref_t iterator, tb_pointer_t items, tb_size_t count, tb_size_t size) { // check tb_assert(iterator && items && count && size); // init operation static tb_iterator_op_t op = { tb_array_iterator_ptr_size , tb_array_iterator_ptr_head , tb_null , tb_array_iterator_ptr_tail , tb_array_iterator_ptr_prev , tb_array_iterator_ptr_next , tb_array_iterator_mem_item , tb_array_iterator_mem_comp , tb_array_iterator_mem_copy , tb_null , tb_null }; // init iterator->base.priv = tb_null; iterator->base.step = size; iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; iterator->base.op = &op; iterator->items = items; iterator->count = count; // ok return (tb_iterator_ref_t)iterator; } tb_iterator_ref_t tb_array_iterator_init_str(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count) { // check tb_assert(iterator && items && count); // init operation static tb_iterator_op_t op = { tb_array_iterator_ptr_size , tb_array_iterator_ptr_head , tb_null , tb_array_iterator_ptr_tail , tb_array_iterator_ptr_prev , tb_array_iterator_ptr_next , tb_array_iterator_ptr_item , tb_array_iterator_str_comp , tb_array_iterator_ptr_copy , tb_null , tb_null }; // init iterator iterator->base.priv = tb_null; iterator->base.step = sizeof(tb_char_t const*); iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; iterator->base.op = &op; iterator->items = items; iterator->count = count; // ok return (tb_iterator_ref_t)iterator; } tb_iterator_ref_t tb_array_iterator_init_istr(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count) { // check tb_assert(iterator && items && count); // init operation static tb_iterator_op_t op = { tb_array_iterator_ptr_size , tb_array_iterator_ptr_head , tb_null , tb_array_iterator_ptr_tail , tb_array_iterator_ptr_prev , tb_array_iterator_ptr_next , tb_array_iterator_ptr_item , tb_array_iterator_istr_comp , tb_array_iterator_ptr_copy , tb_null , tb_null }; // init iterator iterator->base.priv = tb_null; iterator->base.step = sizeof(tb_char_t const*); iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; iterator->base.op = &op; iterator->items = items; iterator->count = count; // ok return (tb_iterator_ref_t)iterator; } tb_iterator_ref_t tb_array_iterator_init_size(tb_array_iterator_ref_t iterator, tb_size_t* items, tb_size_t count) { return tb_array_iterator_init_ptr(iterator, (tb_pointer_t*)items, count); } tb_iterator_ref_t tb_array_iterator_init_long(tb_array_iterator_ref_t iterator, tb_long_t* items, tb_size_t count) { // check tb_assert(iterator && items && count); // init operation static tb_iterator_op_t op = { tb_array_iterator_ptr_size , tb_array_iterator_ptr_head , tb_null , tb_array_iterator_ptr_tail , tb_array_iterator_ptr_prev , tb_array_iterator_ptr_next , tb_array_iterator_ptr_item , tb_array_iterator_long_comp , tb_array_iterator_ptr_copy , tb_null , tb_null }; // init iterator iterator->base.priv = tb_null; iterator->base.step = sizeof(tb_long_t); iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; iterator->base.op = &op; iterator->items = items; iterator->count = count; // ok return (tb_iterator_ref_t)iterator; } tbox-1.6.7/src/tbox/container/array_iterator.h 0000664 0000000 0000000 00000007024 14142237372 0021436 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file array_iterator.h * @ingroup container * */ #ifndef TB_CONTAINER_ARRAY_ITERATOR_H #define TB_CONTAINER_ARRAY_ITERATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the array iterator type typedef struct __tb_array_iterator_t { /// the iterator base tb_iterator_t base; /// the items tb_pointer_t items; /// the items count tb_size_t count; }tb_array_iterator_t, *tb_array_iterator_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init array iterator for pointer element * * @param iterator the array iterator * @param items the items * @param count the count * * @return the iterator */ tb_iterator_ref_t tb_array_iterator_init_ptr(tb_array_iterator_ref_t iterator, tb_pointer_t* items, tb_size_t count); /*! init array iterator for memory element * * @param iterator the array iterator * @param items the items * @param count the count * @param size the element size * * @return the iterator */ tb_iterator_ref_t tb_array_iterator_init_mem(tb_array_iterator_ref_t iterator, tb_pointer_t items, tb_size_t count, tb_size_t size); /*! init array iterator for c-string element * * @param iterator the array iterator * @param items the items * @param count the count * * @return the iterator */ tb_iterator_ref_t tb_array_iterator_init_str(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count); /*! init array iterator for c-string element and ignore case * * @param iterator the array iterator * @param items the items * @param count the count * * @return the iterator */ tb_iterator_ref_t tb_array_iterator_init_istr(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count); /*! init array iterator for long element * * @param iterator the array iterator * @param items the items * @param count the count * * @return the iterator */ tb_iterator_ref_t tb_array_iterator_init_long(tb_array_iterator_ref_t iterator, tb_long_t* items, tb_size_t count); /*! init array iterator for size element * * @param iterator the array iterator * @param items the items * @param count the count * * @return the iterator */ tb_iterator_ref_t tb_array_iterator_init_size(tb_array_iterator_ref_t iterator, tb_size_t* items, tb_size_t count); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/bloom_filter.c 0000664 0000000 0000000 00000033170 14142237372 0021060 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file bloom_filter.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "bloom_filter" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "bloom_filter.h" #include "../libc/libc.h" #include "../libm/libm.h" #include "../math/math.h" #include "../utils/utils.h" #include "../memory/memory.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the data size maxn #ifdef __tb_small__ # define TB_BLOOM_FILTER_DATA_MAXN (1 << 28) #else # define TB_BLOOM_FILTER_DATA_MAXN (1 << 30) #endif // the item default maxn #ifdef __tb_small__ # define TB_BLOOM_FILTER_ITEM_MAXN_DEFAULT TB_BLOOM_FILTER_ITEM_MAXN_MICRO #else # define TB_BLOOM_FILTER_ITEM_MAXN_DEFAULT TB_BLOOM_FILTER_ITEM_MAXN_SMALL #endif // the bit sets #define tb_bloom_filter_set1(data, i) do {(data)[(i) >> 3] |= (0x1 << ((i) & 7));} while (0) #define tb_bloom_filter_set0(data, i) do {(data)[(i) >> 3] &= ~(0x1 << ((i) & 7));} while (0) #define tb_bloom_filter_bset(data, i) ((data)[(i) >> 3] & (0x1 << ((i) & 7))) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the bloom filter type typedef struct __tb_bloom_filter_t { // the probability tb_size_t probability; // the hash count tb_size_t hash_count; // the maxn tb_size_t maxn; // the element tb_element_t element; // the size tb_size_t size; // the data tb_byte_t* data; // the hash mask tb_size_t mask; }tb_bloom_filter_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bloom_filter_ref_t tb_bloom_filter_init(tb_size_t probability, tb_size_t hash_count, tb_size_t item_maxn, tb_element_t element) { // check tb_assert_and_check_return_val(element.hash, tb_null); // done tb_bool_t ok = tb_false; tb_bloom_filter_t* filter = tb_null; do { // check tb_assert_and_check_break(probability && probability < 32); #ifdef __tb_small__ tb_assert_and_check_break(hash_count && hash_count < 4); #else tb_assert_and_check_break(hash_count && hash_count < 16); #endif // check item maxn if (!item_maxn) item_maxn = TB_BLOOM_FILTER_ITEM_MAXN_DEFAULT; tb_assert_and_check_break(item_maxn < TB_MAXU32); // make filter filter = tb_malloc0_type(tb_bloom_filter_t); tb_assert_and_check_break(filter); // init filter filter->element = element; filter->maxn = item_maxn; filter->hash_count = hash_count; filter->probability = probability; /* compute the storage space * * c = p^(1/k) * s = m / n = 2k / (2c + c * c) */ #ifdef TB_CONFIG_TYPE_HAVE_FLOAT tb_double_t k = (tb_double_t)hash_count; tb_double_t p = 1. / (tb_double_t)(1 << probability); tb_double_t c = tb_pow(p, 1 / k); tb_double_t s = (k + k) / (c + c + c * c); tb_size_t n = item_maxn; tb_size_t m = tb_round(s * n); tb_trace_d("k: %lf, p: %lf, c: %lf, s: %lf => p: %lf, m: %lu, n: %lu", k, p, c, s, tb_pow((1 - tb_exp(-k / s)), k), m, n); #else #if 0 // make scale table tb_size_t i = 0; for (i = 1; i < 16; i++) { tb_printf(",\t{ "); tb_size_t j = 0; for (j = 0; j < 31; j++) { tb_double_t k = (tb_double_t)i; tb_double_t p = 1. / (tb_double_t)(1 << j); tb_double_t c = tb_pow(p, 1 / k); tb_double_t s = (k + k) / (c + c + c * c); if (j != 30) tb_printf("%#010x, ", tb_float_to_fixed(s)); else tb_printf("%#010x }\n", tb_float_to_fixed(s)); } } #endif // the scale static tb_size_t s_scale[15][31] = { { 0x0000aaaa, 0x00019999, 0x00038e38, 0x00078787, 0x000f83e0, 0x001f81f8, 0x003f80fe, 0x007f807f, 0x00ff803f, 0x01ff801f, 0x03ff800f, 0x07ff8007, 0x0fff8003, 0x1fff8001, 0x3fff8000, 0x7fff8000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000 } , { 0x00015555, 0x000216f2, 0x00033333, 0x0004ce9c, 0x00071c71, 0x000a6519, 0x000f0f0f, 0x0015ab74, 0x001f07c1, 0x002c46c5, 0x003f03f0, 0x00598545, 0x007f01fc, 0x00b4065b, 0x00ff00ff, 0x01690a9a, 0x01ff007f, 0x02d31427, 0x03ff003f, 0x05a727c6, 0x07ff001f, 0x0b4f4f49, 0x0fff000f, 0x169f9e71, 0x1fff0007, 0x2d403cd2, 0x3fff0003, 0x5a81799c, 0x7fff0001, 0x80000000, 0x80000000 } , { 0x00020000, 0x0002b4b7, 0x00039f1a, 0x0004cccc, 0x00064ed1, 0x00083a7e, 0x000aaaaa, 0x000dc122, 0x0011a886, 0x00169696, 0x001ccf1a, 0x0024a789, 0x002e8ba2, 0x003b0334, 0x004ab965, 0x005e85e8, 0x00777886, 0x0096e7b6, 0x00be82fa, 0x00f06a01, 0x012f49d1, 0x017e817e, 0x01e25077, 0x026010d0, 0x02fe80bf, 0x03c61f26, 0x04c1a037, 0x05fe805f, 0x078dbd69, 0x0984bfba, 0x0bfe802f } , { 0x0002aaaa, 0x0003594c, 0x00042de4, 0x00052f7d, 0x00066666, 0x0007dc6f, 0x00099d38, 0x000bb692, 0x000e38e3, 0x001137b0, 0x0014ca32, 0x00190c0b, 0x001e1e1e, 0x0024278c, 0x002b56e8, 0x0033e397, 0x003e0f83, 0x004a2914, 0x00588d8b, 0x0069abd5, 0x007e07e0, 0x00963e94, 0x00b30a8b, 0x00d549b3, 0x00fe03f8, 0x012e7338, 0x01680cb6, 0x01ac8c57, 0x01fe01fe, 0x025ee16e, 0x02d21535 } , { 0x00035555, 0x0004006d, 0x0004c8d7, 0x0005b2de, 0x0006c365, 0x00080000, 0x00096f0f, 0x000b17e2, 0x000d02d9, 0x000f3993, 0x0011c71c, 0x0014b825, 0x00181b43, 0x001c013a, 0x00207d4e, 0x0025a5a5, 0x002b93b2, 0x003264b4, 0x003a3a48, 0x00433b0d, 0x004d9364, 0x0059764a, 0x00671e54, 0x0076cecd, 0x0088d509, 0x009d89d8, 0x00b55345, 0x00d0a688, 0x00f00a47, 0x01141931, 0x013d84f6 } , { 0x00040000, 0x0004a8c7, 0x0005696e, 0x000644d6, 0x00073e35, 0x00085921, 0x00099999, 0x000b0419, 0x000c9da2, 0x000e6bd5, 0x001074fd, 0x0012c02d, 0x00155555, 0x00183d5c, 0x001b8245, 0x001f2f4c, 0x0023510d, 0x0027f5b5, 0x002d2d2d, 0x00330952, 0x00399e34, 0x0041025c, 0x00494f13, 0x0052a0c0, 0x005d1745, 0x0068d66e, 0x00760668, 0x0084d450, 0x009572cb, 0x00a81ab0, 0x00bd0bd0 } , { 0x0004aaaa, 0x000551d0, 0x00060d16, 0x0006de8d, 0x0007c87b, 0x0008cd5c, 0x0009efee, 0x000b3333, 0x000c9a7b, 0x000e296d, 0x000fe410, 0x0011ced6, 0x0013eea3, 0x001648e3, 0x0018e38e, 0x001bc53c, 0x001ef538, 0x00227b8e, 0x00266121, 0x002aafc2, 0x002f724a, 0x0034b4b4, 0x003a843a, 0x0040ef7a, 0x00480696, 0x004fdb60, 0x00588189, 0x00620eca, 0x006c9b26, 0x0078411d, 0x00851df4 } , { 0x00055555, 0x0005fb45, 0x0006b298, 0x00077cdf, 0x00085bc8, 0x00095128, 0x000a5efb, 0x000b8769, 0x000ccccc, 0x000e31b1, 0x000fb8de, 0x0011655a, 0x00133a71, 0x00153bbc, 0x00176d24, 0x0019d2ef, 0x001c71c7, 0x001f4ebe, 0x00226f61, 0x0025d9bb, 0x00299465, 0x002da690, 0x00321817, 0x0036f188, 0x003c3c3c, 0x00420262, 0x00484f19, 0x004f2e80, 0x0056add0, 0x005edb76, 0x0067c72f } , { 0x00060000, 0x0006a500, 0x0007594f, 0x00081e25, 0x0008f4ce, 0x0009deb1, 0x000add50, 0x000bf249, 0x000d1f5a, 0x000e6666, 0x000fc972, 0x00114aad, 0x0012ec74, 0x0014b150, 0x00169c01, 0x0018af7c, 0x001aeef6, 0x001d5de3, 0x00200000, 0x0022d953, 0x0025ee3a, 0x00294368, 0x002cddf5, 0x0030c35e, 0x0034f994, 0x00398700, 0x003e7291, 0x0043c3c3, 0x004982ad, 0x004fb80b, 0x00566d4f } , { 0x0006aaaa, 0x00074eec, 0x000800da, 0x0008c16d, 0x000991af, 0x000a72ba, 0x000b65bd, 0x000c6bfa, 0x000d86ca, 0x000eb79e, 0x00100000, 0x00116194, 0x0012de1e, 0x00147782, 0x00162fc4, 0x0018090e, 0x001a05b2, 0x001c282d, 0x001e7327, 0x0020e97b, 0x00238e38, 0x002664a7, 0x0029704a, 0x002cb4e6, 0x00303686, 0x0033f97e, 0x00380274, 0x003c5662, 0x0040fa9d, 0x0045f4df, 0x004b4b4b } , { 0x00075555, 0x0007f8fb, 0x0008a8fc, 0x00096622, 0x000a3147, 0x000b0b4e, 0x000bf52c, 0x000cefe2, 0x000dfc83, 0x000f1c30, 0x0010501f, 0x00119999, 0x0012f9fb, 0x001472b9, 0x0016055f, 0x0017b390, 0x00197f0d, 0x001b69b3, 0x001d757e, 0x001fa48a, 0x0021f917, 0x0024758a, 0x00271c71, 0x0029f084, 0x002cf4a7, 0x00302bf1, 0x003399ab, 0x00374154, 0x003b26a9, 0x003f4da1, 0x0043ba79 } , { 0x00080000, 0x0008a325, 0x0009518e, 0x000a0be5, 0x000ad2dc, 0x000ba731, 0x000c89ac, 0x000d7b1f, 0x000e7c6a, 0x000f8e78, 0x0010b242, 0x0011e8ce, 0x00133333, 0x00149297, 0x00160832, 0x0017954d, 0x00193b45, 0x001afb8d, 0x001cd7aa, 0x001ed13d, 0x0020e9fb, 0x002323b6, 0x0025805b, 0x002801f4, 0x002aaaaa, 0x002d7cc8, 0x00307ab9, 0x0033a712, 0x0037048b, 0x003a9608, 0x003e5e98 } , { 0x0008aaaa, 0x00094d63, 0x0009fa76, 0x000ab273, 0x000b75f0, 0x000c458d, 0x000d21f2, 0x000e0bcc, 0x000f03d6, 0x00100ad2, 0x0011218b, 0x001248da, 0x001381a0, 0x0014cccc, 0x00162b5a, 0x00179e52, 0x001926cc, 0x001ac5ed, 0x001c7cec, 0x001e4d0f, 0x002037af, 0x00223e37, 0x00246228, 0x0026a515, 0x002908a8, 0x002b8ea4, 0x002e38e3, 0x0031095a, 0x00340218, 0x0037254b, 0x003a753f } , { 0x00095555, 0x0009f7b1, 0x000aa3a1, 0x000b599e, 0x000c1a2c, 0x000ce5d1, 0x000dbd1b, 0x000ea09e, 0x000f90f6, 0x00108ec6, 0x00119ab9, 0x0012b582, 0x0013dfdc, 0x00151a8e, 0x00166666, 0x0017c43d, 0x001934f6, 0x001ab982, 0x001c52db, 0x001e0209, 0x001fc821, 0x0021a647, 0x00239dac, 0x0025af91, 0x0027dd47, 0x002a2832, 0x002c91c7, 0x002f1b8b, 0x0031c71c, 0x00349629, 0x00378a79 } , { 0x000a0000, 0x000aa20c, 0x000b4d00, 0x000c0147, 0x000cbf51, 0x000d8793, 0x000e5a86, 0x000f38aa, 0x00102283, 0x0011189b, 0x00121b85, 0x00132bd7, 0x00144a30, 0x00157735, 0x0016b393, 0x00180000, 0x00195d38, 0x001acc02, 0x001c4d2d, 0x001de193, 0x001f8a17, 0x002147a6, 0x00231b39, 0x002505d5, 0x0027088c, 0x0029247a, 0x002b5acc, 0x002dacba, 0x00301b8e, 0x0032a89f, 0x00355555 } }; // m = (s * n) >> 16 tb_size_t m = tb_fixed_mul(s_scale[hash_count - 1][probability], item_maxn); #endif // init size filter->size = tb_align8(m) >> 3; tb_assert_and_check_break(filter->size); if (filter->size > TB_BLOOM_FILTER_DATA_MAXN) { tb_trace_e("the need space too large, size: %lu, please decrease hash count and probability!", filter->size); break; } tb_trace_d("size: %lu", filter->size); // init data filter->data = tb_malloc0_bytes(filter->size); tb_assert_and_check_break(filter->data); // init hash mask filter->mask = tb_align_pow2((filter->size << 3)) - 1; tb_assert_and_check_break(filter->mask); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (filter) tb_bloom_filter_exit((tb_bloom_filter_ref_t)filter); filter = tb_null; } // ok? return (tb_bloom_filter_ref_t)filter; } tb_void_t tb_bloom_filter_exit(tb_bloom_filter_ref_t self) { // check tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self; tb_assert_and_check_return(filter); // exit data if (filter->data) tb_free(filter->data); filter->data = tb_null; // exit it tb_free(filter); } tb_void_t tb_bloom_filter_clear(tb_bloom_filter_ref_t self) { // check tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self; tb_assert_and_check_return(filter); // clear it if (filter->data && filter->size) tb_memset(filter->data, 0, filter->size); } tb_bool_t tb_bloom_filter_set(tb_bloom_filter_ref_t self, tb_cpointer_t data) { // check tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self; tb_assert_and_check_return_val(filter, tb_false); // walk tb_size_t i = 0; tb_size_t n = filter->hash_count; tb_bool_t ok = tb_false; for (i = 0; i < n; i++) { // compute the bit index tb_size_t index = filter->element.hash(&filter->element, data, filter->mask, i); if (index >= (filter->size << 3)) index %= (filter->size << 3); // not exists? if (!tb_bloom_filter_bset(filter->data, index)) { // set it tb_bloom_filter_set1(filter->data, index); // ok ok = tb_true; } } // ok? return ok; } tb_bool_t tb_bloom_filter_get(tb_bloom_filter_ref_t self, tb_cpointer_t data) { // check tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self; tb_assert_and_check_return_val(filter, tb_false); // walk tb_size_t i = 0; tb_size_t n = filter->hash_count; for (i = 0; i < n; i++) { // compute the bit index tb_size_t index = filter->element.hash(&filter->element, data, filter->mask, i); if (index >= (filter->size << 3)) index %= (filter->size << 3); // not exists? break it if (!tb_bloom_filter_bset(filter->data, index)) break; } // ok? return (i == n)? tb_true : tb_false; } tbox-1.6.7/src/tbox/container/bloom_filter.h 0000664 0000000 0000000 00000015610 14142237372 0021064 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file bloom_filter.h * @ingroup container * */ #ifndef TB_CONTAINER_BLOOM_FILTER_H #define TB_CONTAINER_BLOOM_FILTER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the item maxn #define TB_BLOOM_FILTER_ITEM_MAXN_MICRO (1 << 16) #define TB_BLOOM_FILTER_ITEM_MAXN_SMALL (1 << 20) #define TB_BLOOM_FILTER_ITEM_MAXN_LARGE (1 << 24) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the bloom filter type * * A Bloom filter is a space-efficient probabilistic data structure, * conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set. * False positive matches are possible, but false negatives are not; * i.e. a query returns either "possibly in set" or "definitely not in set". * Elements can be added to the set, but not removed (though this can be addressed with a "counting" filter). * The more elements that are added to the set, the larger the probability of false positives. * * Assume that a hash function selects each array position with equal probability. * If m is the number of bits in the array, and k is the number of hash functions, * then the probability that a certain bit is not set to 1 by a certain hash function * during the insertion of an element is then * 1 - 1 / m * * The probability that it is not set to 1 by any of the hash functions is * (1 - 1/ m) ^ k * * If we have inserted n elements, the probability that a certain bit is still 0 is * (1 - 1/ m) ^ kn * * the probability that it is 1 is therefore * 1 - ((1 - 1/ m) ^ kn) * * Now test membership of an element that is not in the set. * Each of the k array positions computed by the hash functions is 1 with a probability as above. * The probability of all of them being 1, * which would cause the algorithm to erroneously claim that the element is in the set, is often given as * p = (1 - ((1 - 1/ m) ^ kn))^k ~= (1 - e^(-kn/m))^k * * For a given m and n, the value of k (the number of hash functions) that minimizes the probability is * k = (m / n) * ln2 ~= (m / n) * (9 / 13) * * which gives * 2 ^ -k ~= 0.6185 ^ (m / n) * * The required number of bits m, given n (the number of inserted elements) * and a desired false positive probability p (and assuming the optimal value of k is used) * can be computed by substituting the optimal value of k in the probability expression above: * p = (1 - e ^-(m/nln2)n/m))^(m/nln2) * * which can be simplified to: * lnp = -m/n * (ln2)^2 * * This optimal results in: * s = m/n = -lnp / (ln2 * ln2) = -log2(p) / ln2 * k = s * ln2 = -log2(p) <= note: this k will be larger * * compute s(m/n) for given k and p: * p = (1 - e^(-kn/m))^k = (1 - e^(-k/s))^k * => lnp = k * ln(1 - e^(-k/s)) * => (lnp) / k = ln(1 - e^(-k/s)) * => e^((lnp) / k) = 1 - e^(-k/s) * => e^(-k/s) = 1 - e^((lnp) / k) = 1 - (e^lnp)^(1/k) = 1 - p^(1/k) * => -k/s = ln(1 - p^(1/k)) * => s = -k / ln(1 - p^(1/k)) and define c = p^(1/k) * => s = -k / ln(1 - c)) and ln(1 + x) ~= x - 0.5x^2 while x < 1 * => s ~= -k / (-c-0.5c^2) = 2k / (2c + c * c) * * so * c = p^(1/k) * s = m / n = 2k / (2c + c * c) */ typedef __tb_typeref__(bloom_filter); /// the probability of false positives typedef enum __tb_bloom_filter_probability_e { TB_BLOOM_FILTER_PROBABILITY_0_1 = 3 ///!< 1 / 2^3 = 0.125 ~= 0.1 , TB_BLOOM_FILTER_PROBABILITY_0_01 = 6 ///!< 1 / 2^6 = 0.015625 ~= 0.01 , TB_BLOOM_FILTER_PROBABILITY_0_001 = 10 ///!< 1 / 2^10 = 0.0009765625 ~= 0.001 , TB_BLOOM_FILTER_PROBABILITY_0_0001 = 13 ///!< 1 / 2^13 = 0.0001220703125 ~= 0.0001 , TB_BLOOM_FILTER_PROBABILITY_0_00001 = 16 ///!< 1 / 2^16 = 0.0000152587890625 ~= 0.00001 , TB_BLOOM_FILTER_PROBABILITY_0_000001 = 20 ///!< 1 / 2^20 = 0.00000095367431640625 ~= 0.000001 }tb_bloom_filter_probability_e; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init bloom filter * * @note not supports iterator * * @param probability the probability of false positives * @param hash_count the hash count: < 16 * @param item_maxn the item maxn * @param element the element only for hash * * @return the bloom filter */ tb_bloom_filter_ref_t tb_bloom_filter_init(tb_size_t probability, tb_size_t hash_count, tb_size_t item_maxn, tb_element_t element); /*! exit bloom filter * * @param bloom_filter the bloom filter */ tb_void_t tb_bloom_filter_exit(tb_bloom_filter_ref_t bloom_filter); /*! clear bloom filter * * @param bloom_filter the bloom filter */ tb_void_t tb_bloom_filter_clear(tb_bloom_filter_ref_t bloom_filter); /*! set data to the bloom filter * * @code * if (tb_bloom_filter_set(filter, data)) * { * tb_trace_i("this data not exists, set ok!"); * } * else * { * tb_trace_i("this data have been existed, set failed!"); * * // note: maybe false positives * } * @endcode * * @param bloom_filter the bloom filter * @param data the item data * * @return return tb_false if the data have been existed, otherwise set it and return tb_true */ tb_bool_t tb_bloom_filter_set(tb_bloom_filter_ref_t bloom_filter, tb_cpointer_t data); /*! get data to the bloom filter * * @code * if (tb_bloom_filter_get(filter, data)) * { * tb_trace_i("this data have been existed, get ok!"); * * // note: maybe false positives * } * else * { * tb_trace_i("this data not exists, get failed!"); * } * @endcode * * @param bloom_filter the bloom filter * @param data the item data * * @return return tb_true if the data exists, otherwise return tb_false */ tb_bool_t tb_bloom_filter_get(tb_bloom_filter_ref_t bloom_filter, tb_cpointer_t data); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/circle_queue.c 0000664 0000000 0000000 00000023027 14142237372 0021050 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file circle_queue.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "circle_queue.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../memory/memory.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ #ifdef __tb_small__ # define TB_CIRCLE_QUEUE_SIZE_DEFAULT (256) #else # define TB_CIRCLE_QUEUE_SIZE_DEFAULT (65536) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the circle queue type typedef struct __tb_circle_queue_t { // the itor tb_iterator_t itor; // the data tb_byte_t* data; // the head tb_size_t head; // the tail tb_size_t tail; // the maxn tb_size_t maxn; // the size tb_size_t size; // the element tb_element_t element; }tb_circle_queue_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_size_t tb_circle_queue_itor_size(tb_iterator_ref_t iterator) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue, 0); // the size return queue->size; } static tb_size_t tb_circle_queue_itor_head(tb_iterator_ref_t iterator) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue, 0); // head return queue->head; } static tb_size_t tb_circle_queue_itor_last(tb_iterator_ref_t iterator) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue, 0); // last return (queue->tail + queue->maxn - 1) % queue->maxn; } static tb_size_t tb_circle_queue_itor_tail(tb_iterator_ref_t iterator) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue, 0); // tail return queue->tail; } static tb_size_t tb_circle_queue_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue, 0); // next return (itor + 1) % queue->maxn; } static tb_size_t tb_circle_queue_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue, 0); // prev return (itor + queue->maxn - 1) % queue->maxn; } static tb_pointer_t tb_circle_queue_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue && itor < queue->maxn, tb_null); // item return queue->element.data(&queue->element, queue->data + itor * iterator->step); } static tb_void_t tb_circle_queue_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert(queue); // copy queue->element.copy(&queue->element, queue->data + itor * iterator->step, item); } static tb_long_t tb_circle_queue_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator; tb_assert_and_check_return_val(queue && queue->element.comp, 0); // comp return queue->element.comp(&queue->element, litem, ritem); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_circle_queue_ref_t tb_circle_queue_init(tb_size_t maxn, tb_element_t element) { // check tb_assert_and_check_return_val(element.size && element.dupl && element.data, tb_null); // done tb_bool_t ok = tb_false; tb_circle_queue_t* queue = tb_null; do { // make queue queue = tb_malloc0_type(tb_circle_queue_t); tb_assert_and_check_break(queue); // using the default maxn if (!maxn) maxn = TB_CIRCLE_QUEUE_SIZE_DEFAULT; // init queue, + tail queue->maxn = maxn + 1; queue->element = element; // init operation static tb_iterator_op_t op = { tb_circle_queue_itor_size , tb_circle_queue_itor_head , tb_circle_queue_itor_last , tb_circle_queue_itor_tail , tb_circle_queue_itor_prev , tb_circle_queue_itor_next , tb_circle_queue_itor_item , tb_circle_queue_itor_comp , tb_circle_queue_itor_copy , tb_null , tb_null }; // init iterator queue->itor.priv = tb_null; queue->itor.step = element.size; queue->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_MUTABLE; queue->itor.op = &op; // make data queue->data = (tb_byte_t*)tb_nalloc0(queue->maxn, element.size); tb_assert_and_check_break(queue->data); // ok ok = tb_true; } while (0); // failed? if (!ok) { if (queue) tb_circle_queue_exit((tb_circle_queue_ref_t)queue); queue = tb_null; } // ok? return (tb_circle_queue_ref_t)queue; } tb_void_t tb_circle_queue_exit(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return(queue); // clear data tb_circle_queue_clear(self); // free data if (queue->data) tb_free(queue->data); // free it tb_free(queue); } tb_void_t tb_circle_queue_clear(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return(queue); // clear it while (!tb_circle_queue_null(self)) tb_circle_queue_pop(self); queue->head = 0; queue->tail = 0; queue->size = 0; } tb_void_t tb_circle_queue_put(tb_circle_queue_ref_t self, tb_cpointer_t data) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return(queue && queue->size < queue->maxn); // put it queue->element.dupl(&queue->element, queue->data + queue->tail * queue->element.size, data); queue->tail = (queue->tail + 1) % queue->maxn; queue->size++; } tb_void_t tb_circle_queue_pop(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return(queue && queue->size); // pop it if (queue->element.free) queue->element.free(&queue->element, queue->data + queue->head * queue->element.size); queue->head = (queue->head + 1) % queue->maxn; queue->size--; } tb_pointer_t tb_circle_queue_get(tb_circle_queue_ref_t self) { // get the head item return tb_circle_queue_head(self); } tb_pointer_t tb_circle_queue_head(tb_circle_queue_ref_t self) { // the head item return tb_iterator_item((tb_iterator_ref_t)self, tb_iterator_head((tb_iterator_ref_t)self)); } tb_pointer_t tb_circle_queue_last(tb_circle_queue_ref_t self) { // the last item return tb_iterator_item((tb_iterator_ref_t)self, tb_iterator_last((tb_iterator_ref_t)self)); } tb_size_t tb_circle_queue_size(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return_val(queue, 0); // the size return queue->size; } tb_size_t tb_circle_queue_maxn(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return_val(queue, 0); // the maxn return queue->maxn; } tb_bool_t tb_circle_queue_full(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return_val(queue, tb_true); // is full? return (queue->size + 1) == queue->maxn; } tb_bool_t tb_circle_queue_null(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return_val(queue, tb_true); // is null? return !queue->size; } #ifdef __tb_debug__ tb_void_t tb_circle_queue_dump(tb_circle_queue_ref_t self) { // check tb_circle_queue_t* queue = (tb_circle_queue_t*)self; tb_assert_and_check_return(queue); // trace tb_trace_i("self: size: %lu", tb_circle_queue_size(self)); // done tb_char_t cstr[4096]; tb_for_all (tb_pointer_t, data, self) { // trace if (queue->element.cstr) { tb_trace_i(" %s", queue->element.cstr(&queue->element, data, cstr, sizeof(cstr))); } else { tb_trace_i(" %p", data); } } } #endif tbox-1.6.7/src/tbox/container/circle_queue.h 0000664 0000000 0000000 00000010326 14142237372 0021053 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file queue.h * @ingroup container * */ #ifndef TB_CONTAINER_CIRCLE_QUEUE_H #define TB_CONTAINER_CIRCLE_QUEUE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the circle queue ref type * *
* queue: |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||------| * head last tail * * queue: ||||||||||||||-----|--------------------------|||||||||||||||||||||||||| * last tail head * * performance: * * put: O(1) * pop: O(1) * * iterator: * * next: fast * prev: fast * ** * @note the index of the same item is mutable * */ typedef tb_iterator_ref_t tb_circle_queue_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init queue * * @param maxn the item maxn, using the default maxn if be zero * @param element the element * * @return the queue */ tb_circle_queue_ref_t tb_circle_queue_init(tb_size_t maxn, tb_element_t element); /*! exit queue * * @param queue the queue */ tb_void_t tb_circle_queue_exit(tb_circle_queue_ref_t queue); /*! the queue head item * * @param queue the queue * * @return the head item */ tb_pointer_t tb_circle_queue_head(tb_circle_queue_ref_t queue); /*! the queue last item * * @param queue the queue * * @return the last item */ tb_pointer_t tb_circle_queue_last(tb_circle_queue_ref_t queue); /*! clear the queue * * @param queue the queue */ tb_void_t tb_circle_queue_clear(tb_circle_queue_ref_t queue); /*! put the queue item * * @param queue the queue * @param data the item data */ tb_void_t tb_circle_queue_put(tb_circle_queue_ref_t queue, tb_cpointer_t data); /*! pop the queue item * * @param queue the queue */ tb_void_t tb_circle_queue_pop(tb_circle_queue_ref_t queue); /*! get the queue item * * @param queue the queue * * @return the queue item */ tb_pointer_t tb_circle_queue_get(tb_circle_queue_ref_t queue); /*! the queue size * * @param queue the queue * * @return the queue size */ tb_size_t tb_circle_queue_size(tb_circle_queue_ref_t queue); /*! the queue maxn * * @param queue the queue * * @return the queue maxn */ tb_size_t tb_circle_queue_maxn(tb_circle_queue_ref_t queue); /*! the queue full? * * @param queue the queue * * @return tb_true or tb_false */ tb_bool_t tb_circle_queue_full(tb_circle_queue_ref_t queue); /*! the queue null? * * @param queue the queue * * @return tb_true or tb_false */ tb_bool_t tb_circle_queue_null(tb_circle_queue_ref_t queue); #ifdef __tb_debug__ /*! dump queue * * @param queue the queue */ tb_void_t tb_circle_queue_dump(tb_circle_queue_ref_t circle_queue); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/container.h 0000664 0000000 0000000 00000002400 14142237372 0020362 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file container.h * @defgroup container * */ #ifndef TB_CONTAINER_H #define TB_CONTAINER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" #include "array_iterator.h" #include "heap.h" #include "stack.h" #include "vector.h" #include "hash_set.h" #include "hash_map.h" #include "queue.h" #include "circle_queue.h" #include "priority_queue.h" #include "list.h" #include "list_entry.h" #include "single_list.h" #include "single_list_entry.h" #include "bloom_filter.h" #endif tbox-1.6.7/src/tbox/container/element.h 0000664 0000000 0000000 00000022625 14142237372 0020044 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file element.h * @ingroup container * */ #ifndef TB_CONTAINER_ELEMENT_H #define TB_CONTAINER_ELEMENT_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the element ref type typedef struct __tb_element_t* tb_element_ref_t; /*! the element data hash function type * * @param element the element * @param data the element data * @param mask the hash mask * @param index the hash index * * @return the hash value */ typedef tb_size_t (*tb_element_hash_func_t)(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index); /*! the element data compare function type * * @param element the element * @param ldata the left-hand data * @param rdata the right-hand data * * @return equal: 0, 1: >, -1: < */ typedef tb_long_t (*tb_element_comp_func_t)(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata); /*! the element data function type * * @param element the element * @param buff the element data address * * @return the element data */ typedef tb_pointer_t (*tb_element_data_func_t)(tb_element_ref_t element, tb_cpointer_t buff); /*! the element data string function type * * @param element the element * @param data the element data * @param cstr the string buffer * @param maxn the string buffer maximum size * * @return the string pointer */ typedef tb_char_t const* (*tb_element_cstr_func_t)(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn); /*! the element free function type * * @param element the element * @param buff the element buffer */ typedef tb_void_t (*tb_element_free_func_t)(tb_element_ref_t element, tb_pointer_t buff); /*! the element duplicate function type * * allocate a new element and copy the element data * * @param element the element * @param buff the element buffer * @param data the element data */ typedef tb_void_t (*tb_element_dupl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data); /*! the element replace function type * * free the previous element data and duplicate the new data * * @param element the element * @param buff the element buffer * @param data the element data */ typedef tb_void_t (*tb_element_repl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data); /*! the element copy function type * * only copy the element data and not allocate new element * * @param element the element * @param buff the element buffer * @param data the element data */ typedef tb_void_t (*tb_element_copy_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data); /*! the elements free function type * * free some elements * * @param element the element * @param buff the element buffer * @param size the element count */ typedef tb_void_t (*tb_element_nfree_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size); /*! the elements duplicate function type * * duplicate some elements * * @param element the element * @param buff the element buffer * @param data the element data * @param size the element count */ typedef tb_void_t (*tb_element_ndupl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size); /*! the elements replace function type * * replace some elements * * @param element the element * @param buff the element buffer * @param data the element data * @param size the element count */ typedef tb_void_t (*tb_element_nrepl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size); /*! the elements copy function type * * copy some elements * * @param element the element * @param buff the element buffer * @param data the element data * @param size the element count */ typedef tb_void_t (*tb_element_ncopy_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size); /// the element type typedef enum __tb_element_type_t { TB_ELEMENT_TYPE_NULL = 0 //!< null , TB_ELEMENT_TYPE_LONG = 1 //!< long , TB_ELEMENT_TYPE_SIZE = 2 //!< size , TB_ELEMENT_TYPE_UINT8 = 3 //!< uint8 , TB_ELEMENT_TYPE_UINT16 = 4 //!< uint16 , TB_ELEMENT_TYPE_UINT32 = 5 //!< uint32 , TB_ELEMENT_TYPE_STR = 6 //!< string , TB_ELEMENT_TYPE_PTR = 7 //!< pointer , TB_ELEMENT_TYPE_MEM = 8 //!< memory , TB_ELEMENT_TYPE_OBJ = 9 //!< object , TB_ELEMENT_TYPE_TRUE = 10 //!< true , TB_ELEMENT_TYPE_USER = 11 //!< the user-defined type }tb_element_type_t; /// the element type typedef struct __tb_element_t { /// the element type tb_uint16_t type; /// the element flag tb_uint16_t flag; /// the element size tb_uint16_t size; /// the priv data tb_cpointer_t priv; /// the hash function tb_element_hash_func_t hash; /// the compare function tb_element_comp_func_t comp; /// the data function tb_element_data_func_t data; /// the string function tb_element_cstr_func_t cstr; /// the free element tb_element_free_func_t free; /// the duplicate function tb_element_dupl_func_t dupl; /// the replace function tb_element_repl_func_t repl; /// the copy function tb_element_copy_func_t copy; /// the free elements function tb_element_nfree_func_t nfree; /// the duplicate elements function tb_element_ndupl_func_t ndupl; /// the replace elements function tb_element_nrepl_func_t nrepl; /// the copy elements function tb_element_ncopy_func_t ncopy; }tb_element_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the null element, no space * * @return the element */ tb_element_t tb_element_null(tb_noarg_t); /*! the true element, no space * * .e.g for hash data * * @return the element */ tb_element_t tb_element_true(tb_noarg_t); /*! the long element * * @return the element */ tb_element_t tb_element_long(tb_noarg_t); /*! the size element * * @return the element */ tb_element_t tb_element_size(tb_noarg_t); /*! the uint8 element * * @return the element */ tb_element_t tb_element_uint8(tb_noarg_t); /*! the uint16 element for * * @return the element */ tb_element_t tb_element_uint16(tb_noarg_t); /*! the uint32 element * * @return the element */ tb_element_t tb_element_uint32(tb_noarg_t); /*! the string element * * @param is_case is case? * * @return the element */ tb_element_t tb_element_str(tb_bool_t is_case); /*! the pointer element * * @note if the free function have been hooked, the nfree need hook too. * * @param free the element free function * @param priv the private data of the element free function * * @return the element */ tb_element_t tb_element_ptr(tb_element_free_func_t free, tb_cpointer_t priv); /*! the object element * * @return the element */ tb_element_t tb_element_obj(tb_noarg_t); /*! the memory element with the fixed space * * @param size the element size * @param free the element free function * @param priv the private data of the element free function * * @return the element */ tb_element_t tb_element_mem(tb_size_t size, tb_element_free_func_t free, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/element/ 0000775 0000000 0000000 00000000000 14142237372 0017664 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/container/element/hash.c 0000664 0000000 0000000 00000023307 14142237372 0020760 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file hash.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "hash.h" #include "../../hash/hash.h" /* ////////////////////////////////////////////////////////////////////////////////////// * data hash implementation */ static tb_size_t tb_element_hash_data_func_0(tb_byte_t const* data, tb_size_t size) { return tb_bkdr_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_1(tb_byte_t const* data, tb_size_t size) { return tb_adler32_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_2(tb_byte_t const* data, tb_size_t size) { return tb_fnv32_1a_make(data, size, 0); } #if !defined(__tb_small__) && defined(TB_CONFIG_MODULE_HAVE_HASH) static tb_size_t tb_element_hash_data_func_3(tb_byte_t const* data, tb_size_t size) { return tb_ap_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_4(tb_byte_t const* data, tb_size_t size) { return tb_murmur_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_5(tb_byte_t const* data, tb_size_t size) { return tb_crc32_le_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_6(tb_byte_t const* data, tb_size_t size) { return tb_fnv32_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_7(tb_byte_t const* data, tb_size_t size) { return tb_djb2_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_8(tb_byte_t const* data, tb_size_t size) { return tb_blizzard_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_9(tb_byte_t const* data, tb_size_t size) { return tb_rs_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_10(tb_byte_t const* data, tb_size_t size) { return tb_sdbm_make(data, size, 0); } static tb_size_t tb_element_hash_data_func_11(tb_byte_t const* data, tb_size_t size) { // using md5, better but too slower tb_byte_t b[16] = {0}; tb_md5_make(data, size, b, 16); return tb_bits_get_u32_ne(b); } static tb_size_t tb_element_hash_data_func_12(tb_byte_t const* data, tb_size_t size) { // using sha, better but too slower tb_byte_t b[32] = {0}; tb_sha_make(TB_SHA_MODE_SHA1_160, data, size, b, 32); return tb_bits_get_u32_ne(b); } static tb_size_t tb_element_hash_data_func_13(tb_byte_t const* data, tb_size_t size) { tb_trace_noimpl(); return 0; } static tb_size_t tb_element_hash_data_func_14(tb_byte_t const* data, tb_size_t size) { tb_trace_noimpl(); return 0; } static tb_size_t tb_element_hash_data_func_15(tb_byte_t const* data, tb_size_t size) { tb_trace_noimpl(); return 0; } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * cstr hash implementation */ static tb_size_t tb_element_hash_cstr_func_0(tb_char_t const* data) { return tb_bkdr_make_from_cstr(data, 0); } static tb_size_t tb_element_hash_cstr_func_1(tb_char_t const* data) { return tb_fnv32_1a_make_from_cstr(data, 0); } /* ////////////////////////////////////////////////////////////////////////////////////// * uint8 hash implementation */ static tb_size_t tb_element_hash_uint8_func_0(tb_uint8_t value) { return (tb_size_t)value; } static tb_size_t tb_element_hash_uint8_func_1(tb_uint8_t value) { return (tb_size_t)(((tb_uint64_t)(value) * 2654435761ul) >> 16); } /* ////////////////////////////////////////////////////////////////////////////////////// * uint16 hash implementation */ static tb_size_t tb_element_hash_uint16_func_0(tb_uint16_t value) { return (tb_size_t)(((tb_uint64_t)(value) * 2654435761ul) >> 16); } /* ////////////////////////////////////////////////////////////////////////////////////// * uint32 hash implementation */ static tb_size_t tb_element_hash_uint32_func_0(tb_uint32_t value) { return (tb_size_t)(((tb_uint64_t)(value) * 2654435761ul) >> 16); } static tb_size_t tb_element_hash_uint32_func_1(tb_uint32_t value) { // Bob Jenkins' 32 bit integer hash function value = (value + 0x7ed55d16) + (value << 12); value = (value ^ 0xc761c23c) ^ (value >> 19); value = (value + 0x165667b1) + (value << 5); value = (value + 0xd3a2646c) ^ (value << 9); value = (value + 0xfd7046c5) + (value << 3); value = (value ^ 0xb55a4f09) ^ (value >> 16); return value; } static tb_size_t tb_element_hash_uint32_func_2(tb_uint32_t value) { // Tomas Wang value = ~value + (value << 15); value = value ^ (value >> 12); value = value + (value << 2); value = value ^ (value >> 4); value = value * 2057; value = value ^ (value >> 16); return value; } /* ////////////////////////////////////////////////////////////////////////////////////// * uint64 hash implementation */ static tb_size_t tb_element_hash_uint64_func_0(tb_uint64_t value) { return (tb_size_t)((value * 2654435761ul) >> 16); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_element_hash_uint8(tb_uint8_t value, tb_size_t mask, tb_size_t index) { // check tb_assert_and_check_return_val(mask, 0); // for optimization if (index < 2) { // the func static tb_size_t (*s_func[])(tb_uint8_t) = { tb_element_hash_uint8_func_0 , tb_element_hash_uint8_func_1 }; tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0); // done return s_func[index](value) & mask; } // using uint32 hash tb_uint32_t v = (tb_uint32_t)value; return tb_element_hash_uint32(v | (v << 8) | (v << 16) | (v << 24), mask, index - 1); } tb_size_t tb_element_hash_uint16(tb_uint16_t value, tb_size_t mask, tb_size_t index) { // check tb_assert_and_check_return_val(mask, 0); // for optimization if (index < 1) { // the func static tb_size_t (*s_func[])(tb_uint16_t) = { tb_element_hash_uint16_func_0 }; tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0); // done return s_func[index](value) & mask; } // using uint32 hash tb_uint32_t v = (tb_uint32_t)value; return tb_element_hash_uint32(v | (v << 16), mask, index); } tb_size_t tb_element_hash_uint32(tb_uint32_t value, tb_size_t mask, tb_size_t index) { // check tb_assert_and_check_return_val(mask, 0); // for optimization if (index < 3) { // the func static tb_size_t (*s_func[])(tb_uint32_t) = { tb_element_hash_uint32_func_0 , tb_element_hash_uint32_func_1 , tb_element_hash_uint32_func_2 }; tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0); // done return s_func[index](value) & mask; } // done return tb_element_hash_data((tb_byte_t const*)&value, sizeof(tb_uint32_t), mask, index - 3); } tb_size_t tb_element_hash_uint64(tb_uint64_t value, tb_size_t mask, tb_size_t index) { // for optimization if (index < 1) { // the func static tb_size_t (*s_func[])(tb_uint64_t) = { tb_element_hash_uint64_func_0 }; tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0); // done return s_func[index](value) & mask; } // using the uint32 hash tb_size_t hash0 = tb_element_hash_uint32((tb_uint32_t)value, mask, index); tb_size_t hash1 = tb_element_hash_uint32((tb_uint32_t)(value >> 32), mask, index); return ((hash0 ^ hash1) & mask); } tb_size_t tb_element_hash_data(tb_byte_t const* data, tb_size_t size, tb_size_t mask, tb_size_t index) { // check tb_assert_and_check_return_val(data && size && mask, 0); // the func static tb_size_t (*s_func[])(tb_byte_t const* , tb_size_t) = { tb_element_hash_data_func_0 , tb_element_hash_data_func_1 , tb_element_hash_data_func_2 #if !defined(__tb_small__) && defined(TB_CONFIG_MODULE_HAVE_HASH) , tb_element_hash_data_func_3 , tb_element_hash_data_func_4 , tb_element_hash_data_func_5 , tb_element_hash_data_func_6 , tb_element_hash_data_func_7 , tb_element_hash_data_func_8 , tb_element_hash_data_func_9 , tb_element_hash_data_func_10 , tb_element_hash_data_func_11 , tb_element_hash_data_func_12 , tb_element_hash_data_func_13 , tb_element_hash_data_func_14 , tb_element_hash_data_func_15 #endif }; tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0); // done return s_func[index](data, size) & mask; } tb_size_t tb_element_hash_cstr(tb_char_t const* cstr, tb_size_t mask, tb_size_t index) { // check tb_assert_and_check_return_val(cstr && mask, 0); // for optimization if (index < 2) { // the func static tb_size_t (*s_func[])(tb_char_t const*) = { tb_element_hash_cstr_func_0 , tb_element_hash_cstr_func_1 }; tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0); // done return s_func[index](cstr) & mask; } // using the data hash return tb_element_hash_data((tb_byte_t const*)cstr, tb_strlen(cstr), mask, index); } tbox-1.6.7/src/tbox/container/element/hash.h 0000664 0000000 0000000 00000005553 14142237372 0020770 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file hash.h * */ #ifndef TB_CONTAINER_ELEMENT_HASH_H #define TB_CONTAINER_ELEMENT_HASH_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* compute the uint8 hash * * @param value the value * @param mask the mask * @param index the hash func index * * @return the hash value */ tb_size_t tb_element_hash_uint8(tb_uint8_t value, tb_size_t mask, tb_size_t index); /* compute the uint16 hash * * @param value the value * @param mask the mask * @param index the hash func index * * @return the hash value */ tb_size_t tb_element_hash_uint16(tb_uint16_t value, tb_size_t mask, tb_size_t index); /* compute the uint32 hash * * @param value the value * @param mask the mask * @param index the hash func index * * @return the hash value */ tb_size_t tb_element_hash_uint32(tb_uint32_t value, tb_size_t mask, tb_size_t index); /* compute the uint64 hash * * @param value the value * @param mask the mask * @param index the hash func index * * @return the hash value */ tb_size_t tb_element_hash_uint64(tb_uint64_t value, tb_size_t mask, tb_size_t index); /* compute the data hash * * @param data the data * @param size the size * @param mask the mask * @param index the hash func index * * @return the hash value */ tb_size_t tb_element_hash_data(tb_byte_t const* data, tb_size_t size, tb_size_t mask, tb_size_t index); /* compute the cstring hash * * @param cstr the cstring * @param mask the mask * @param index the hash func index * * @return the hash value */ tb_size_t tb_element_hash_cstr(tb_char_t const* cstr, tb_size_t mask, tb_size_t index); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/element/long.c 0000664 0000000 0000000 00000007037 14142237372 0020776 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file long.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_long_t tb_element_long_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata) { // compare it return ((tb_long_t)ldata < (tb_long_t)rdata)? -1 : ((tb_long_t)ldata > (tb_long_t)rdata); } static tb_pointer_t tb_element_long_data(tb_element_ref_t element, tb_cpointer_t buff) { // check tb_assert_and_check_return_val(buff, tb_null); // the element data return (tb_pointer_t)*((tb_long_t*)buff); } static tb_char_t const* tb_element_long_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(element && cstr, ""); // format string tb_long_t n = tb_snprintf(cstr, maxn, "%ld", (tb_long_t)data); if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0'; // ok? return (tb_char_t const*)cstr; } static tb_void_t tb_element_long_free(tb_element_ref_t element, tb_pointer_t buff) { // check tb_assert_and_check_return(buff); // clear *((tb_size_t*)buff) = 0; } static tb_void_t tb_element_long_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { // check tb_assert_and_check_return(buff); // copy element *((tb_long_t*)buff) = (tb_long_t)data; } static tb_void_t tb_element_long_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size) { // check tb_assert_and_check_return(buff); // clear elements if (size) tb_memset(buff, 0, size * sizeof(tb_long_t)); } static tb_void_t tb_element_long_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { // check tb_assert_and_check_return(buff); // copy elements if (size) tb_memset_ptr(buff, data, size); } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_element_t tb_element_long() { // the size element tb_element_t element_size = tb_element_size(); // init element tb_element_t element = {0}; element.type = TB_ELEMENT_TYPE_LONG; element.flag = 0; element.hash = element_size.hash; element.comp = tb_element_long_comp; element.data = tb_element_long_data; element.cstr = tb_element_long_cstr; element.free = tb_element_long_free; element.dupl = tb_element_long_copy; element.repl = tb_element_long_copy; element.copy = tb_element_long_copy; element.nfree = tb_element_long_nfree; element.ndupl = tb_element_long_ncopy; element.nrepl = tb_element_long_ncopy; element.ncopy = tb_element_long_ncopy; element.size = sizeof(tb_long_t); // ok? return element; } tbox-1.6.7/src/tbox/container/element/mem.c 0000664 0000000 0000000 00000013136 14142237372 0020612 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file mem.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "hash.h" #include "../../hash/hash.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_size_t tb_element_mem_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index) { return tb_element_hash_data((tb_byte_t const*)data, element->size, mask, index); } static tb_long_t tb_element_mem_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata) { // check tb_assert_and_check_return_val(element && element->size && ldata && rdata, 0); // comp return tb_memcmp(ldata, rdata, element->size); } static tb_pointer_t tb_element_mem_data(tb_element_ref_t element, tb_cpointer_t buff) { // check tb_assert_and_check_return_val(element && buff, tb_null); // the element data return (tb_pointer_t)buff; } static tb_char_t const* tb_element_mem_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(element && element->size && cstr && data, tb_null); // make info tb_long_t size = tb_snprintf(cstr, maxn, "0x%x", tb_adler32_make((tb_byte_t const*)data, element->size, 0)); if (size >= 0) cstr[size] = '\0'; // ok? return cstr; } static tb_void_t tb_element_mem_free(tb_element_ref_t element, tb_pointer_t buff) { // check tb_assert_and_check_return(element && element->size && buff); // clear it tb_memset(buff, 0, element->size); } static tb_void_t tb_element_mem_dupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { // check tb_assert_and_check_return(element && element->size && buff && data); // copy element tb_memcpy(buff, data, element->size); } static tb_void_t tb_element_mem_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { // check tb_assert_and_check_return(element && element->size && buff && data); // the free is hooked? free it if (element->free != tb_element_mem_free && element->free) element->free(element, buff); // copy element tb_memcpy(buff, data, element->size); } static tb_void_t tb_element_mem_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { // check tb_assert_and_check_return(element && element->size && buff && data); // copy element tb_memcpy(buff, data, element->size); } static tb_void_t tb_element_mem_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size) { // check tb_assert_and_check_return(element && element->size && buff); // the free is hooked? free it if (element->free != tb_element_mem_free && element->free) { tb_size_t n = size; while (n--) element->free(element, (tb_byte_t*)buff + n * element->size); } // clear if (size) tb_memset(buff, 0, size * element->size); } static tb_void_t tb_element_mem_ndupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { // check tb_assert_and_check_return(element && element->size && buff && data); // copy elements if (element->ncopy) element->ncopy(element, buff, data, size); } static tb_void_t tb_element_mem_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { // check tb_assert_and_check_return(element && element->size && buff && data); // free elements if (element->nfree) element->nfree(element, buff, size); // copy elements if (element->ncopy) element->ncopy(element, buff, data, size); } static tb_void_t tb_element_mem_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { // check tb_assert_and_check_return(element && element->size && buff && data); // copy elements while (size--) tb_memcpy((tb_byte_t*)buff + size * element->size, data, element->size); } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_element_t tb_element_mem(tb_size_t size, tb_element_free_func_t free, tb_cpointer_t priv) { // check tb_assert(size < TB_MAXU16); // init element tb_element_t element = {0}; element.type = TB_ELEMENT_TYPE_MEM; element.flag = 0; element.hash = tb_element_mem_hash; element.comp = tb_element_mem_comp; element.data = tb_element_mem_data; element.cstr = tb_element_mem_cstr; element.free = free? free : tb_element_mem_free; element.dupl = tb_element_mem_dupl; element.repl = tb_element_mem_repl; element.copy = tb_element_mem_copy; element.nfree = tb_element_mem_nfree; element.ndupl = tb_element_mem_ndupl; element.nrepl = tb_element_mem_nrepl; element.ncopy = tb_element_mem_ncopy; element.size = (tb_uint16_t)size; element.priv = priv; // ok? return element; } tbox-1.6.7/src/tbox/container/element/null.c 0000664 0000000 0000000 00000005730 14142237372 0021007 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file null.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_size_t tb_element_null_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t size, tb_size_t index) { return 0; } static tb_long_t tb_element_null_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata) { // always be equal return 0; } static tb_pointer_t tb_element_null_data(tb_element_ref_t element, tb_cpointer_t buff) { // the element data return (tb_pointer_t)tb_null; } static tb_char_t const* tb_element_null_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(element && cstr && maxn, ""); // format string tb_strlcpy(cstr, "null", maxn); // ok? return (tb_char_t const*)cstr; } static tb_void_t tb_element_null_free(tb_element_ref_t element, tb_pointer_t buff) { } static tb_void_t tb_element_null_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size) { } static tb_void_t tb_element_null_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { tb_assert(data == tb_null); } static tb_void_t tb_element_null_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { tb_assert(data == tb_null); } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_element_t tb_element_null() { // init element tb_element_t element = {0}; element.type = TB_ELEMENT_TYPE_NULL; element.flag = 0; element.hash = tb_element_null_hash; element.comp = tb_element_null_comp; element.data = tb_element_null_data; element.cstr = tb_element_null_cstr; element.free = tb_element_null_free; element.dupl = tb_element_null_repl; element.repl = tb_element_null_repl; element.copy = tb_element_null_repl; element.nfree = tb_element_null_nfree; element.ndupl = tb_element_null_nrepl; element.nrepl = tb_element_null_nrepl; element.ncopy = tb_element_null_nrepl; element.size = 0; // ok? return element; } tbox-1.6.7/src/tbox/container/element/obj.c 0000664 0000000 0000000 00000006456 14142237372 0020615 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file obj.c * @ingroup container */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_char_t const* tb_element_obj_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(cstr, ""); // format string tb_long_t n = tb_snprintf(cstr, maxn, "
* 0 1 3 ... ... n n + 1 * hash_list: |--------|--------|--------|--------|--------|--------|--------|--------| * | * ----- * item_list: | | key:0 * ----- * | | key:1 * ----- <= insert by binary search algorithm * | | key:2 * ----- * | | key:3 * ----- * | | key:4 * ----- * | | * ----- * | | * ----- * | | * ----- * ** * @note the itor of the same item is mutable */ typedef tb_iterator_ref_t tb_hash_map_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init hash map * * @param bucket_size the hash bucket size, using the default size if be zero * @param element_name the item for name * @param element_data the item for data * * @return the hash map */ tb_hash_map_ref_t tb_hash_map_init(tb_size_t bucket_size, tb_element_t element_name, tb_element_t element_data); /*! exit hash map * * @param hash_map the hash map */ tb_void_t tb_hash_map_exit(tb_hash_map_ref_t hash_map); /*! clear hash map * * @param hash_map the hash map */ tb_void_t tb_hash_map_clear(tb_hash_map_ref_t hash_map); /*! get item data from name * * @note * the return value may be zero if the item type is integer * so we need call tb_hash_map_find for judging whether to get value successfully * * @code * * // find item and get item data * tb_xxxx_ref_t data = (tb_xxxx_ref_t)tb_hash_map_get(hash_map, name); * if (data) * { * // ... * } * @endcode * * @param hash_map the hash map * @param name the item name * * @return the item data */ tb_pointer_t tb_hash_map_get(tb_hash_map_ref_t hash_map, tb_cpointer_t name); /*! find item from name * * @code * * // find item * tb_size_t itor = tb_hash_map_find(hash_map, name); * if (itor != tb_iterator_tail(hash_map)) * { * // get data * tb_xxxx_ref_t data = (tb_xxxx_ref_t)tb_iterator_item(hash_map, itor); * tb_assert(data); * * // remove it * tb_iterator_remove(hash_map, itor); * } * @endcode * * @param hash_map the hash map * @param name the item name * * @return the item itor, @note: the itor of the same item is mutable */ tb_size_t tb_hash_map_find(tb_hash_map_ref_t hash_map, tb_cpointer_t name); /*! insert item data from name * * @note the pair (name => data) is unique * * @param hash_map the hash map * @param name the item name * @param data the item data * * @return the item itor, @note: the itor of the same item is mutable */ tb_size_t tb_hash_map_insert(tb_hash_map_ref_t hash_map, tb_cpointer_t name, tb_cpointer_t data); /*! remove item from name * * @param hash_map the hash map * @param name the item name */ tb_void_t tb_hash_map_remove(tb_hash_map_ref_t hash_map, tb_cpointer_t name); /*! the hash map size * * @param hash_map the hash map * * @return the hash map size */ tb_size_t tb_hash_map_size(tb_hash_map_ref_t hash_map); /*! the hash map maxn * * @param hash_map the hash map * * @return the hash map maxn */ tb_size_t tb_hash_map_maxn(tb_hash_map_ref_t hash_map); #ifdef __tb_debug__ /*! dump hash * * @param hash_map the hash map */ tb_void_t tb_hash_map_dump(tb_hash_map_ref_t hash_map); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/hash_set.c 0000664 0000000 0000000 00000007356 14142237372 0020210 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file hash_set.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "hash_set" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "hash_set.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the hash map itor item func type typedef tb_pointer_t (*gb_hash_map_item_func_t)(tb_iterator_ref_t, tb_size_t); /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_pointer_t tb_hash_set_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && iterator->priv); // the item func for the hash map gb_hash_map_item_func_t func = (gb_hash_map_item_func_t)iterator->priv; // get the item of the hash map tb_hash_map_item_ref_t item = (tb_hash_map_item_ref_t)func(iterator, itor); // get the item of the hash set return item? item->name : tb_null; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_hash_set_ref_t tb_hash_set_init(tb_size_t bucket_size, tb_element_t element) { // init hash set tb_iterator_ref_t hash_set = (tb_iterator_ref_t)tb_hash_map_init(bucket_size, element, tb_element_true()); tb_assert_and_check_return_val(hash_set, tb_null); // @note the private data of the hash map iterator cannot be used tb_assert(!hash_set->priv); // init operation static tb_iterator_op_t op = {0}; if (op.item != tb_hash_set_itor_item) { op = *hash_set->op; op.item = tb_hash_set_itor_item; } // hacking hash_map and hook the item hash_set->priv = (tb_pointer_t)hash_set->op->item; hash_set->op = &op; // ok? return (tb_hash_set_ref_t)hash_set; } tb_void_t tb_hash_set_exit(tb_hash_set_ref_t self) { tb_hash_map_exit((tb_hash_map_ref_t)self); } tb_void_t tb_hash_set_clear(tb_hash_set_ref_t self) { tb_hash_map_clear((tb_hash_map_ref_t)self); } tb_bool_t tb_hash_set_get(tb_hash_set_ref_t self, tb_cpointer_t data) { return tb_p2b(tb_hash_map_get((tb_hash_map_ref_t)self, data)); } tb_size_t tb_hash_set_find(tb_hash_set_ref_t self, tb_cpointer_t data) { return tb_hash_map_find((tb_hash_map_ref_t)self, data); } tb_size_t tb_hash_set_insert(tb_hash_set_ref_t self, tb_cpointer_t data) { return tb_hash_map_insert((tb_hash_map_ref_t)self, data, tb_b2p(tb_true)); } tb_void_t tb_hash_set_remove(tb_hash_set_ref_t self, tb_cpointer_t data) { tb_hash_map_remove((tb_hash_map_ref_t)self, data); } tb_size_t tb_hash_set_size(tb_hash_set_ref_t self) { return tb_hash_map_size((tb_hash_map_ref_t)self); } tb_size_t tb_hash_set_maxn(tb_hash_set_ref_t self) { return tb_hash_map_maxn((tb_hash_map_ref_t)self); } #ifdef __tb_debug__ tb_void_t tb_hash_set_dump(tb_hash_set_ref_t self) { tb_hash_map_dump((tb_hash_map_ref_t)self); } #endif tbox-1.6.7/src/tbox/container/hash_set.h 0000664 0000000 0000000 00000010350 14142237372 0020201 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file hash_set.h * @ingroup container * */ #ifndef TB_CONTAINER_HASH_SET_H #define TB_CONTAINER_HASH_SET_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "hash_map.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the micro hash bucket size #define TB_HASH_SET_BUCKET_SIZE_MICRO TB_HASH_MAP_BUCKET_SIZE_MICRO /// the small hash bucket size #define TB_HASH_SET_BUCKET_SIZE_SMALL TB_HASH_MAP_BUCKET_SIZE_SMALL /// the large hash bucket size #define TB_HASH_SET_BUCKET_SIZE_LARGE TB_HASH_MAP_BUCKET_SIZE_LARGE /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the hash set ref type * * @note the itor of the same item is mutable */ typedef tb_iterator_ref_t tb_hash_set_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init hash set * * @param bucket_size the hash bucket size, using the default size if be zero * @param element the element * * @return the hash set */ tb_hash_set_ref_t tb_hash_set_init(tb_size_t bucket_size, tb_element_t element); /*! exit hash set * * @param hash_set the hash set */ tb_void_t tb_hash_set_exit(tb_hash_set_ref_t hash_set); /*! clear hash set * * @param hash_set the hash set */ tb_void_t tb_hash_set_clear(tb_hash_set_ref_t hash_set); /*! get item? * * @code * if (tb_hash_set_get(hash_set, name)) * { * } * @endcode * * @param hash_set the hash set * @param data the item data * * @return tb_true or tb_false */ tb_bool_t tb_hash_set_get(tb_hash_set_ref_t hash_set, tb_cpointer_t data); /*! find item * * @code * * // find item * tb_size_t itor = tb_hash_set_find(hash_set, data); * if (itor != tb_iterator_tail(hash_set)) * { * // remove it * tb_iterator_remove(hash_set, itor); * } * @endcode * * @param hash_set the hash set * @param data the item data * * @return the item itor, @note: the itor of the same item is mutable */ tb_size_t tb_hash_set_find(tb_hash_set_ref_t hash_set, tb_cpointer_t data); /*! insert item * * @note each item is unique * * @param hash_set the hash set * @param data the item data * * @return the item itor, @note: the itor of the same item is mutable */ tb_size_t tb_hash_set_insert(tb_hash_set_ref_t hash_set, tb_cpointer_t data); /*! remove item * * @param hash_set the hash set * @param data the item data */ tb_void_t tb_hash_set_remove(tb_hash_set_ref_t hash_set, tb_cpointer_t data); /*! the hash set size * * @param hash_set the hash set * * @return the hash set size */ tb_size_t tb_hash_set_size(tb_hash_set_ref_t hash_set); /*! the hash set maxn * * @param hash_set the hash set * * @return the hash set maxn */ tb_size_t tb_hash_set_maxn(tb_hash_set_ref_t hash_set); #ifdef __tb_debug__ /*! dump hash * * @param hash_set the hash set */ tb_void_t tb_hash_set_dump(tb_hash_set_ref_t hash_set); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/heap.c 0000664 0000000 0000000 00000050421 14142237372 0017316 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file heap.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "heap" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "heap.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../memory/memory.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the self grow #ifdef __tb_small__ # define TB_HEAP_GROW (128) #else # define TB_HEAP_GROW (256) #endif // the self maxn #ifdef __tb_small__ # define TB_HEAP_MAXN (1 << 16) #else # define TB_HEAP_MAXN (1 << 30) #endif // enable check #ifdef __tb_debug__ # define TB_HEAP_CHECK_ENABLE (0) #else # define TB_HEAP_CHECK_ENABLE (0) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the self type typedef struct __tb_heap_t { // the itor tb_iterator_t itor; // the data tb_byte_t* data; // the size tb_size_t size; // the maxn tb_size_t maxn; // the grow tb_size_t grow; // the element tb_element_t element; }tb_heap_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ #if TB_HEAP_CHECK_ENABLE static tb_void_t tb_heap_check(tb_heap_t* heap) { // init tb_byte_t* data = heap->data; tb_size_t tail = heap->size; tb_size_t step = heap->element.size; tb_size_t parent = 0; // done for (; parent < tail; parent++) { // the left child node tb_size_t lchild = (parent << 1) + 1; tb_check_break(lchild < tail); // the parent data tb_pointer_t parent_data = heap->element.data(&heap->element, data + parent * step); // check? if (heap->element.comp(&heap->element, heap->element.data(&heap->element, data + lchild * step), parent_data) < 0) { // dump self tb_heap_dump((tb_heap_ref_t)heap); // abort tb_assertf(0, "lchild[%lu]: invalid, parent: %lu, tail: %lu", lchild, parent, tail); } // the right child node tb_size_t rchild = lchild + 1; tb_check_break(rchild < tail); // check? if (heap->element.comp(&heap->element, heap->element.data(&heap->element, data + rchild * step), parent_data) < 0) { // dump self tb_heap_dump((tb_heap_ref_t)heap); // abort tb_assertf(0, "rchild[%lu]: invalid, parent: %lu, tail: %lu", rchild, parent, tail); } } } #endif /*! shift up the self * *
* * before: * * 1(head) * ------------------------- * | | * 4 2 * -------------- ------------- * | | | | * 6(parent) 9 7 8 * --------- * | | * 10 5(hole) <------ data * after: * * 1(head) * ------------------------- * | | * 4 2 * -------------- ------------- * | | | | * data -------> 5(hole) 9 7 8 * --------- * | | * 10 6 **/ static tb_pointer_t tb_heap_shift_up(tb_heap_t* heap, tb_size_t hole, tb_cpointer_t data) { // check tb_assert_and_check_return_val(heap && heap->data, tb_null); // the element function tb_element_comp_func_t func_comp = heap->element.comp; tb_element_data_func_t func_data = heap->element.data; tb_assert(func_comp && func_data); // (hole - 1) / 2: the parent node of the hole tb_size_t parent = 0; tb_byte_t* head = heap->data; tb_size_t step = heap->element.size; switch (step) { case sizeof(tb_size_t): { for (parent = (hole - 1) >> 1; hole && (func_comp(&heap->element, func_data(&heap->element, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole *((tb_size_t*)(head + hole * step)) = *((tb_size_t*)(head + parent * step)); // move node: hole => parent hole = parent; } } break; default: for (parent = (hole - 1) >> 1; hole && (func_comp(&heap->element, func_data(&heap->element, head + parent * step), data) > 0); parent = (hole - 1) >> 1) { // move item: parent => hole tb_memcpy(head + hole * step, head + parent * step, step); // move node: hole => parent hole = parent; } break; } // ok? return head + hole * step; } /*! shift down the self * *
* * before: * 1(head) * ------------------------- * | | * (hole) 2 * -------------- ------------- * | | | | * lchild --> 6(smaller) 7 7 8 * --------- ------ * | | | * 11 16 10 * * * move hole: * 1(head) * ------------------------- * | | * 6 2 * -------------- ------------- * | | | | * (hole) 7 7 8 * --------- ----- * | | | * lchild --> 11(smaller)16 10 * * 11 >= data: 9? break it * * move data to hole: * 1(head) * ------------------------- * | | * 6 2 * -------------- ------------- * | | | | * data ------------> 9 7 7 8 * --------- --- * | | | * 11 16 10 * **/ static tb_pointer_t tb_heap_shift_down(tb_heap_t* heap, tb_size_t hole, tb_cpointer_t data) { // check tb_assert_and_check_return_val(heap && heap->data, tb_null); // init element tb_element_comp_func_t func_comp = heap->element.comp; tb_element_data_func_t func_data = heap->element.data; tb_assert(func_comp && func_data); // 2 * hole + 1: the left child node of hole tb_size_t step = heap->element.size; tb_byte_t* head = heap->data; tb_byte_t* tail = head + heap->size * step; tb_byte_t* phole = head + hole * step; tb_byte_t* lchild = head + ((hole << 1) + 1) * step; tb_pointer_t data_lchild = tb_null; tb_pointer_t data_rchild = tb_null; switch (step) { case sizeof(tb_size_t): { for (; lchild < tail; lchild = head + (((lchild - head) << 1) + step)) { // the smaller child node data_lchild = func_data(&heap->element, lchild); if (lchild + step < tail && func_comp(&heap->element, data_lchild, (data_rchild = func_data(&heap->element, lchild + step))) > 0) { lchild += step; data_lchild = data_rchild; } // end? if (func_comp(&heap->element, data_lchild, data) >= 0) break; // the smaller child node => hole *((tb_size_t*)phole) = *((tb_size_t*)lchild); // move the hole down to it's smaller child node phole = lchild; } } break; default: { for (; lchild < tail; lchild = head + (((lchild - head) << 1) + step)) { // the smaller child node data_lchild = func_data(&heap->element, lchild); if (lchild + step < tail && func_comp(&heap->element, data_lchild, (data_rchild = func_data(&heap->element, lchild + step))) > 0) { lchild += step; data_lchild = data_rchild; } // end? if (func_comp(&heap->element, data_lchild, data) >= 0) break; // the smaller child node => hole tb_memcpy(phole, lchild, step); // move the hole down to it's smaller child node phole = lchild; } } break; } // ok? return phole; } static tb_size_t tb_heap_itor_size(tb_iterator_ref_t iterator) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap, 0); // size return heap->size; } static tb_size_t tb_heap_itor_head(tb_iterator_ref_t iterator) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap, 0); // head return 0; } static tb_size_t tb_heap_itor_last(tb_iterator_ref_t iterator) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap, 0); // last return heap->size? heap->size - 1 : 0; } static tb_size_t tb_heap_itor_tail(tb_iterator_ref_t iterator) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap, 0); // tail return heap->size; } static tb_size_t tb_heap_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap, 0); tb_assert_and_check_return_val(itor < heap->size, heap->size); // next return itor + 1; } static tb_size_t tb_heap_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap, 0); tb_assert_and_check_return_val(itor && itor < heap->size, 0); // prev return itor - 1; } static tb_pointer_t tb_heap_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap && itor < heap->size, tb_null); // data return heap->element.data(&heap->element, heap->data + itor * iterator->step); } static tb_void_t tb_heap_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return(heap); // copy heap->element.copy(&heap->element, heap->data + itor * iterator->step, item); } static tb_long_t tb_heap_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return_val(heap && heap->element.comp, 0); // comp return heap->element.comp(&heap->element, litem, ritem); } static tb_void_t tb_heap_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_heap_t* heap = (tb_heap_t*)iterator; tb_assert_and_check_return(heap && heap->data && heap->size && itor < heap->size); // check the element function tb_assert(heap->element.comp && heap->element.data); // the step tb_size_t step = heap->element.size; tb_assert(step); // free the item first if (heap->element.free) heap->element.free(&heap->element, heap->data + itor * step); // the removed item is not the last item? if (itor != heap->size - 1) { // the last and parent tb_pointer_t last = heap->data + (heap->size - 1) * step; tb_pointer_t parent = heap->data + ((itor - 1) >> 1) * step; // the last and parent data tb_pointer_t data_last = heap->element.data(&heap->element, last); tb_pointer_t data_parent = heap->element.data(&heap->element, parent); /* we might need to shift it upward if it is less than its parent, * or downward if it is greater than one or both its children. * * since the children are known to be less than the parent, * it can't need to shift both up and down. */ tb_pointer_t hole = tb_null; if (itor && heap->element.comp(&heap->element, data_parent, data_last) > 0) { // shift up the self from the given hole hole = tb_heap_shift_up(heap, itor, data_last); } // shift down the self from the given hole else hole = tb_heap_shift_down(heap, itor, data_last); tb_assert(hole); // copy the last data to the hole if (hole != last) tb_memcpy(hole, last, step); } // size-- heap->size--; // check #if TB_HEAP_CHECK_ENABLE tb_heap_check(heap); #endif } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_heap_ref_t tb_heap_init(tb_size_t grow, tb_element_t element) { // check tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl, tb_null); // done tb_bool_t ok = tb_false; tb_heap_t* heap = tb_null; do { // using the default grow if (!grow) grow = TB_HEAP_GROW; // make heap heap = tb_malloc0_type(tb_heap_t); tb_assert_and_check_break(heap); // init heap heap->size = 0; heap->grow = grow; heap->maxn = grow; heap->element = element; tb_assert_and_check_break(heap->maxn < TB_HEAP_MAXN); // init operation static tb_iterator_op_t op = { tb_heap_itor_size , tb_heap_itor_head , tb_heap_itor_last , tb_heap_itor_tail , tb_heap_itor_prev , tb_heap_itor_next , tb_heap_itor_item , tb_heap_itor_comp , tb_heap_itor_copy , tb_heap_itor_remove , tb_null }; // init iterator heap->itor.priv = tb_null; heap->itor.step = element.size; heap->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; heap->itor.op = &op; // make data heap->data = (tb_byte_t*)tb_nalloc0(heap->maxn, element.size); tb_assert_and_check_break(heap->data); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (heap) tb_heap_exit((tb_heap_ref_t)heap); heap = tb_null; } // ok? return (tb_heap_ref_t)heap; } tb_void_t tb_heap_exit(tb_heap_ref_t self) { // check tb_heap_t* heap = (tb_heap_t*)self; tb_assert_and_check_return(heap); // clear data tb_heap_clear(self); // free data if (heap->data) tb_free(heap->data); heap->data = tb_null; // free it tb_free(heap); } tb_void_t tb_heap_clear(tb_heap_ref_t self) { // check tb_heap_t* heap = (tb_heap_t*)self; tb_assert_and_check_return(heap); // free data if (heap->element.nfree) heap->element.nfree(&heap->element, heap->data, heap->size); // reset size heap->size = 0; } tb_size_t tb_heap_size(tb_heap_ref_t self) { // check tb_heap_t const* heap = (tb_heap_t const*)self; tb_assert_and_check_return_val(heap, 0); // size return heap->size; } tb_size_t tb_heap_maxn(tb_heap_ref_t self) { // check tb_heap_t const* heap = (tb_heap_t const*)self; tb_assert_and_check_return_val(heap, 0); // maxn return heap->maxn; } tb_pointer_t tb_heap_top(tb_heap_ref_t self) { return tb_iterator_item(self, tb_iterator_head(self)); } tb_void_t tb_heap_put(tb_heap_ref_t self, tb_cpointer_t data) { // check tb_heap_t* heap = (tb_heap_t*)self; tb_assert_and_check_return(heap && heap->element.dupl && heap->data); // no enough? grow it if (heap->size == heap->maxn) { // the maxn tb_size_t maxn = tb_align4(heap->maxn + heap->grow); tb_assert_and_check_return(maxn < TB_HEAP_MAXN); // realloc data heap->data = (tb_byte_t*)tb_ralloc(heap->data, maxn * heap->element.size); tb_assert_and_check_return(heap->data); // must be align by 4-bytes tb_assert_and_check_return(!(((tb_size_t)(heap->data)) & 3)); // clear the grow data tb_memset(heap->data + heap->size * heap->element.size, 0, (maxn - heap->maxn) * heap->element.size); // save maxn heap->maxn = maxn; } // check tb_assert_and_check_return(heap->size < heap->maxn); // shift up the self from the tail hole tb_pointer_t hole = tb_heap_shift_up(heap, heap->size, data); tb_assert(hole); // save data to the hole if (hole) heap->element.dupl(&heap->element, hole, data); // update the size heap->size++; // check #if TB_HEAP_CHECK_ENABLE tb_heap_check(heap); #endif } tb_void_t tb_heap_pop(tb_heap_ref_t self) { // check tb_heap_t* heap = (tb_heap_t*)self; tb_assert_and_check_return(heap && heap->data && heap->size); // free the top item first if (heap->element.free) heap->element.free(&heap->element, heap->data); // the last item is not in top if (heap->size > 1) { // check the element function tb_assert(heap->element.data); // the step tb_size_t step = heap->element.size; tb_assert(step); // the last tb_pointer_t last = heap->data + (heap->size - 1) * step; // shift down the self from the top hole tb_pointer_t hole = tb_heap_shift_down(heap, 0, heap->element.data(&heap->element, last)); tb_assert(hole); // copy the last data to the hole if (hole != last) tb_memcpy(hole, last, step); } // update the size heap->size--; // check #if TB_HEAP_CHECK_ENABLE tb_heap_check(heap); #endif } tb_void_t tb_heap_remove(tb_heap_ref_t self, tb_size_t itor) { tb_heap_itor_remove(self, itor); } #ifdef __tb_debug__ tb_void_t tb_heap_dump(tb_heap_ref_t self) { // check tb_heap_t* heap = (tb_heap_t*)self; tb_assert_and_check_return(heap); // trace tb_trace_i("self: size: %lu", tb_heap_size(self)); // done tb_char_t cstr[4096]; tb_for_all (tb_pointer_t, data, self) { // trace if (heap->element.cstr) { #if TB_HEAP_CHECK_ENABLE tb_trace_i(" [%lu]: %s", data_itor, heap->element.cstr(&heap->element, data, cstr, sizeof(cstr))); #else tb_trace_i(" %s", heap->element.cstr(&heap->element, data, cstr, sizeof(cstr))); #endif } else { tb_trace_i(" %p", data); } } } #endif tbox-1.6.7/src/tbox/container/heap.h 0000664 0000000 0000000 00000007453 14142237372 0017332 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file heap.h * @ingroup container * */ #ifndef TB_CONTAINER_HEAP_H #define TB_CONTAINER_HEAP_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the head ref type * *
* heap: 1 4 2 6 9 7 8 10 14 16 * * 1(head) * ------------------------- * | | * 4 2 * -------------- ------------- * | | | | * 6 (last / 2 - 1)9 7 8 * --------- ---- * | | | * 10 14 16(last - 1) * * performance: * * put: O(lgn) * pop: O(1) * top: O(1) * del: O(lgn) + find: O(n) * * iterator: * * next: fast * prev: fast * ** * @note the itor of the same item is mutable */ typedef tb_iterator_ref_t tb_heap_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init heap, default: minheap * * @param grow the item grow, using the default grow if be zero * @param element the element * * @return the heap */ tb_heap_ref_t tb_heap_init(tb_size_t grow, tb_element_t element); /*! exit heap * * @param heap the heap */ tb_void_t tb_heap_exit(tb_heap_ref_t heap); /*! clear the heap * * @param heap the heap */ tb_void_t tb_heap_clear(tb_heap_ref_t heap); /*! the heap size * * @param heap the heap * * @return the heap size */ tb_size_t tb_heap_size(tb_heap_ref_t heap); /*! the heap maxn * * @param heap the heap * * @return the heap maxn */ tb_size_t tb_heap_maxn(tb_heap_ref_t heap); /*! the heap top item * * @param heap the heap * * @return the heap top item */ tb_pointer_t tb_heap_top(tb_heap_ref_t heap); /*! put the heap item * * @param heap the heap * @param data the item data */ tb_void_t tb_heap_put(tb_heap_ref_t heap, tb_cpointer_t data); /*! pop the heap item * * @param heap the heap */ tb_void_t tb_heap_pop(tb_heap_ref_t heap); /*! remove the heap item using iterator only for algorithm(find, ...) * * @param heap the heap * @param itor the itor */ tb_void_t tb_heap_remove(tb_heap_ref_t heap, tb_size_t itor); #ifdef __tb_debug__ /*! dump heap * * @param heap the heap */ tb_void_t tb_heap_dump(tb_heap_ref_t heap); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/iterator.c 0000664 0000000 0000000 00000007061 14142237372 0020234 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX op->n Source Group. * * @author ruki * @file iterator.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "iterator.h" #include "../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_iterator_mode(tb_iterator_ref_t iterator) { // check tb_assert(iterator); // mode return iterator->mode; } tb_size_t tb_iterator_step(tb_iterator_ref_t iterator) { // check tb_assert(iterator); // step return iterator->step; } tb_size_t tb_iterator_size(tb_iterator_ref_t iterator) { // check tb_assert(iterator && iterator->op && iterator->op->size); // size return iterator->op->size(iterator); } tb_size_t tb_iterator_head(tb_iterator_ref_t iterator) { // check tb_assert(iterator && iterator->op && iterator->op->head); // head return iterator->op->head(iterator); } tb_size_t tb_iterator_last(tb_iterator_ref_t iterator) { // check tb_assert(iterator && iterator->op && iterator->op->last); // last return iterator->op->last(iterator); } tb_size_t tb_iterator_tail(tb_iterator_ref_t iterator) { // check tb_assert(iterator && iterator->op && iterator->op->tail); // tail return iterator->op->tail(iterator); } tb_size_t tb_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && iterator->op && iterator->op->prev); // prev return iterator->op->prev(iterator, itor); } tb_size_t tb_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && iterator->op && iterator->op->next); // next return iterator->op->next(iterator, itor); } tb_pointer_t tb_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && iterator->op && iterator->op->item); // item return iterator->op->item(iterator, itor); } tb_void_t tb_iterator_remove(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(iterator && iterator->op && iterator->op->remove); // remove return iterator->op->remove(iterator, itor); } tb_void_t tb_iterator_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size) { // check tb_assert(iterator && iterator->op && iterator->op->nremove); // nremove return iterator->op->nremove(iterator, prev, next, size); } tb_void_t tb_iterator_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_assert(iterator && iterator->op && iterator->op->copy); // copy return iterator->op->copy(iterator, itor, item); } tb_long_t tb_iterator_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert(iterator && iterator->op && iterator->op->comp); // comp return iterator->op->comp(iterator, litem, ritem); } tbox-1.6.7/src/tbox/container/iterator.h 0000664 0000000 0000000 00000014701 14142237372 0020240 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file iterator.h * @ingroup container * */ #ifndef TB_CONTAINER_ITERATOR_H #define TB_CONTAINER_ITERATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the iterator mode type typedef enum __tb_iterator_mode_t { TB_ITERATOR_MODE_FORWARD = 1 //!< forward iterator , TB_ITERATOR_MODE_REVERSE = 2 //!< reverse iterator , TB_ITERATOR_MODE_RACCESS = 4 //!< random access iterator , TB_ITERATOR_MODE_MUTABLE = 8 //!< mutable iterator, the item of the same iterator is mutable for removing and moving, .e.g vector, hash, ... , TB_ITERATOR_MODE_READONLY = 16 //!< readonly iterator }tb_iterator_mode_t; /// the iterator operation type struct __tb_iterator_t; typedef struct __tb_iterator_op_t { /// the iterator size tb_size_t (*size)(struct __tb_iterator_t* iterator); /// the iterator head tb_size_t (*head)(struct __tb_iterator_t* iterator); /// the iterator last tb_size_t (*last)(struct __tb_iterator_t* iterator); /// the iterator tail tb_size_t (*tail)(struct __tb_iterator_t* iterator); /// the iterator prev tb_size_t (*prev)(struct __tb_iterator_t* iterator, tb_size_t itor); /// the iterator next tb_size_t (*next)(struct __tb_iterator_t* iterator, tb_size_t itor); /// the iterator item tb_pointer_t (*item)(struct __tb_iterator_t* iterator, tb_size_t itor); /// the iterator comp tb_long_t (*comp)(struct __tb_iterator_t* iterator, tb_cpointer_t litem, tb_cpointer_t ritem); /// the iterator copy tb_void_t (*copy)(struct __tb_iterator_t* iterator, tb_size_t itor, tb_cpointer_t item); /// the iterator remove tb_void_t (*remove)(struct __tb_iterator_t* iterator, tb_size_t itor); /// the iterator nremove tb_void_t (*nremove)(struct __tb_iterator_t* iterator, tb_size_t prev, tb_size_t next, tb_size_t size); }tb_iterator_op_t; /// the iterator operation ref type typedef tb_iterator_op_t const* tb_iterator_op_ref_t; /// the iterator type typedef struct __tb_iterator_t { /// the iterator mode tb_size_t mode; /// the iterator step tb_size_t step; /// the iterator priv tb_pointer_t priv; /// the iterator operation tb_iterator_op_ref_t op; }tb_iterator_t, *tb_iterator_ref_t; /// the iterator comp func type typedef tb_long_t (*tb_iterator_comp_t)(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the iterator mode * * @param iterator the iterator * * @return the iterator mode */ tb_size_t tb_iterator_mode(tb_iterator_ref_t iterator); /*! the iterator step * * @param iterator the iterator * * @return the iterator step */ tb_size_t tb_iterator_step(tb_iterator_ref_t iterator); /*! the iterator size * * @param iterator the iterator * * @return the iterator size */ tb_size_t tb_iterator_size(tb_iterator_ref_t iterator); /*! the iterator head * * @param iterator the iterator * * @return the iterator head */ tb_size_t tb_iterator_head(tb_iterator_ref_t iterator); /*! the iterator last * * @param iterator the iterator * * @return the iterator last */ tb_size_t tb_iterator_last(tb_iterator_ref_t iterator); /*! the iterator tail * * @param iterator the iterator * * @return the iterator tail */ tb_size_t tb_iterator_tail(tb_iterator_ref_t iterator); /*! the iterator prev * * @param iterator the iterator * @param itor the item itor * * @return the iterator prev */ tb_size_t tb_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor); /*! the iterator next * * @param iterator the iterator * @param itor the item itor * * @return the iterator next */ tb_size_t tb_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor); /*! the iterator item * * @param iterator the iterator * @param itor the item itor * * @return the iterator item */ tb_pointer_t tb_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor); /*! remove the iterator item * * @param iterator the iterator * @param itor the item itor */ tb_void_t tb_iterator_remove(tb_iterator_ref_t iterator, tb_size_t itor); /*! remove the iterator items from range(prev, next) * * @param iterator the iterator * @param prev the prev item * @param next the next item * @param size the removed size */ tb_void_t tb_iterator_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size); /*! copy the iterator item * * @param iterator the iterator * @param itor the item itor * @param item the copied item */ tb_void_t tb_iterator_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item); /*! compare the iterator item * * @param iterator the iterator * @param litem the item * @param ritem the compared item * * @return =: 0, >: 1, <: -1 */ tb_long_t tb_iterator_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/list.c 0000664 0000000 0000000 00000030552 14142237372 0017357 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file list.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "list" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "list.h" #include "list_entry.h" #include "../libc/libc.h" #include "../math/math.h" #include "../memory/memory.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the self grow #ifdef __tb_small__ # define TB_LIST_GROW (128) #else # define TB_LIST_GROW (256) #endif // the self maxn #ifdef __tb_small__ # define TB_LIST_MAXN (1 << 16) #else # define TB_LIST_MAXN (1 << 30) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the self type typedef struct __tb_list_t { // the itor tb_iterator_t itor; // the pool tb_fixed_pool_ref_t pool; // the head tb_list_entry_head_t head; // the element tb_element_t element; }tb_list_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_size_t tb_list_itor_size(tb_iterator_ref_t iterator) { // the size return tb_list_size((tb_list_ref_t)iterator); } static tb_size_t tb_list_itor_head(tb_iterator_ref_t iterator) { // check tb_list_t* list = (tb_list_t*)iterator; tb_assert(list); // head return (tb_size_t)tb_list_entry_head(&list->head); } static tb_size_t tb_list_itor_last(tb_iterator_ref_t iterator) { // check tb_list_t* list = (tb_list_t*)iterator; tb_assert(list); // last return (tb_size_t)tb_list_entry_last(&list->head); } static tb_size_t tb_list_itor_tail(tb_iterator_ref_t iterator) { // check tb_list_t* list = (tb_list_t*)iterator; tb_assert(list); // tail return (tb_size_t)tb_list_entry_tail(&list->head); } static tb_size_t tb_list_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(itor); // next return (tb_size_t)tb_list_entry_next((tb_list_entry_t*)itor); } static tb_size_t tb_list_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(itor); // prev return (tb_size_t)tb_list_entry_prev((tb_list_entry_t*)itor); } static tb_pointer_t tb_list_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_list_t* list = (tb_list_t*)iterator; tb_assert(list && itor); // data return list->element.data(&list->element, (tb_cpointer_t)(((tb_list_entry_t*)itor) + 1)); } static tb_void_t tb_list_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_list_t* list = (tb_list_t*)iterator; tb_assert(list && itor); // copy list->element.copy(&list->element, (tb_pointer_t)(((tb_list_entry_t*)itor) + 1), item); } static tb_long_t tb_list_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_list_t* list = (tb_list_t*)iterator; tb_assert(list && list->element.comp); // comp return list->element.comp(&list->element, litem, ritem); } static tb_void_t tb_list_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor) { // remove it tb_list_remove((tb_list_ref_t)iterator, itor); } static tb_void_t tb_list_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size) { // no size? tb_check_return(size); // the self size tb_size_t list_size = tb_list_size((tb_list_ref_t)iterator); tb_check_return(list_size); // limit size if (size > list_size) size = list_size; // remove the body items if (prev) { tb_size_t itor = tb_iterator_next((tb_list_ref_t)iterator, prev); while (itor != next && size--) itor = tb_list_remove((tb_list_ref_t)iterator, itor); } // remove the head items else { while (size--) tb_list_remove_head((tb_list_ref_t)iterator); } } static tb_void_t tb_list_item_exit(tb_pointer_t data, tb_cpointer_t priv) { // check tb_list_t* list = (tb_list_t*)priv; tb_assert_and_check_return(list); // free data if (list->element.free) list->element.free(&list->element, (tb_pointer_t)(((tb_list_entry_t*)data) + 1)); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_list_ref_t tb_list_init(tb_size_t grow, tb_element_t element) { // check tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl, tb_null); // done tb_bool_t ok = tb_false; tb_list_t* list = tb_null; do { // using the default grow if (!grow) grow = TB_LIST_GROW; // make self list = tb_malloc0_type(tb_list_t); tb_assert_and_check_break(list); // init element list->element = element; // init operation static tb_iterator_op_t op = { tb_list_itor_size , tb_list_itor_head , tb_list_itor_last , tb_list_itor_tail , tb_list_itor_prev , tb_list_itor_next , tb_list_itor_item , tb_list_itor_comp , tb_list_itor_copy , tb_list_itor_remove , tb_list_itor_nremove }; // init iterator list->itor.priv = tb_null; list->itor.step = element.size; list->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE; list->itor.op = &op; // init pool, item = entry + data list->pool = tb_fixed_pool_init(tb_null, grow, sizeof(tb_list_entry_t) + element.size, tb_null, tb_list_item_exit, (tb_cpointer_t)list); tb_assert_and_check_break(list->pool); // init head tb_list_entry_init_(&list->head, 0, sizeof(tb_list_entry_t) + element.size, tb_null); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (list) tb_list_exit((tb_list_ref_t)list); list = tb_null; } // ok? return (tb_list_ref_t)list; } tb_void_t tb_list_exit(tb_list_ref_t self) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return(list); // clear data tb_list_clear((tb_list_ref_t)list); // exit pool if (list->pool) tb_fixed_pool_exit(list->pool); // exit it tb_free(list); } tb_void_t tb_list_clear(tb_list_ref_t self) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return(list); // clear pool if (list->pool) tb_fixed_pool_clear(list->pool); // clear head tb_list_entry_clear(&list->head); } tb_pointer_t tb_list_head(tb_list_ref_t self) { return tb_iterator_item(self, tb_iterator_head(self)); } tb_pointer_t tb_list_last(tb_list_ref_t self) { return tb_iterator_item(self, tb_iterator_last(self)); } tb_size_t tb_list_size(tb_list_ref_t self) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return_val(list && list->pool, 0); tb_assert(tb_list_entry_size(&list->head) == tb_fixed_pool_size(list->pool)); // the size return tb_list_entry_size(&list->head); } tb_size_t tb_list_maxn(tb_list_ref_t self) { // the item maxn return TB_LIST_MAXN; } tb_size_t tb_list_insert_prev(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0); // full? tb_assert_and_check_return_val(tb_list_size(self) < tb_list_maxn(self), tb_iterator_tail(self)); // the node tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor; tb_assert_and_check_return_val(node, tb_iterator_tail(self)); // make entry tb_list_entry_ref_t entry = (tb_list_entry_ref_t)tb_fixed_pool_malloc(list->pool); tb_assert_and_check_return_val(entry, tb_iterator_tail(self)); // init entry data list->element.dupl(&list->element, (tb_pointer_t)(((tb_list_entry_t*)entry) + 1), data); // insert it tb_list_entry_insert_prev(&list->head, node, entry); // ok return (tb_size_t)entry; } tb_size_t tb_list_insert_next(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data) { return tb_list_insert_prev(self, tb_iterator_next(self, itor), data); } tb_size_t tb_list_insert_head(tb_list_ref_t self, tb_cpointer_t data) { return tb_list_insert_prev(self, tb_iterator_head(self), data); } tb_size_t tb_list_insert_tail(tb_list_ref_t self, tb_cpointer_t data) { return tb_list_insert_prev(self, tb_iterator_tail(self), data); } tb_void_t tb_list_replace(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return(list && list->element.repl && itor); // the node tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor; tb_assert_and_check_return(node); // replace data list->element.repl(&list->element, (tb_pointer_t)(((tb_list_entry_t*)node) + 1), data); } tb_void_t tb_list_replace_head(tb_list_ref_t self, tb_cpointer_t data) { tb_list_replace(self, tb_iterator_head(self), data); } tb_void_t tb_list_replace_last(tb_list_ref_t self, tb_cpointer_t data) { tb_list_replace(self, tb_iterator_last(self), data); } tb_size_t tb_list_remove(tb_list_ref_t self, tb_size_t itor) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return_val(list && list->pool && itor, 0); // the node tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor; tb_assert_and_check_return_val(node, tb_iterator_tail(self)); // the next node tb_list_entry_ref_t next = tb_list_entry_next(node); // remove node tb_list_entry_remove(&list->head, node); // free node tb_fixed_pool_free(list->pool, node); // the next node return (tb_size_t)next; } tb_void_t tb_list_remove_head(tb_list_ref_t self) { tb_list_remove(self, tb_iterator_head(self)); } tb_void_t tb_list_remove_last(tb_list_ref_t self) { tb_list_remove(self, tb_iterator_last(self)); } tb_void_t tb_list_moveto_prev(tb_list_ref_t self, tb_size_t itor, tb_size_t move) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return(list && list->pool && move); // the node tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor; tb_assert_and_check_return(node); // the entry tb_list_entry_ref_t entry = (tb_list_entry_ref_t)move; tb_assert_and_check_return(entry); // move to the prev node tb_list_entry_moveto_prev(&list->head, node, entry); } tb_void_t tb_list_moveto_next(tb_list_ref_t self, tb_size_t itor, tb_size_t move) { tb_list_moveto_prev(self, tb_iterator_next(self, itor), move); } tb_void_t tb_list_moveto_head(tb_list_ref_t self, tb_size_t move) { tb_list_moveto_prev(self, tb_iterator_head(self), move); } tb_void_t tb_list_moveto_tail(tb_list_ref_t self, tb_size_t move) { tb_list_moveto_prev(self, tb_iterator_tail(self), move); } #ifdef __tb_debug__ tb_void_t tb_list_dump(tb_list_ref_t self) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return(list); // trace tb_trace_i("self: size: %lu", tb_list_size(self)); // done tb_char_t cstr[4096]; tb_for_all (tb_pointer_t, data, self) { // trace if (list->element.cstr) { tb_trace_i(" %s", list->element.cstr(&list->element, data, cstr, sizeof(cstr))); } else { tb_trace_i(" %p", data); } } } #endif tbox-1.6.7/src/tbox/container/list.h 0000664 0000000 0000000 00000014000 14142237372 0017352 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file list.h * @ingroup container * */ #ifndef TB_CONTAINER_LIST_H #define TB_CONTAINER_LIST_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the doubly-linked list ref type * * *
* list: tail => |-----| => |-------------------------------------------------=> |------| => |------| => tail * | head last | * | | * <----------------------------------------------------------------------------------------------- * * performance: * * insert: * insert midd: fast * insert head: fast * insert tail: fast * insert next: fast * * remove: * remove midd: fast * remove head: fast * remove last: fast * remove next: fast * * iterator: * next: fast * prev: fast ** */ typedef tb_iterator_ref_t tb_list_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init list * * @param grow the grow size * @param element the element * * @return the list */ tb_list_ref_t tb_list_init(tb_size_t grow, tb_element_t element); /*! exit list * * @param list the list */ tb_void_t tb_list_exit(tb_list_ref_t list); /*! clear list * * @param list the list */ tb_void_t tb_list_clear(tb_list_ref_t list); /*! the list head item * * @param list the list * * @return the head item */ tb_pointer_t tb_list_head(tb_list_ref_t list); /*! the list last item * * @param list the list * * @return the last item */ tb_pointer_t tb_list_last(tb_list_ref_t list); /*! insert the prev item * * @param list the list * @param itor the item itor * @param data the item data * * @return the item itor */ tb_size_t tb_list_insert_prev(tb_list_ref_t list, tb_size_t itor, tb_cpointer_t data); /*! insert the next item * * @param list the list * @param itor the item itor * @param data the item data * * @return the item itor */ tb_size_t tb_list_insert_next(tb_list_ref_t list, tb_size_t itor, tb_cpointer_t data); /*! insert the head item * * @param list the list * @param data the item data * * @return the item itor */ tb_size_t tb_list_insert_head(tb_list_ref_t list, tb_cpointer_t data); /*! insert the tail item * * @param list the list * @param data the item data * * @return the item itor */ tb_size_t tb_list_insert_tail(tb_list_ref_t list, tb_cpointer_t data); /*! replace the item * * @param list the list * @param itor the item itor * @param data the item data */ tb_void_t tb_list_replace(tb_list_ref_t list, tb_size_t itor, tb_cpointer_t data); /*! replace the head item * * @param list the list * @param data the item data */ tb_void_t tb_list_replace_head(tb_list_ref_t list, tb_cpointer_t data); /*! replace the tail item * * @param list the list * @param data the item data */ tb_void_t tb_list_replace_last(tb_list_ref_t list, tb_cpointer_t data); /*! remove the item * * @param list the list * @param itor the item itor * * @return the next item */ tb_size_t tb_list_remove(tb_list_ref_t list, tb_size_t itor); /*! remove the head item * * @param list the list */ tb_void_t tb_list_remove_head(tb_list_ref_t list); /*! remove the last item * * @param list the list */ tb_void_t tb_list_remove_last(tb_list_ref_t list); /*! moveto the prev item * * @param list the list * @param itor the item itor * @param move the move itor */ tb_void_t tb_list_moveto_prev(tb_list_ref_t list, tb_size_t itor, tb_size_t move); /*! moveto the next item * * @param list the list * @param itor the item itor * @param move the move itor */ tb_void_t tb_list_moveto_next(tb_list_ref_t list, tb_size_t itor, tb_size_t move); /*! moveto the head item * * @param list the list * @param move the move itor */ tb_void_t tb_list_moveto_head(tb_list_ref_t list, tb_size_t move); /*! moveto the tail item * * @param list the list * @param move the move itor */ tb_void_t tb_list_moveto_tail(tb_list_ref_t list, tb_size_t move); /*! the item count * * @param list the list * * @return the item count */ tb_size_t tb_list_size(tb_list_ref_t list); /*! the item max count * * @param list the list * * @return the item max count */ tb_size_t tb_list_maxn(tb_list_ref_t list); #ifdef __tb_debug__ /*! dump list * * @param list the list */ tb_void_t tb_list_dump(tb_list_ref_t list); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/list_entry.c 0000664 0000000 0000000 00000012534 14142237372 0020600 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file list_entry.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "list_entry.h" #include "../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation */ static tb_size_t tb_list_entry_itor_size(tb_iterator_ref_t iterator) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list); // the size return list->size; } static tb_size_t tb_list_entry_itor_head(tb_iterator_ref_t iterator) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list); // head return (tb_size_t)list->next; } static tb_size_t tb_list_entry_itor_last(tb_iterator_ref_t iterator) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list); // last return (tb_size_t)list->prev; } static tb_size_t tb_list_entry_itor_tail(tb_iterator_ref_t iterator) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list); // tail return (tb_size_t)list; } static tb_size_t tb_list_entry_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(itor); // next return (tb_size_t)((tb_list_entry_ref_t)itor)->next; } static tb_size_t tb_list_entry_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(itor); // prev return (tb_size_t)((tb_list_entry_ref_t)itor)->prev; } static tb_pointer_t tb_list_entry_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list && list->eoff < itor); // data return (tb_pointer_t)(itor - list->eoff); } static tb_void_t tb_list_entry_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list && list->copy); tb_assert(list->eoff < itor && item); // copy it list->copy((tb_pointer_t)(itor - list->eoff), (tb_pointer_t)item); } static tb_void_t tb_list_entry_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list && itor); // remove it tb_list_entry_remove(list, (tb_list_entry_ref_t)itor); } static tb_void_t tb_list_entry_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size) { // check tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator); tb_assert(list && prev && next); // no size? tb_check_return(size); // the entry tb_list_entry_ref_t prev_entry = (tb_list_entry_ref_t)prev; tb_list_entry_ref_t next_entry = (tb_list_entry_ref_t)next; // remove entries prev_entry->next = next_entry; next_entry->prev = prev_entry; // update size list->size -= size; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_iterator_ref_t tb_list_entry_itor(tb_list_entry_head_ref_t list) { // check tb_assert_and_check_return_val(list, tb_null); // the iterator return &list->itor; } tb_void_t tb_list_entry_init_(tb_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy) { // check tb_assert_and_check_return(list && entry_size > sizeof(tb_list_entry_t)); // init list list->next = (tb_list_entry_ref_t)list; list->prev = (tb_list_entry_ref_t)list; list->size = 0; list->eoff = entry_offset; list->copy = copy; // init operation static tb_iterator_op_t op = { tb_list_entry_itor_size , tb_list_entry_itor_head , tb_list_entry_itor_last , tb_list_entry_itor_tail , tb_list_entry_itor_prev , tb_list_entry_itor_next , tb_list_entry_itor_item , tb_null , tb_list_entry_itor_copy , tb_list_entry_itor_remove , tb_list_entry_itor_nremove }; // init iterator list->itor.priv = tb_null; list->itor.step = entry_size; list->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE; list->itor.op = &op; } tb_void_t tb_list_entry_exit(tb_list_entry_head_ref_t list) { // check tb_assert_and_check_return(list); // exit it list->next = (tb_list_entry_ref_t)list; list->prev = (tb_list_entry_ref_t)list; list->size = 0; } tbox-1.6.7/src/tbox/container/list_entry.h 0000664 0000000 0000000 00000044700 14142237372 0020605 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file list_entry.h * @ingroup container * */ #ifndef TB_CONTAINER_LIST_ENTRY_H #define TB_CONTAINER_LIST_ENTRY_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// get the list entry #define tb_list_entry(head, entry) ((((tb_byte_t*)(entry)) - (head)->eoff)) /*! get the list entry with zero offset * * @code * // the xxxx entry type typedef struct __tb_xxxx_entry_t { // the list entry (be placed in header with zero offset) tb_list_entry_t entry; // .. }tb_xxxx_entry_t; * * @endcode */ #define tb_list_entry0(entry) (entry) /*! init the list entry * * @code * // the xxxx entry type typedef struct __tb_xxxx_entry_t { // the list entry tb_list_entry_t entry; // the data tb_size_t data; }tb_xxxx_entry_t; // the xxxx entry copy func static tb_void_t tb_xxxx_entry_copy(tb_pointer_t litem, tb_pointer_t ritem) { // check tb_assert(litem && ritem); // copy it ((tb_xxxx_entry_t*)litem)->data = ((tb_xxxx_entry_t*)ritem)->data; } // init the list tb_list_entry_head_t list; tb_list_entry_init(&list, tb_xxxx_entry_t, entry, tb_xxxx_entry_copy); * @endcode */ #define tb_list_entry_init(list, type, entry, copy) tb_list_entry_init_(list, tb_offsetof(type, entry), sizeof(type), copy) /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the doubly-linked list entry type * *
* list: list => ... => last * | | * <--------------- * **/ typedef struct __tb_list_entry_t { /// the next entry struct __tb_list_entry_t* next; /// the prev entry struct __tb_list_entry_t* prev; }tb_list_entry_t, *tb_list_entry_ref_t; /// the list entry head type typedef struct __tb_list_entry_head_t { /// the next entry struct __tb_list_entry_t* next; /// the prev entry struct __tb_list_entry_t* prev; /// the list size tb_size_t size; /// the iterator tb_iterator_t itor; /// the entry offset tb_size_t eoff; /// the entry copy func tb_entry_copy_t copy; }tb_list_entry_head_t, *tb_list_entry_head_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the list iterator * * @param list the list * * @return the list iterator */ tb_iterator_ref_t tb_list_entry_itor(tb_list_entry_head_ref_t list); /*! init list * * @param list the list * @param entry_offset the entry offset * @param entry_size the entry size * @param copy the copy func of the entry for algorithm, .e.g sort */ tb_void_t tb_list_entry_init_(tb_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy); /*! exit list * * @param list the list */ tb_void_t tb_list_entry_exit(tb_list_entry_head_ref_t list); /*! clear list * * @param list the list */ static __tb_inline__ tb_void_t tb_list_entry_clear(tb_list_entry_head_ref_t list) { // check tb_assert(list); // clear it list->next = (tb_list_entry_ref_t)list; list->prev = (tb_list_entry_ref_t)list; list->size = 0; } /*! the list entry count * * @param list the list * * @return the list entry count */ static __tb_inline__ tb_size_t tb_list_entry_size(tb_list_entry_head_ref_t list) { // check tb_assert(list); // done return list->size; } /*! the list next entry * * @param entry the entry * * @return the next entry */ static __tb_inline__ tb_list_entry_ref_t tb_list_entry_next(tb_list_entry_ref_t entry) { // check tb_assert(entry); // done return entry->next; } /*! the list prev entry * * @param entry the entry * * @return the prev entry */ static __tb_inline__ tb_list_entry_ref_t tb_list_entry_prev(tb_list_entry_ref_t entry) { // check tb_assert(entry); // done return entry->prev; } /*! the list head entry * * @param list the list * * @return the head entry */ static __tb_inline__ tb_list_entry_ref_t tb_list_entry_head(tb_list_entry_head_ref_t list) { // check tb_assert(list); // done return list->next; } /*! the list last entry * * @param list the list * * @return the last entry */ static __tb_inline__ tb_list_entry_ref_t tb_list_entry_last(tb_list_entry_head_ref_t list) { // check tb_assert(list); // done return list->prev; } /*! the list tail entry * * @param list the list * * @return the tail entry */ static __tb_inline__ tb_list_entry_ref_t tb_list_entry_tail(tb_list_entry_head_ref_t list) { // done return (tb_list_entry_ref_t)list; } /*! the list is null? * * @param list the list * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_list_entry_is_null(tb_list_entry_head_ref_t list) { // check tb_assert(list); // done return !list->size; } /*! is the list head entry? * * @param list the list * @param entry the entry * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_list_entry_is_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(list); // done return list->next == entry; } /*! is the list last entry? * * @param list the list * @param entry the entry * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_list_entry_is_last(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(list); // done return list->prev == entry; } /*! the list is valid? * * @param list the list * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_list_entry_is_valid(tb_list_entry_head_ref_t list) { // check tb_assert(list); // done return (list->next && list->next->prev == (tb_list_entry_ref_t)list) && (list->prev && list->prev->next == (tb_list_entry_ref_t)list); } /*! splice the spliced_list to list[prev, next] * * @param list the list * @param prev the prev * @param next the next * @param spliced_list the spliced list */ static __tb_inline__ tb_void_t tb_list_entry_splice(tb_list_entry_head_ref_t list, tb_list_entry_ref_t prev, tb_list_entry_ref_t next, tb_list_entry_head_ref_t spliced_list) { // check tb_assert(list && prev && next); tb_assert(spliced_list && spliced_list->next && spliced_list->prev); // valid? tb_assert(tb_list_entry_is_valid(list)); tb_assert(tb_list_entry_is_valid(spliced_list)); // empty? tb_check_return(!tb_list_entry_is_null(spliced_list)); // done spliced_list->next->prev = prev; prev->next = spliced_list->next; spliced_list->prev->next = next; next->prev = spliced_list->prev; // update size list->size += spliced_list->size; // clear the spliced list tb_list_entry_clear(spliced_list); } /*! splice the spliced_list at the list head * * @param list the list * @param spliced_list the spliced list */ static __tb_inline__ tb_void_t tb_list_entry_splice_head(tb_list_entry_head_ref_t list, tb_list_entry_head_ref_t spliced_list) { // check tb_assert(list); // done tb_list_entry_splice(list, (tb_list_entry_ref_t)list, list->next, spliced_list); } /*! splice the spliced_list at the list tail * * @param list the list * @param spliced_list the spliced list */ static __tb_inline__ tb_void_t tb_list_entry_splice_tail(tb_list_entry_head_ref_t list, tb_list_entry_head_ref_t spliced_list) { // check tb_assert(list); // done tb_list_entry_splice(list, list->prev, (tb_list_entry_ref_t)list, spliced_list); } /*! insert entry to the next * * @param list the list * @param node the list node * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_list_entry_insert_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_assert(list && node && node->next && entry); tb_assert(node != entry); // valid? tb_assert(tb_list_entry_is_valid(list)); // insert entry node->next->prev = entry; entry->next = node->next; entry->prev = node; node->next = entry; // size++ list->size++; } /*! insert entry to the prev * * @param list the list * @param node the list node * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_list_entry_insert_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_assert(list && node); // insert it tb_list_entry_insert_next(list, node->prev, entry); } /*! insert entry to the head * * @param list the list * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_list_entry_insert_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { tb_list_entry_insert_next(list, (tb_list_entry_ref_t)list, entry); } /*! insert entry to the tail * * @param list the list * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_list_entry_insert_tail(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(list && entry); // insert it tb_list_entry_insert_next(list, list->prev, entry); } /*! replace the entry * * @param list the list * @param node the replaced list node * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_list_entry_replace(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_assert(node && node->next && node->prev && entry); tb_assert(node != entry); // valid? tb_assert(tb_list_entry_is_valid(list)); // replace it entry->next = node->next; entry->next->prev = entry; entry->prev = node->prev; entry->prev->next = entry; } /*! replace the next entry * * @param list the list * @param node the list node * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_list_entry_replace_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_assert(node); // replace it tb_list_entry_replace(list, node->next, entry); } /*! replace the prev entry * * @param list the list * @param node the list node * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_list_entry_replace_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_assert(node); // replace it tb_list_entry_replace(list, node->prev, entry); } /*! replace the head entry * * @param list the list * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_list_entry_replace_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(list); // replace it tb_list_entry_replace(list, list->next, entry); } /*! replace the last entry * * @param list the list * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_list_entry_replace_last(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(list); // replace it tb_list_entry_replace(list, list->prev, entry); } /*! remove the entry (private interface) * * @param list the list * @param prev the prev entry * @param next the next entry */ static __tb_inline__ tb_void_t tb_list_entry_remove_(tb_list_entry_head_ref_t list, tb_list_entry_ref_t prev, tb_list_entry_ref_t next) { // check tb_assert(list && list->size && prev && next); // valid? tb_assert(tb_list_entry_is_valid(list)); // remove entries prev->next = next; next->prev = prev; // update size list->size--; } /*! remove the entry * * @param list the list * @param entry the removed list entry */ static __tb_inline__ tb_void_t tb_list_entry_remove(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(entry); // remove it tb_list_entry_remove_(list, entry->prev, entry->next); } /*! remove the next entry * * @param list the list * @param prev the prev entry */ static __tb_inline__ tb_void_t tb_list_entry_remove_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t prev) { // check tb_assert(prev && prev->next); // remove it tb_list_entry_remove_(list, prev, prev->next->next); } /*! remove the prev entry * * @param list the list * @param next the next entry */ static __tb_inline__ tb_void_t tb_list_entry_remove_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t next) { // check tb_assert(next && next->prev); // remove it tb_list_entry_remove_(list, next->prev->prev, next); } /*! remove the head entry * * @param list the list */ static __tb_inline__ tb_void_t tb_list_entry_remove_head(tb_list_entry_head_ref_t list) { // check tb_assert(list && list->next); // remove it tb_list_entry_remove_(list, (tb_list_entry_ref_t)list, list->next->next); } /*! remove the last entry * * @param list the list */ static __tb_inline__ tb_void_t tb_list_entry_remove_last(tb_list_entry_head_ref_t list) { // check tb_assert(list && list->prev); // remove it tb_list_entry_remove_(list, list->prev->prev, (tb_list_entry_ref_t)list); } /*! moveto the next entry * * @param list the list * @param node the list node * @param entry the moved list entry */ static __tb_inline__ tb_void_t tb_list_entry_moveto_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_check_return(node != entry); // move it tb_list_entry_remove(list, entry); tb_list_entry_insert_next(list, node, entry); } /*! moveto the prev entry * * @param list the list * @param node the list node * @param entry the moved list entry */ static __tb_inline__ tb_void_t tb_list_entry_moveto_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry) { // check tb_assert(node); // move it tb_list_entry_moveto_next(list, node->prev, entry); } /*! moveto the head entry * * @param list the list * @param entry the moved list entry */ static __tb_inline__ tb_void_t tb_list_entry_moveto_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // move it tb_list_entry_moveto_next(list, (tb_list_entry_ref_t)list, entry); } /*! moveto the tail entry * * @param list the list * @param entry the moved list entry */ static __tb_inline__ tb_void_t tb_list_entry_moveto_tail(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry) { // check tb_assert(list); // move it tb_list_entry_moveto_next(list, list->prev, entry); } /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/prefix.h 0000664 0000000 0000000 00000002145 14142237372 0017703 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_CONTAINER_PREFIX_H #define TB_CONTAINER_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the entry copy func type typedef tb_void_t (*tb_entry_copy_t)(tb_pointer_t litem, tb_pointer_t ritem); #endif tbox-1.6.7/src/tbox/container/priority_queue.c 0000664 0000000 0000000 00000004207 14142237372 0021467 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file priority_queue.c * @ingroup container */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "priority_queue.h" /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_priority_queue_ref_t tb_priority_queue_init(tb_size_t grow, tb_element_t element) { return (tb_priority_queue_ref_t)tb_heap_init(grow, element); } tb_void_t tb_priority_queue_exit(tb_priority_queue_ref_t self) { tb_heap_exit((tb_heap_ref_t)self); } tb_void_t tb_priority_queue_clear(tb_priority_queue_ref_t self) { tb_heap_clear((tb_heap_ref_t)self); } tb_size_t tb_priority_queue_size(tb_priority_queue_ref_t self) { return tb_heap_size((tb_heap_ref_t)self); } tb_size_t tb_priority_queue_maxn(tb_priority_queue_ref_t self) { return tb_heap_maxn((tb_heap_ref_t)self); } tb_pointer_t tb_priority_queue_get(tb_priority_queue_ref_t self) { return tb_heap_top((tb_heap_ref_t)self); } tb_void_t tb_priority_queue_put(tb_priority_queue_ref_t self, tb_cpointer_t data) { tb_heap_put((tb_heap_ref_t)self, data); } tb_void_t tb_priority_queue_pop(tb_priority_queue_ref_t self) { tb_heap_pop((tb_heap_ref_t)self); } tb_void_t tb_priority_queue_remove(tb_priority_queue_ref_t self, tb_size_t itor) { tb_heap_remove((tb_heap_ref_t)self, itor); } #ifdef __tb_debug__ tb_void_t tb_priority_queue_dump(tb_priority_queue_ref_t self) { tb_heap_dump((tb_heap_ref_t)self); } #endif tbox-1.6.7/src/tbox/container/priority_queue.h 0000664 0000000 0000000 00000006653 14142237372 0021503 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file priority_queue.h * @ingroup container * */ #ifndef TB_CONTAINER_PRIORITY_QUEUE_H #define TB_CONTAINER_PRIORITY_QUEUE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "element.h" #include "heap.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the priority queue ref type * * using the min/max heap */ typedef tb_heap_ref_t tb_priority_queue_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init queue, default: min-priority * * @param grow the element grow, using the default grow if be zero * @param element the element * * @return the queue */ tb_priority_queue_ref_t tb_priority_queue_init(tb_size_t grow, tb_element_t element); /*! exit queue * * @param queue the queue */ tb_void_t tb_priority_queue_exit(tb_priority_queue_ref_t queue); /*! clear the queue * * @param queue the queue */ tb_void_t tb_priority_queue_clear(tb_priority_queue_ref_t queue); /*! the queue size * * @param queue the queue * * @return the queue size */ tb_size_t tb_priority_queue_size(tb_priority_queue_ref_t queue); /*! the queue maxn * * @param queue the queue * * @return the queue maxn */ tb_size_t tb_priority_queue_maxn(tb_priority_queue_ref_t queue); /*! get the queue item * * @param queue the queue * * @return the queue top item */ tb_pointer_t tb_priority_queue_get(tb_priority_queue_ref_t queue); /*! put the queue item * * @param queue the queue * @param data the item data */ tb_void_t tb_priority_queue_put(tb_priority_queue_ref_t queue, tb_cpointer_t data); /*! pop the queue item * * @param queue the queue */ tb_void_t tb_priority_queue_pop(tb_priority_queue_ref_t queue); /*! remove the queue item * * @param queue the queue * @param itor the itor */ tb_void_t tb_priority_queue_remove(tb_priority_queue_ref_t queue, tb_size_t itor); #ifdef __tb_debug__ /*! dump queue * * @param queue the queue */ tb_void_t tb_priority_queue_dump(tb_priority_queue_ref_t queue); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/queue.c 0000664 0000000 0000000 00000004743 14142237372 0017533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file queue.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "queue.h" /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_queue_ref_t tb_queue_init(tb_size_t grow, tb_element_t element) { return (tb_queue_ref_t)tb_single_list_init(grow, element); } tb_void_t tb_queue_exit(tb_queue_ref_t queue) { tb_single_list_exit((tb_single_list_ref_t)queue); } tb_void_t tb_queue_clear(tb_queue_ref_t queue) { tb_single_list_clear((tb_single_list_ref_t)queue); } tb_void_t tb_queue_put(tb_queue_ref_t queue, tb_cpointer_t data) { tb_single_list_insert_tail((tb_single_list_ref_t)queue, data); } tb_void_t tb_queue_pop(tb_queue_ref_t queue) { tb_single_list_remove_head((tb_single_list_ref_t)queue); } tb_pointer_t tb_queue_get(tb_queue_ref_t queue) { return tb_queue_head(queue); } tb_pointer_t tb_queue_head(tb_queue_ref_t queue) { return tb_single_list_head((tb_single_list_ref_t)queue); } tb_pointer_t tb_queue_last(tb_queue_ref_t queue) { return tb_single_list_last((tb_single_list_ref_t)queue); } tb_size_t tb_queue_size(tb_queue_ref_t queue) { return tb_single_list_size((tb_single_list_ref_t)queue); } tb_size_t tb_queue_maxn(tb_queue_ref_t queue) { return tb_single_list_maxn((tb_single_list_ref_t)queue); } tb_bool_t tb_queue_full(tb_queue_ref_t queue) { return (tb_single_list_size((tb_single_list_ref_t)queue) < tb_single_list_maxn((tb_single_list_ref_t)queue))? tb_false : tb_true; } tb_bool_t tb_queue_null(tb_queue_ref_t queue) { return tb_single_list_size((tb_single_list_ref_t)queue)? tb_false : tb_true; } #ifdef __tb_debug__ tb_void_t tb_queue_dump(tb_queue_ref_t queue) { tb_single_list_dump((tb_single_list_ref_t)queue); } #endif tbox-1.6.7/src/tbox/container/queue.h 0000664 0000000 0000000 00000007314 14142237372 0017535 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file queue.h * @ingroup container * */ #ifndef TB_CONTAINER_QUEUE_H #define TB_CONTAINER_QUEUE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" #include "single_list.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the queue ref type * *
* queue: |-----| => |-----| => ... => |-----| => tail * head last * * performance: * * put: O(1) * pop: O(1) * * iterator: * * next: fast * prev: fast * **/ typedef tb_single_list_ref_t tb_queue_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init queue * * @param grow the grow size, using the default grow size if be zero * @param element the element * * @return the queue */ tb_queue_ref_t tb_queue_init(tb_size_t grow, tb_element_t element); /*! exit queue * * @param queue the queue */ tb_void_t tb_queue_exit(tb_queue_ref_t queue); /*! the queue head item * * @param queue the queue * * @return the head item */ tb_pointer_t tb_queue_head(tb_queue_ref_t queue); /*! the queue last item * * @param queue the queue * * @return the last item */ tb_pointer_t tb_queue_last(tb_queue_ref_t queue); /*! clear the queue * * @param queue the queue */ tb_void_t tb_queue_clear(tb_queue_ref_t queue); /*! put the queue item * * @param queue the queue * @param data the item data */ tb_void_t tb_queue_put(tb_queue_ref_t queue, tb_cpointer_t data); /*! pop the queue item * * @param queue the queue */ tb_void_t tb_queue_pop(tb_queue_ref_t queue); /*! get the queue item * * @param queue the queue * * @return the queue item */ tb_pointer_t tb_queue_get(tb_queue_ref_t queue); /*! the queue size * * @param queue the queue * * @return the queue size */ tb_size_t tb_queue_size(tb_queue_ref_t queue); /*! the queue maxn * * @param queue the queue * * @return the queue maxn */ tb_size_t tb_queue_maxn(tb_queue_ref_t queue); /*! the queue full? * * @param queue the queue * * @return tb_true or tb_false */ tb_bool_t tb_queue_full(tb_queue_ref_t queue); /*! the queue null? * * @param queue the queue * * @return tb_true or tb_false */ tb_bool_t tb_queue_null(tb_queue_ref_t queue); #ifdef __tb_debug__ /*! dump queue * * @param queue the queue */ tb_void_t tb_queue_dump(tb_queue_ref_t queue); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/single_list.c 0000664 0000000 0000000 00000033017 14142237372 0020717 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file single_list.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "single_list" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "single_list.h" #include "single_list_entry.h" #include "../libc/libc.h" #include "../math/math.h" #include "../memory/memory.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the self grow #ifdef __tb_small__ # define TB_SINGLE_LIST_GROW (128) #else # define TB_SINGLE_LIST_GROW (256) #endif // the self maxn #ifdef __tb_small__ # define TB_SINGLE_LIST_MAXN (1 << 16) #else # define TB_SINGLE_LIST_MAXN (1 << 30) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the single list type typedef struct __tb_single_list_t { // the itor tb_iterator_t itor; // the pool tb_fixed_pool_ref_t pool; // the head tb_single_list_entry_head_t head; // the element tb_element_t element; }tb_single_list_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_size_t tb_single_list_itor_size(tb_iterator_ref_t iterator) { // the size return tb_single_list_size((tb_single_list_ref_t)iterator); } static tb_size_t tb_single_list_itor_head(tb_iterator_ref_t iterator) { // check tb_single_list_t* list = (tb_single_list_t*)iterator; tb_assert(list); // head return (tb_size_t)tb_single_list_entry_head(&list->head); } static tb_size_t tb_single_list_itor_last(tb_iterator_ref_t iterator) { // check tb_single_list_t* list = (tb_single_list_t*)iterator; tb_assert(list); // last return (tb_size_t)tb_single_list_entry_last(&list->head); } static tb_size_t tb_single_list_itor_tail(tb_iterator_ref_t iterator) { // check tb_single_list_t* list = (tb_single_list_t*)iterator; tb_assert(list); // tail return (tb_size_t)tb_single_list_entry_tail(&list->head); } static tb_size_t tb_single_list_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(itor); // next return (tb_size_t)tb_single_list_entry_next((tb_single_list_entry_t*)itor); } static tb_pointer_t tb_single_list_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_single_list_t* list = (tb_single_list_t*)iterator; tb_assert(list && itor); // data return list->element.data(&list->element, (tb_cpointer_t)(((tb_single_list_entry_t*)itor) + 1)); } static tb_void_t tb_single_list_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_single_list_t* list = (tb_single_list_t*)iterator; tb_assert(list && itor); // copy list->element.copy(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)itor) + 1), item); } static tb_long_t tb_single_list_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_single_list_t* list = (tb_single_list_t*)iterator; tb_assert(list && list->element.comp); // comp return list->element.comp(&list->element, litem, ritem); } static tb_void_t tb_single_list_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size) { // no size? tb_check_return(size); // the self size tb_size_t single_list_size = tb_single_list_size((tb_single_list_ref_t)iterator); tb_check_return(single_list_size); // limit size if (size > single_list_size) size = single_list_size; // remove the body items if (prev) { // done tb_bool_t end = tb_false; while (size-- && !end) { // end? end = (tb_iterator_next((tb_single_list_ref_t)iterator, prev) == next)? tb_true : tb_false; // remove next tb_single_list_remove_next((tb_single_list_ref_t)iterator, prev); } } // remove the head items else { while (size--) tb_single_list_remove_head((tb_single_list_ref_t)iterator); } } static tb_void_t tb_single_list_item_exit(tb_pointer_t data, tb_cpointer_t priv) { // check tb_single_list_t* list = (tb_single_list_t*)priv; tb_assert_and_check_return(list); // free data if (list->element.free) list->element.free(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)data) + 1)); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_single_list_ref_t tb_single_list_init(tb_size_t grow, tb_element_t element) { // check tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl, tb_null); // done tb_bool_t ok = tb_false; tb_single_list_t* list = tb_null; do { // using the default grow if (!grow) grow = TB_SINGLE_LIST_GROW; // make self list = tb_malloc0_type(tb_single_list_t); tb_assert_and_check_break(list); // init element list->element = element; // init operation static tb_iterator_op_t op = { tb_single_list_itor_size , tb_single_list_itor_head , tb_single_list_itor_last , tb_single_list_itor_tail , tb_null , tb_single_list_itor_next , tb_single_list_itor_item , tb_single_list_itor_comp , tb_single_list_itor_copy , tb_null , tb_single_list_itor_nremove }; // init iterator list->itor.priv = tb_null; list->itor.step = element.size; list->itor.mode = TB_ITERATOR_MODE_FORWARD; list->itor.op = &op; // init pool, item = entry + data list->pool = tb_fixed_pool_init(tb_null, grow, sizeof(tb_single_list_entry_t) + element.size, tb_null, tb_single_list_item_exit, (tb_cpointer_t)list); tb_assert_and_check_break(list->pool); // init head tb_single_list_entry_init_(&list->head, 0, sizeof(tb_single_list_entry_t) + element.size, tb_null); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (list) tb_single_list_exit((tb_single_list_ref_t)list); list = tb_null; } // ok? return (tb_single_list_ref_t)list; } tb_void_t tb_single_list_exit(tb_single_list_ref_t self) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return(list); // clear data tb_single_list_clear((tb_single_list_ref_t)list); // free pool if (list->pool) tb_fixed_pool_exit(list->pool); // free it tb_free(list); } tb_void_t tb_single_list_clear(tb_single_list_ref_t self) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return(list); // clear pool if (list->pool) tb_fixed_pool_clear(list->pool); // clear head tb_single_list_entry_clear(&list->head); } tb_pointer_t tb_single_list_head(tb_single_list_ref_t self) { return tb_iterator_item(self, tb_iterator_head(self)); } tb_pointer_t tb_single_list_last(tb_single_list_ref_t self) { return tb_iterator_item(self, tb_iterator_last(self)); } tb_size_t tb_single_list_size(tb_single_list_ref_t self) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return_val(list && list->pool, 0); tb_assert(tb_single_list_entry_size(&list->head) == tb_fixed_pool_size(list->pool)); // the size return tb_single_list_entry_size(&list->head); } tb_size_t tb_single_list_maxn(tb_single_list_ref_t self) { // the item maxn return TB_SINGLE_LIST_MAXN; } tb_size_t tb_single_list_insert_next(tb_single_list_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0); // full? tb_assert_and_check_return_val(tb_single_list_size(self) < tb_single_list_maxn(self), tb_iterator_tail(self)); // the node tb_single_list_entry_ref_t node = (tb_single_list_entry_ref_t)itor; tb_assert_and_check_return_val(node, tb_iterator_tail(self)); // make entry tb_single_list_entry_ref_t entry = (tb_single_list_entry_ref_t)tb_fixed_pool_malloc(list->pool); tb_assert_and_check_return_val(entry, tb_iterator_tail(self)); // init entry data list->element.dupl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)entry) + 1), data); // insert it tb_single_list_entry_insert_next(&list->head, node, entry); // ok return (tb_size_t)entry; } tb_size_t tb_single_list_insert_head(tb_single_list_ref_t self, tb_cpointer_t data) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0); // full? tb_assert_and_check_return_val(tb_single_list_size(self) < tb_single_list_maxn(self), tb_iterator_tail(self)); // make entry tb_single_list_entry_ref_t entry = (tb_single_list_entry_ref_t)tb_fixed_pool_malloc(list->pool); tb_assert_and_check_return_val(entry, tb_iterator_tail(self)); // init entry data list->element.dupl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)entry) + 1), data); // insert it tb_single_list_entry_insert_head(&list->head, entry); // ok return (tb_size_t)entry; } tb_size_t tb_single_list_insert_tail(tb_single_list_ref_t self, tb_cpointer_t data) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0); // full? tb_assert_and_check_return_val(tb_single_list_size(self) < tb_single_list_maxn(self), tb_iterator_tail(self)); // make entry tb_single_list_entry_ref_t entry = (tb_single_list_entry_ref_t)tb_fixed_pool_malloc(list->pool); tb_assert_and_check_return_val(entry, tb_iterator_tail(self)); // init entry data list->element.dupl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)entry) + 1), data); // insert it tb_single_list_entry_insert_tail(&list->head, entry); // ok return (tb_size_t)entry; } tb_void_t tb_single_list_replace(tb_single_list_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return(list && list->element.repl && itor); // the node tb_single_list_entry_ref_t node = (tb_single_list_entry_ref_t)itor; tb_assert_and_check_return(node); // replace data list->element.repl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)node) + 1), data); } tb_void_t tb_single_list_replace_head(tb_single_list_ref_t self, tb_cpointer_t data) { tb_single_list_replace(self, tb_iterator_head(self), data); } tb_void_t tb_single_list_replace_last(tb_single_list_ref_t self, tb_cpointer_t data) { tb_single_list_replace(self, tb_iterator_last(self), data); } tb_void_t tb_single_list_remove_next(tb_single_list_ref_t self, tb_size_t itor) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return(list && list->pool && itor); // the node tb_single_list_entry_ref_t node = (tb_single_list_entry_ref_t)itor; tb_assert_and_check_return(node); // the next node tb_single_list_entry_ref_t next = tb_single_list_entry_next(node); tb_assert_and_check_return(next); // remove next node tb_single_list_entry_remove_next(&list->head, node); // free next node tb_fixed_pool_free(list->pool, next); } tb_void_t tb_single_list_remove_head(tb_single_list_ref_t self) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return(list && list->pool); // the node tb_single_list_entry_ref_t node = tb_single_list_entry_head(&list->head); tb_assert_and_check_return(node); // remove next node tb_single_list_entry_remove_head(&list->head); // free head node tb_fixed_pool_free(list->pool, node); } #ifdef __tb_debug__ tb_void_t tb_single_list_dump(tb_single_list_ref_t self) { // check tb_single_list_t* list = (tb_single_list_t*)self; tb_assert_and_check_return(list); // trace tb_trace_i("single_list: size: %lu", tb_single_list_size(self)); // done tb_char_t cstr[4096]; tb_for_all (tb_pointer_t, data, self) { // trace if (list->element.cstr) { tb_trace_i(" %s", list->element.cstr(&list->element, data, cstr, sizeof(cstr))); } else { tb_trace_i(" %p", data); } } } #endif tbox-1.6.7/src/tbox/container/single_list.h 0000664 0000000 0000000 00000012003 14142237372 0020714 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file single_list.h * @ingroup container * */ #ifndef TB_CONTAINER_SINGLE_LIST_H #define TB_CONTAINER_SINGLE_LIST_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the double list ref type * * *
* list: |-----| => |-------------------------------------------------=> |------| => |------| => tail * head last * * performance: * * insert: * insert midd: slow * insert head: fast * insert tail: fast * insert next: fast * * remove: * remove midd: slow * remove head: fast * remove last: fast * remove next: fast * * iterator: * next: fast ** */ typedef tb_iterator_ref_t tb_single_list_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init list * * @param grow the grow size * @param element the element * * @return the list */ tb_single_list_ref_t tb_single_list_init(tb_size_t grow, tb_element_t element); /*! exit list * * @param list the list */ tb_void_t tb_single_list_exit(tb_single_list_ref_t list); /*! clear list * * @param list the list */ tb_void_t tb_single_list_clear(tb_single_list_ref_t list); /*! the list head item * * @param list the list * * @return the head item */ tb_pointer_t tb_single_list_head(tb_single_list_ref_t list); /*! the list last item * * @param list the list * * @return the last item */ tb_pointer_t tb_single_list_last(tb_single_list_ref_t list); /*! insert the next item * * @param list the list * @param itor the item itor * @param data the item data * * @return the item itor */ tb_size_t tb_single_list_insert_next(tb_single_list_ref_t list, tb_size_t itor, tb_cpointer_t data); /*! insert the head item * * @param list the list * @param data the item data * * @return the item itor */ tb_size_t tb_single_list_insert_head(tb_single_list_ref_t list, tb_cpointer_t data); /*! insert the tail item * * @param list the list * @param data the item data * * @return the item itor */ tb_size_t tb_single_list_insert_tail(tb_single_list_ref_t list, tb_cpointer_t data); /*! replace the item * * @param list the list * @param itor the item itor * @param data the item data */ tb_void_t tb_single_list_replace(tb_single_list_ref_t list, tb_size_t itor, tb_cpointer_t data); /*! replace the head item * * @param list the list * @param data the item data */ tb_void_t tb_single_list_replace_head(tb_single_list_ref_t list, tb_cpointer_t data); /*! replace the tail item * * @param list the list * @param data the item data */ tb_void_t tb_single_list_replace_last(tb_single_list_ref_t list, tb_cpointer_t data); /*! remove the next item * * @param list the list * @param itor the item itor */ tb_void_t tb_single_list_remove_next(tb_single_list_ref_t list, tb_size_t itor); /*! remove the head item * * @param list the list */ tb_void_t tb_single_list_remove_head(tb_single_list_ref_t list); /*! the item count * * @param list the list * * @return the item count */ tb_size_t tb_single_list_size(tb_single_list_ref_t list); /*! the item max count * * @param list the list * * @return the item max count */ tb_size_t tb_single_list_maxn(tb_single_list_ref_t list); #ifdef __tb_debug__ /*! dump list * * @param list the list */ tb_void_t tb_single_list_dump(tb_single_list_ref_t list); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/single_list_entry.c 0000664 0000000 0000000 00000011575 14142237372 0022145 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file single_list_entry.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "single_list_entry.h" #include "../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation */ static tb_size_t tb_single_list_entry_itor_size(tb_iterator_ref_t iterator) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert(list); // the size return list->size; } static tb_size_t tb_single_list_entry_itor_head(tb_iterator_ref_t iterator) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert(list); // head return (tb_size_t)list->next; } static tb_size_t tb_single_list_entry_itor_last(tb_iterator_ref_t iterator) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert(list); // last return (tb_size_t)list->last; } static tb_size_t tb_single_list_entry_itor_tail(tb_iterator_ref_t iterator) { // tail return (tb_size_t)0; } static tb_size_t tb_single_list_entry_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert(itor); // next return (tb_size_t)((tb_single_list_entry_ref_t)itor)->next; } static tb_pointer_t tb_single_list_entry_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert(list && list->eoff < itor); // data return (tb_pointer_t)(itor - list->eoff); } static tb_void_t tb_single_list_entry_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert(list && list->copy); tb_assert(list->eoff < itor && item); // copy it list->copy((tb_pointer_t)(itor - list->eoff), (tb_pointer_t)item); } static tb_void_t tb_single_list_entry_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert(list && prev && next); // no size? tb_check_return(size); // the entry tb_single_list_entry_ref_t prev_entry = (tb_single_list_entry_ref_t)prev; tb_single_list_entry_ref_t next_entry = (tb_single_list_entry_ref_t)next; // remove entries prev_entry->next = next_entry; // update size list->size -= size; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_iterator_ref_t tb_single_list_entry_itor(tb_single_list_entry_head_ref_t list) { // check tb_assert_and_check_return_val(list, tb_null); // the iterator return &list->itor; } tb_void_t tb_single_list_entry_init_(tb_single_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy) { // check tb_assert_and_check_return(list && entry_size > sizeof(tb_single_list_entry_t)); // init list list->next = tb_null; list->last = tb_null; list->size = 0; list->eoff = entry_offset; list->copy = copy; // init operation static tb_iterator_op_t op = { tb_single_list_entry_itor_size , tb_single_list_entry_itor_head , tb_single_list_entry_itor_last , tb_single_list_entry_itor_tail , tb_null , tb_single_list_entry_itor_next , tb_single_list_entry_itor_item , tb_null , tb_single_list_entry_itor_copy , tb_null , tb_single_list_entry_itor_nremove }; // init iterator list->itor.priv = tb_null; list->itor.step = entry_size; list->itor.mode = TB_ITERATOR_MODE_FORWARD; list->itor.op = &op; } tb_void_t tb_single_list_entry_exit(tb_single_list_entry_head_ref_t list) { // check tb_assert_and_check_return(list); // exit it list->next = tb_null; list->last = tb_null; list->size = 0; } tbox-1.6.7/src/tbox/container/single_list_entry.h 0000664 0000000 0000000 00000027375 14142237372 0022157 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file single_list_entry.h * @ingroup container * */ #ifndef TB_CONTAINER_SINGLE_LIST_ENTRY_H #define TB_CONTAINER_SINGLE_LIST_ENTRY_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the list entry #define tb_single_list_entry(head, entry) ((((tb_byte_t*)(entry)) - (head)->eoff)) /*! get the list entry with zero offset * * @code * // the xxxx entry type typedef struct __tb_xxxx_entry_t { // the list entry (be placed in header with zero offset) tb_single_list_entry_t entry; // .. }tb_xxxx_entry_t; * * @endcode */ #define tb_single_list_entry0(entry) (entry) /*! init the list entry * * @code * // the xxxx entry type typedef struct __tb_xxxx_entry_t { // the list entry tb_single_list_entry_t entry; // the data tb_size_t data; }tb_xxxx_entry_t; // the xxxx entry copy func static tb_void_t tb_xxxx_entry_copy(tb_pointer_t litem, tb_pointer_t ritem) { // check tb_assert(litem && ritem); // copy it ((tb_xxxx_entry_t*)litem)->data = ((tb_xxxx_entry_t*)ritem)->data; } // init the list tb_single_list_entry_head_t list; tb_single_list_entry_init(&list, tb_xxxx_entry_t, entry, tb_xxxx_entry_copy); * @endcode */ #define tb_single_list_entry_init(list, type, entry, copy) tb_single_list_entry_init_(list, tb_offsetof(type, entry), sizeof(type), copy) /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the single-linked list entry type * *
* list: head => ... => last => null * **/ typedef struct __tb_single_list_entry_t { /// the next entry struct __tb_single_list_entry_t* next; }tb_single_list_entry_t, *tb_single_list_entry_ref_t; /// the single-linked list entry head type typedef struct __tb_single_list_entry_head_t { /// the next entry struct __tb_single_list_entry_t* next; /// the last entry struct __tb_single_list_entry_t* last; /// the list size tb_size_t size; /// the iterator tb_iterator_t itor; /// the entry offset tb_size_t eoff; /// the entry copy func tb_entry_copy_t copy; }tb_single_list_entry_head_t, *tb_single_list_entry_head_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the list iterator * * @param list the list * * @return the list iterator */ tb_iterator_ref_t tb_single_list_entry_itor(tb_single_list_entry_head_ref_t list); /*! init list * * @param list the list * @param entry_offset the entry offset * @param entry_size the entry size * @param copy the copy func of the entry for algorithm, .e.g sort */ tb_void_t tb_single_list_entry_init_(tb_single_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy); /*! exit list * * @param list the list */ tb_void_t tb_single_list_entry_exit(tb_single_list_entry_head_ref_t list); /*! clear list * * @param list the list */ static __tb_inline__ tb_void_t tb_single_list_entry_clear(tb_single_list_entry_head_ref_t list) { // check tb_assert(list); // clear it list->next = tb_null; list->last = tb_null; list->size = 0; } /*! the list entry count * * @param list the list * * @return the list entry count */ static __tb_inline__ tb_size_t tb_single_list_entry_size(tb_single_list_entry_head_ref_t list) { // check tb_assert(list); // done return list->size; } /*! the list next entry * * @param entry the entry * * @return the next entry */ static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_next(tb_single_list_entry_ref_t entry) { // check tb_assert(entry); // done return entry->next; } /*! the list head entry * * @param list the list * * @return the head entry */ static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_head(tb_single_list_entry_head_ref_t list) { // check tb_assert(list); // done return list->next; } /*! the list last entry * * @param list the list * * @return the last entry */ static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_last(tb_single_list_entry_head_ref_t list) { // check tb_assert(list); // done return list->last; } /*! the list tail entry * * @param list the list * * @return the tail entry */ static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_tail(tb_single_list_entry_head_ref_t list) { return tb_null; } /*! the list is null? * * @param list the list * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_single_list_entry_is_null(tb_single_list_entry_head_ref_t list) { // check tb_assert(list); // done return !list->size; } /*! is the list head entry? * * @param list the list * @param entry the entry * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_single_list_entry_is_head(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry) { // check tb_assert(list); // done return list->next == entry; } /*! is the list last entry? * * @param list the list * @param entry the entry * * @return tb_true or tb_false */ static __tb_inline__ tb_bool_t tb_single_list_entry_is_last(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry) { // check tb_assert(list); // done return list->last == entry; } /*! insert entry to the next * * @param list the list * @param node the list node * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_single_list_entry_insert_next(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t node, tb_single_list_entry_ref_t entry) { // check tb_assert(list && node && entry); tb_assert(node != entry); // update last if (node == list->last || !list->next) list->last = entry; // insert entry entry->next = node->next; node->next = entry; // size++ list->size++; } /*! insert entry to the head * * @param list the list * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_single_list_entry_insert_head(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry) { // insert it tb_single_list_entry_insert_next(list, (tb_single_list_entry_ref_t)list, entry); } /*! insert entry to the tail * * @param list the list * @param entry the inserted list entry */ static __tb_inline__ tb_void_t tb_single_list_entry_insert_tail(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry) { // check tb_assert(list && entry); // insert it if (list->last) tb_single_list_entry_insert_next(list, list->last, entry); else tb_single_list_entry_insert_head(list, entry); } /*! replace the next entry * * @param list the list * @param node the list node * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_single_list_entry_replace_next(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t node, tb_single_list_entry_ref_t entry) { // check tb_assert(node && node->next); tb_assert(node != entry); // update last if (node->next == list->last) list->last = entry; // replace it entry->next = node->next->next; node->next = entry; } /*! replace the head entry * * @param list the list * @param entry the new list entry */ static __tb_inline__ tb_void_t tb_single_list_entry_replace_head(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry) { // replace it tb_single_list_entry_replace_next(list, (tb_single_list_entry_ref_t)list, entry); } /*! remove the entry (private interface) * * @param list the list * @param prev the prev entry * @param next the next entry */ static __tb_inline__ tb_void_t tb_single_list_entry_remove_(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t prev, tb_single_list_entry_ref_t next) { // check tb_assert(list && list->size && prev); // update last, prev -> last -> next (null) if (prev->next == list->last) list->last = prev; // remove entries prev->next = next; // update size list->size--; } /*! remove the next entry * * @param list the list * @param prev the prev entry */ static __tb_inline__ tb_void_t tb_single_list_entry_remove_next(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t prev) { // check tb_assert(prev && prev->next); // remove it tb_single_list_entry_remove_(list, prev, prev->next->next); } /*! remove the head entry * * @param list the list */ static __tb_inline__ tb_void_t tb_single_list_entry_remove_head(tb_single_list_entry_head_ref_t list) { // check tb_assert(list->next); // remove it tb_single_list_entry_remove_(list, (tb_single_list_entry_ref_t)list, list->next->next); } /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/stack.c 0000664 0000000 0000000 00000004465 14142237372 0017515 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file stack.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "stack.h" #include "../libc/libc.h" #include "../utils/utils.h" #include "../memory/memory.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_stack_ref_t tb_stack_init(tb_size_t grow, tb_element_t element) { return (tb_stack_ref_t)tb_vector_init(grow, element); } tb_void_t tb_stack_exit(tb_stack_ref_t self) { tb_vector_exit((tb_vector_ref_t)self); } tb_void_t tb_stack_clear(tb_stack_ref_t self) { tb_vector_clear((tb_vector_ref_t)self); } tb_void_t tb_stack_copy(tb_stack_ref_t self, tb_stack_ref_t copy) { tb_vector_copy((tb_vector_ref_t)self, copy); } tb_void_t tb_stack_put(tb_stack_ref_t self, tb_cpointer_t data) { tb_vector_insert_tail((tb_vector_ref_t)self, data); } tb_void_t tb_stack_pop(tb_stack_ref_t self) { tb_vector_remove_last((tb_vector_ref_t)self); } tb_pointer_t tb_stack_top(tb_stack_ref_t self) { return tb_vector_last((tb_vector_ref_t)self); } tb_pointer_t tb_stack_head(tb_stack_ref_t self) { return tb_vector_head((tb_vector_ref_t)self); } tb_pointer_t tb_stack_last(tb_stack_ref_t self) { return tb_vector_last((tb_vector_ref_t)self); } tb_size_t tb_stack_size(tb_stack_ref_t self) { return tb_vector_size((tb_vector_ref_t)self); } tb_size_t tb_stack_maxn(tb_stack_ref_t self) { return tb_vector_maxn((tb_vector_ref_t)self); } #ifdef __tb_debug__ tb_void_t tb_stack_dump(tb_stack_ref_t self) { tb_vector_dump((tb_vector_ref_t)self); } #endif tbox-1.6.7/src/tbox/container/stack.h 0000664 0000000 0000000 00000007232 14142237372 0017515 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file stack.h * @ingroup container * */ #ifndef TB_CONTAINER_STACK_H #define TB_CONTAINER_STACK_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "vector.h" #include "element.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the stack ref type * *
* stack: |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||------| * head last tail * * stack: |||||||||||||||||||||||||||||||||||||||||------| * head last tail * * performance: * * push: fast * pop: fast * * iterator: * next: fast * prev: fast ** * @note the itor of the same item is fixed * */ typedef tb_vector_ref_t tb_stack_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init stack * * @param grow the item grow * @param element the element * * @return the stack */ tb_stack_ref_t tb_stack_init(tb_size_t grow, tb_element_t element); /*! exit stack * * @param stack the stack */ tb_void_t tb_stack_exit(tb_stack_ref_t stack); /*! the stack head item * * @param stack the stack * * @return the head item */ tb_pointer_t tb_stack_head(tb_stack_ref_t stack); /*! the stack last item * * @param stack the stack * * @return the last item */ tb_pointer_t tb_stack_last(tb_stack_ref_t stack); /*! clear the stack * * @param stack the stack */ tb_void_t tb_stack_clear(tb_stack_ref_t stack); /*! copy the stack * * @param stack the stack * @param copy the copied stack */ tb_void_t tb_stack_copy(tb_stack_ref_t stack, tb_stack_ref_t copy); /*! put the stack item * * @param stack the stack * @param data the item data */ tb_void_t tb_stack_put(tb_stack_ref_t stack, tb_cpointer_t data); /*! pop the stack item * * @param stack the stack */ tb_void_t tb_stack_pop(tb_stack_ref_t stack); /*! the stack top item * * @param stack the stack * * @return the stack top item */ tb_pointer_t tb_stack_top(tb_stack_ref_t stack); /*! the stack size * * @param stack the stack * * @return the stack size */ tb_size_t tb_stack_size(tb_stack_ref_t stack); /*! the stack maxn * * @param stack the stack * * @return the stack maxn */ tb_size_t tb_stack_maxn(tb_stack_ref_t stack); #ifdef __tb_debug__ /*! dump stack * * @param stack the stack */ tb_void_t tb_stack_dump(tb_stack_ref_t stack); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/container/vector.c 0000664 0000000 0000000 00000043675 14142237372 0017720 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file vector.c * @ingroup container * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "vector" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "vector.h" #include "../libc/libc.h" #include "../utils/utils.h" #include "../memory/memory.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the vector grow #ifdef __tb_small__ # define TB_VECTOR_GROW (128) #else # define TB_VECTOR_GROW (256) #endif // the vector maxn #ifdef __tb_small__ # define TB_VECTOR_MAXN (1 << 16) #else # define TB_VECTOR_MAXN (1 << 30) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the vector type typedef struct __tb_vector_t { // the itor tb_iterator_t itor; // the data tb_byte_t* data; // the size tb_size_t size; // the grow tb_size_t grow; // the maxn tb_size_t maxn; // the element tb_element_t element; }tb_vector_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_size_t tb_vector_itor_size(tb_iterator_ref_t iterator) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); // size return vector->size; } static tb_size_t tb_vector_itor_head(tb_iterator_ref_t iterator) { // head return 0; } static tb_size_t tb_vector_itor_last(tb_iterator_ref_t iterator) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); // last return vector->size? vector->size - 1 : 0; } static tb_size_t tb_vector_itor_tail(tb_iterator_ref_t iterator) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); // tail return vector->size; } static tb_size_t tb_vector_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); tb_assert_and_check_return_val(itor < vector->size, vector->size); // next return itor + 1; } static tb_size_t tb_vector_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); tb_assert_and_check_return_val(itor && itor <= vector->size, 0); // prev return itor - 1; } static tb_pointer_t tb_vector_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert_and_check_return_val(vector && itor < vector->size, tb_null); // data return vector->element.data(&vector->element, vector->data + itor * iterator->step); } static tb_void_t tb_vector_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); // copy vector->element.copy(&vector->element, vector->data + itor * iterator->step, item); } static tb_long_t tb_vector_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector && vector->element.comp); // comp return vector->element.comp(&vector->element, litem, ritem); } static tb_void_t tb_vector_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor) { // remove it tb_vector_remove((tb_vector_ref_t)iterator, itor); } static tb_void_t tb_vector_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)iterator; tb_assert(vector); // remove the items if (size) tb_vector_nremove((tb_vector_ref_t)iterator, prev != vector->size? prev + 1 : 0, size); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_vector_ref_t tb_vector_init(tb_size_t grow, tb_element_t element) { // check tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl && element.ndupl && element.nrepl, tb_null); // done tb_bool_t ok = tb_false; tb_vector_t* vector = tb_null; do { // using the default grow if (!grow) grow = TB_VECTOR_GROW; // make vector vector = tb_malloc0_type(tb_vector_t); tb_assert_and_check_break(vector); // init vector vector->size = 0; vector->grow = grow; vector->maxn = grow; vector->element = element; tb_assert_and_check_break(vector->maxn < TB_VECTOR_MAXN); // init operation static tb_iterator_op_t op = { tb_vector_itor_size , tb_vector_itor_head , tb_vector_itor_last , tb_vector_itor_tail , tb_vector_itor_prev , tb_vector_itor_next , tb_vector_itor_item , tb_vector_itor_comp , tb_vector_itor_copy , tb_vector_itor_remove , tb_vector_itor_nremove }; // init iterator vector->itor.priv = tb_null; vector->itor.step = element.size; vector->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE; vector->itor.op = &op; // make data vector->data = (tb_byte_t*)tb_nalloc0(vector->maxn, element.size); tb_assert_and_check_break(vector->data); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (vector) tb_vector_exit((tb_vector_ref_t)vector); vector = tb_null; } // ok? return (tb_vector_ref_t)vector; } tb_void_t tb_vector_exit(tb_vector_ref_t self) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector); // clear data tb_vector_clear(self); // free data if (vector->data) tb_free(vector->data); vector->data = tb_null; // free it tb_free(vector); } tb_void_t tb_vector_clear(tb_vector_ref_t self) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector); // free data if (vector->element.nfree) vector->element.nfree(&vector->element, vector->data, vector->size); // reset size vector->size = 0; } tb_void_t tb_vector_copy(tb_vector_ref_t self, tb_vector_ref_t copy) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_vector_t const* vector_copy = (tb_vector_t const*)copy; tb_assert_and_check_return(vector && vector_copy); // check element tb_assert_and_check_return(vector->element.type == vector_copy->element.type); tb_assert_and_check_return(vector->element.size == vector_copy->element.size); // check itor tb_assert_and_check_return(vector->itor.step == vector_copy->itor.step); // null? clear it if (!vector_copy->size) { tb_vector_clear(self); return ; } // resize if small if (vector->size < vector_copy->size) tb_vector_resize(self, vector_copy->size); tb_assert_and_check_return(vector->data && vector_copy->data && vector->size >= vector_copy->size); // copy data if (vector_copy->data != vector->data) tb_memcpy(vector->data, vector_copy->data, vector_copy->size * vector_copy->element.size); // copy size vector->size = vector_copy->size; } tb_pointer_t tb_vector_data(tb_vector_ref_t self) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return_val(vector, tb_null); // data return vector->data; } tb_pointer_t tb_vector_head(tb_vector_ref_t self) { return tb_iterator_item(self, tb_iterator_head(self)); } tb_pointer_t tb_vector_last(tb_vector_ref_t self) { return tb_iterator_item(self, tb_iterator_last(self)); } tb_size_t tb_vector_size(tb_vector_ref_t self) { // check tb_vector_t const* vector = (tb_vector_t const*)self; tb_assert_and_check_return_val(vector, 0); // size return vector->size; } tb_size_t tb_vector_grow(tb_vector_ref_t self) { // check tb_vector_t const* vector = (tb_vector_t const*)self; tb_assert_and_check_return_val(vector, 0); // grow return vector->grow; } tb_size_t tb_vector_maxn(tb_vector_ref_t self) { // check tb_vector_t const* vector = (tb_vector_t const*)self; tb_assert_and_check_return_val(vector, 0); // maxn return vector->maxn; } tb_bool_t tb_vector_resize(tb_vector_ref_t self, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return_val(vector, tb_false); // free items if the vector is decreased if (size < vector->size) { // free data if (vector->element.nfree) vector->element.nfree(&vector->element, vector->data + size * vector->element.size, vector->size - size); } // resize buffer if (size > vector->maxn) { tb_size_t maxn = tb_align4(size + vector->grow); tb_assert_and_check_return_val(maxn < TB_VECTOR_MAXN, tb_false); // realloc data vector->data = (tb_byte_t*)tb_ralloc(vector->data, maxn * vector->element.size); tb_assert_and_check_return_val(vector->data, tb_false); // must be align by 4-bytes tb_assert_and_check_return_val(!(((tb_size_t)(vector->data)) & 3), tb_false); // clear the grow data tb_memset(vector->data + vector->size * vector->element.size, 0, (maxn - vector->maxn) * vector->element.size); // save maxn vector->maxn = maxn; } // update size vector->size = size; return tb_true; } tb_void_t tb_vector_insert_prev(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && vector->data && vector->element.size && itor <= vector->size); // save size tb_size_t osize = vector->size; // grow a item if (!tb_vector_resize(self, osize + 1)) { tb_trace_d("vector resize: %u => %u failed", osize, osize + 1); return ; } // move items if not at tail if (osize != itor) tb_memmov(vector->data + (itor + 1) * vector->element.size, vector->data + itor * vector->element.size, (osize - itor) * vector->element.size); // save data vector->element.dupl(&vector->element, vector->data + itor * vector->element.size, data); } tb_void_t tb_vector_insert_next(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data) { tb_vector_insert_prev(self, tb_iterator_next(self, itor), data); } tb_void_t tb_vector_insert_head(tb_vector_ref_t self, tb_cpointer_t data) { tb_vector_insert_prev(self, 0, data); } tb_void_t tb_vector_insert_tail(tb_vector_ref_t self, tb_cpointer_t data) { tb_vector_insert_prev(self, tb_vector_size(self), data); } tb_void_t tb_vector_ninsert_prev(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && vector->data && size && itor <= vector->size); // save size tb_size_t osize = vector->size; // grow size if (!tb_vector_resize(self, osize + size)) { tb_trace_d("vector resize: %u => %u failed", osize, osize + 1); return ; } // move items if not at tail if (osize != itor) tb_memmov(vector->data + (itor + size) * vector->element.size, vector->data + itor * vector->element.size, (osize - itor) * vector->element.size); // duplicate data vector->element.ndupl(&vector->element, vector->data + itor * vector->element.size, data, size); } tb_void_t tb_vector_ninsert_next(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data, tb_size_t size) { tb_vector_ninsert_prev(self, tb_iterator_next(self, itor), data, size); } tb_void_t tb_vector_ninsert_head(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size) { tb_vector_ninsert_prev(self, 0, data, size); } tb_void_t tb_vector_ninsert_tail(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size) { tb_vector_ninsert_prev(self, tb_vector_size(self), data, size); } tb_void_t tb_vector_replace(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && vector->data && itor <= vector->size); // replace data vector->element.repl(&vector->element, vector->data + itor * vector->element.size, data); } tb_void_t tb_vector_replace_head(tb_vector_ref_t self, tb_cpointer_t data) { tb_vector_replace(self, 0, data); } tb_void_t tb_vector_replace_last(tb_vector_ref_t self, tb_cpointer_t data) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && vector->size); // replace tb_vector_replace(self, vector->size - 1, data); } tb_void_t tb_vector_nreplace(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && vector->data && vector->size && itor <= vector->size && size); // strip size if (itor + size > vector->size) size = vector->size - itor; // replace data vector->element.nrepl(&vector->element, vector->data + itor * vector->element.size, data, size); } tb_void_t tb_vector_nreplace_head(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size) { tb_vector_nreplace(self, 0, data, size); } tb_void_t tb_vector_nreplace_last(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && vector->size && size); // replace tb_vector_nreplace(self, size >= vector->size? 0 : vector->size - size, data, size); } tb_void_t tb_vector_remove(tb_vector_ref_t self, tb_size_t itor) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && itor < vector->size); if (vector->size) { // do free if (vector->element.free) vector->element.free(&vector->element, vector->data + itor * vector->element.size); // move data if itor is not last if (itor < vector->size - 1) tb_memmov(vector->data + itor * vector->element.size, vector->data + (itor + 1) * vector->element.size, (vector->size - itor - 1) * vector->element.size); // resize vector->size--; } } tb_void_t tb_vector_remove_head(tb_vector_ref_t self) { tb_vector_remove(self, 0); } tb_void_t tb_vector_remove_last(tb_vector_ref_t self) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector); if (vector->size) { // do free if (vector->element.free) vector->element.free(&vector->element, vector->data + (vector->size - 1) * vector->element.size); // resize vector->size--; } } tb_void_t tb_vector_nremove(tb_vector_ref_t self, tb_size_t itor, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && size && itor < vector->size); // clear it if (!itor && size >= vector->size) { tb_vector_clear(self); return ; } // strip size if (itor + size > vector->size) size = vector->size - itor; // compute the left size tb_size_t left = vector->size - itor - size; // free data if (vector->element.nfree) vector->element.nfree(&vector->element, vector->data + itor * vector->element.size, size); // move the left data if (left) { tb_byte_t* pd = vector->data + itor * vector->element.size; tb_byte_t* ps = vector->data + (itor + size) * vector->element.size; tb_memmov(pd, ps, left * vector->element.size); } // update size vector->size -= size; } tb_void_t tb_vector_nremove_head(tb_vector_ref_t self, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && size); // clear it if (size >= vector->size) { tb_vector_clear(self); return ; } // remove head tb_vector_nremove(self, 0, size); } tb_void_t tb_vector_nremove_last(tb_vector_ref_t self, tb_size_t size) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector && size); // clear it if (size >= vector->size) { tb_vector_clear(self); return ; } // remove last tb_vector_nremove(self, vector->size - size, size); } #ifdef __tb_debug__ tb_void_t tb_vector_dump(tb_vector_ref_t self) { // check tb_vector_t* vector = (tb_vector_t*)self; tb_assert_and_check_return(vector); // trace tb_trace_i("vector: size: %lu", tb_vector_size(self)); // done tb_char_t cstr[4096]; tb_for_all (tb_pointer_t, data, self) { // trace if (vector->element.cstr) { tb_trace_i(" %s", vector->element.cstr(&vector->element, data, cstr, sizeof(cstr))); } else { tb_trace_i(" %p", data); } } } #endif tbox-1.6.7/src/tbox/container/vector.h 0000664 0000000 0000000 00000021617 14142237372 0017715 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file vector.h * @ingroup container * */ #ifndef TB_CONTAINER_VECTOR_H #define TB_CONTAINER_VECTOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "element.h" #include "iterator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the vector ref type * *
* vector: |-----|--------------------------------------------------------|------| * head last tail * * performance: * * insert: * insert midd: slow * insert head: slow * insert tail: fast * * ninsert: * ninsert midd: fast * ninsert head: fast * ninsert tail: fast * * remove: * remove midd: slow * remove head: slow * remove last: fast * * nremove: * nremove midd: fast * nremove head: fast * nremove last: fast * * iterator: * next: fast * prev: fast ** * @note the itor of the same item is mutable * */ typedef tb_iterator_ref_t tb_vector_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init vector * * @code * // init vector tb_vector_ref_t vector = tb_vector_init(0, tb_element_str(tb_true)); if (vector) { // insert elements into head tb_vector_insert_head(vector, "hi!"); // insert elements into tail tb_vector_insert_tail(vector, "how"); tb_vector_insert_tail(vector, "are"); tb_vector_insert_tail(vector, "you"); // dump elements tb_for_all (tb_char_t const*, cstr, vector) { // trace tb_trace_d("%s", cstr); } // exit vector tb_vector_exit(vector); } * @endcode * * @param grow the item grow * @param element the element * * @return the vector */ tb_vector_ref_t tb_vector_init(tb_size_t grow, tb_element_t element); /*! exist vector * * @param vector the vector */ tb_void_t tb_vector_exit(tb_vector_ref_t vector); /*! the vector data * * @param vector the vector * * @return the vector data */ tb_pointer_t tb_vector_data(tb_vector_ref_t vector); /*! the vector head item * * @param vector the vector * * @return the vector head item */ tb_pointer_t tb_vector_head(tb_vector_ref_t vector); /*! the vector last item * * @param vector the vector * * @return the vector last item */ tb_pointer_t tb_vector_last(tb_vector_ref_t vector); /*! resize the vector * * @param vector the vector * @param size the vector size * * @return tb_true or tb_false */ tb_bool_t tb_vector_resize(tb_vector_ref_t vector, tb_size_t size); /*! clear the vector * * @param vector the vector */ tb_void_t tb_vector_clear(tb_vector_ref_t vector); /*! copy the vector * * @param vector the vector * @param copy the copied vector */ tb_void_t tb_vector_copy(tb_vector_ref_t vector, tb_vector_ref_t copy); /*! insert the vector prev item * * @param vector the vector * @param itor the item itor * @param data the item data */ tb_void_t tb_vector_insert_prev(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data); /*! insert the vector next item * * @param vector the vector * @param itor the item itor * @param data the item data */ tb_void_t tb_vector_insert_next(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data); /*! insert the vector head item * * @param vector the vector * @param data the item data */ tb_void_t tb_vector_insert_head(tb_vector_ref_t vector, tb_cpointer_t data); /*! insert the vector tail item * * @param vector the vector * @param data the item data */ tb_void_t tb_vector_insert_tail(tb_vector_ref_t vector, tb_cpointer_t data); /*! insert the vector prev items * * @param vector the vector * @param itor the item itor * @param data the item data * @param size the item count */ tb_void_t tb_vector_ninsert_prev(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data, tb_size_t size); /*! insert the vector next items * * @param vector the vector * @param itor the item itor * @param data the item data * @param size the item count */ tb_void_t tb_vector_ninsert_next(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data, tb_size_t size); /*! insert the vector head items * * @param vector the vector * @param data the item data * @param size the item count */ tb_void_t tb_vector_ninsert_head(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size); /*! insert the vector tail items * * @param vector the vector * @param data the item data * @param size the item count */ tb_void_t tb_vector_ninsert_tail(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size); /*! replace the vector item * * @param vector the vector * @param itor the item itor * @param data the item data */ tb_void_t tb_vector_replace(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data); /*! replace the vector head item * * @param vector the vector * @param data the item data */ tb_void_t tb_vector_replace_head(tb_vector_ref_t vector, tb_cpointer_t data); /*! replace the vector last item * * @param vector the vector * @param data the item data */ tb_void_t tb_vector_replace_last(tb_vector_ref_t vector, tb_cpointer_t data); /*! replace the vector items * * @param vector the vector * @param itor the item itor * @param data the item data * @param size the item count */ tb_void_t tb_vector_nreplace(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data, tb_size_t size); /*! replace the vector head items * * @param vector the vector * @param data the item data * @param size the item count */ tb_void_t tb_vector_nreplace_head(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size); /*! replace the vector last items * * @param vector the vector * @param data the item data * @param size the item count */ tb_void_t tb_vector_nreplace_last(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size); /*! remove the vector item * * @param vector the vector * @param itor the item itor */ tb_void_t tb_vector_remove(tb_vector_ref_t vector, tb_size_t itor); /*! remove the vector head item * * @param vector the vector */ tb_void_t tb_vector_remove_head(tb_vector_ref_t vector); /*! remove the vector last item * * @param vector the vector */ tb_void_t tb_vector_remove_last(tb_vector_ref_t vector); /*! remove the vector items * * @param vector the vector * @param itor the item itor * @param size the item count */ tb_void_t tb_vector_nremove(tb_vector_ref_t vector, tb_size_t itor, tb_size_t size); /*! remove the vector head items * * @param vector the vector * @param size the item count */ tb_void_t tb_vector_nremove_head(tb_vector_ref_t vector, tb_size_t size); /*! remove the vector last items * * @param vector the vector * @param size the item count */ tb_void_t tb_vector_nremove_last(tb_vector_ref_t vector, tb_size_t size); /*! the vector size * * @param vector the vector * * @return the vector size */ tb_size_t tb_vector_size(tb_vector_ref_t vector); /*! the vector grow * * @param vector the vector * * @return the vector grow */ tb_size_t tb_vector_grow(tb_vector_ref_t vector); /*! the vector maxn * * @param vector the vector * * @return the vector maxn */ tb_size_t tb_vector_maxn(tb_vector_ref_t vector); #ifdef __tb_debug__ /*! dump vector * * @param vector the vector */ tb_void_t tb_vector_dump(tb_vector_ref_t vector); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/ 0000775 0000000 0000000 00000000000 14142237372 0016260 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/coroutine/channel.c 0000664 0000000 0000000 00000032106 14142237372 0020036 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file channel.h * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "channel" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "channel.h" #include "coroutine.h" #include "scheduler.h" #include "impl/impl.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /* the channel queue type * * we do not use tb_circle_queue_t because it is too heavy */ typedef struct __tb_co_channel_queue_t { // the data tb_cpointer_t* data; // the head tb_size_t head; // the tail tb_size_t tail; // the maxn tb_size_t maxn; // the size tb_size_t size; }tb_co_channel_queue_t; // the coroutine channel type typedef struct __tb_co_channel_t { // the queue tb_co_channel_queue_t queue; // the free function tb_co_channel_free_func_t free; // the user private data tb_cpointer_t priv; // the waiting send coroutines tb_single_list_entry_head_t waiting_send; // the waiting recv coroutines tb_single_list_entry_head_t waiting_recv; }tb_co_channel_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t tb_co_channel_send_resume(tb_co_channel_t* channel, tb_pointer_t* pdata) { // check tb_assert(channel); // resume the first waiting send coroutine and recv data tb_bool_t ok = tb_false; if (tb_single_list_entry_size(&channel->waiting_send)) { // get the next entry from head tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&channel->waiting_send); tb_assert(entry); // remove it from the waiting send coroutines tb_single_list_entry_remove_head(&channel->waiting_send); // get the waiting send coroutine tb_coroutine_ref_t waiting = (tb_coroutine_ref_t)tb_single_list_entry(&channel->waiting_send, entry); // resume this coroutine and recv data tb_pointer_t data = tb_coroutine_resume(waiting, tb_null); // save data if (pdata) *pdata = data; // ok ok = tb_true; } // ok? return ok; } static tb_void_t tb_co_channel_recv_resume(tb_co_channel_t* channel) { // check tb_assert(channel); // resume the first waiting recv coroutine if (tb_single_list_entry_size(&channel->waiting_recv)) { // get the next entry from head tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&channel->waiting_recv); tb_assert(entry); // remove it from the waiting recv coroutines tb_single_list_entry_remove_head(&channel->waiting_recv); // get the waiting recv coroutine tb_coroutine_ref_t waiting = (tb_coroutine_ref_t)tb_single_list_entry(&channel->waiting_recv, entry); // resume this coroutine tb_coroutine_resume(waiting, tb_null); } } static tb_void_t tb_co_channel_send_suspend(tb_co_channel_t* channel, tb_cpointer_t data) { // check tb_assert(channel); // get the running coroutine tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self(); tb_assert(running); // save this coroutine to the waiting send coroutines tb_single_list_entry_insert_tail(&channel->waiting_send, &running->rs.single_entry); // send data and wait it tb_coroutine_suspend(data); } static tb_void_t tb_co_channel_recv_suspend(tb_co_channel_t* channel) { // check tb_assert(channel); // get the running coroutine tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self(); tb_assert(running); // save this coroutine to the waiting recv coroutines tb_single_list_entry_insert_tail(&channel->waiting_recv, &running->rs.single_entry); // wait data tb_coroutine_suspend(tb_null); } static tb_void_t tb_co_channel_send_buffer(tb_co_channel_t* channel, tb_cpointer_t data) { // check tb_assert_and_check_return(channel && channel->queue.data); // done do { // put data into queue if be not full if (channel->queue.size + 1 < channel->queue.maxn) { // trace tb_trace_d("send[%p]: put data(%p)", tb_coroutine_self(), data); // put data channel->queue.data[channel->queue.tail] = data; channel->queue.tail = (channel->queue.tail + 1) % channel->queue.maxn; channel->queue.size++; // notify to recv data tb_co_channel_recv_resume(channel); // send ok break; } // wait it if be full else { // trace tb_trace_d("send[%p]: wait ..", tb_coroutine_self()); // wait send tb_co_channel_send_suspend(channel, tb_null); // trace tb_trace_d("send[%p]: wait ok", tb_coroutine_self()); } } while (1); // trace tb_trace_d("send[%p]: ok", tb_coroutine_self()); } static tb_pointer_t tb_co_channel_recv_buffer(tb_co_channel_t* channel) { // check tb_assert_and_check_return_val(channel && channel->queue.data, tb_null); // done tb_pointer_t data = tb_null; do { // recv data from channel if be not null if (channel->queue.size) { // get data data = (tb_pointer_t)channel->queue.data[channel->queue.head]; // pop data channel->queue.head = (channel->queue.head + 1) % channel->queue.maxn; channel->queue.size--; // trace tb_trace_d("recv[%p]: get data(%p)", tb_coroutine_self(), data); // notify to send data tb_co_channel_send_resume(channel, tb_null); // recv ok break; } // wait it if be null else { // trace tb_trace_d("recv[%p]: wait ..", tb_coroutine_self()); // wait recv tb_co_channel_recv_suspend(channel); // trace tb_trace_d("recv[%p]: wait ok", tb_coroutine_self()); } } while (1); // trace tb_trace_d("recv[%p]: ok", tb_coroutine_self()); // get data return data; } static tb_bool_t tb_co_channel_send_buffer_try(tb_co_channel_t* channel, tb_cpointer_t data) { // check tb_assert_and_check_return_val(channel && channel->queue.data, tb_false); // put data into queue if be not full if (channel->queue.size + 1 < channel->queue.maxn) { // trace tb_trace_d("send[%p]: put data(%p)", tb_coroutine_self(), data); // put data channel->queue.data[channel->queue.tail] = data; channel->queue.tail = (channel->queue.tail + 1) % channel->queue.maxn; channel->queue.size++; // notify to recv data tb_co_channel_recv_resume(channel); // send ok return tb_true; } // failed return tb_false; } static tb_bool_t tb_co_channel_recv_buffer_try(tb_co_channel_t* channel, tb_pointer_t* pdata) { // check tb_assert_and_check_return_val(channel && channel->queue.data && pdata, tb_false); // recv data from channel if be not null if (channel->queue.size) { // get data *pdata = (tb_pointer_t)channel->queue.data[channel->queue.head]; // pop data channel->queue.head = (channel->queue.head + 1) % channel->queue.maxn; channel->queue.size--; // trace tb_trace_d("recv[%p]: get data(%p)", tb_coroutine_self(), *pdata); // notify to send data tb_co_channel_send_resume(channel, tb_null); // recv ok return tb_true; } // failed return tb_false; } static tb_void_t tb_co_channel_send_buffer0(tb_co_channel_t* channel, tb_cpointer_t data) { // check tb_assert(channel); // resume one waiting recv coroutine tb_co_channel_recv_resume(channel); // send data and wait it tb_co_channel_send_suspend(channel, data); } static tb_pointer_t tb_co_channel_recv_buffer0(tb_co_channel_t* channel) { // check tb_assert(channel); // done tb_pointer_t data = tb_null; do { // resume the first waiting send coroutine and recv data if (tb_co_channel_send_resume(channel, &data)) { // recv ok break; } // no data? else { // wait data tb_co_channel_recv_suspend(channel); } } while (1); // ok? return data; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_co_channel_ref_t tb_co_channel_init(tb_size_t size, tb_co_channel_free_func_t free, tb_cpointer_t priv) { // done tb_bool_t ok = tb_false; tb_co_channel_t* channel = tb_null; do { // make channel channel = tb_malloc0_type(tb_co_channel_t); tb_assert_and_check_break(channel); // init waiting send coroutines tb_single_list_entry_init(&channel->waiting_send, tb_coroutine_t, rs.single_entry, tb_null); // init waiting recv coroutines tb_single_list_entry_init(&channel->waiting_recv, tb_coroutine_t, rs.single_entry, tb_null); // init free function and data channel->free = free; channel->priv = priv; // with buffer? if (size) { // init maxn, + tail channel->queue.maxn = size + 1; // make data channel->queue.data = tb_nalloc_type(channel->queue.maxn, tb_cpointer_t); tb_assert_and_check_break(channel->queue.data); } // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (channel) tb_co_channel_exit((tb_co_channel_ref_t)channel); channel = tb_null; } // ok? return (tb_co_channel_ref_t)channel; } tb_void_t tb_co_channel_exit(tb_co_channel_ref_t self) { // check tb_co_channel_t* channel = (tb_co_channel_t*)self; tb_assert_and_check_return(channel); // exit queue if (channel->queue.data) { // free data if (channel->free) { tb_size_t head = channel->queue.head; tb_size_t maxn = channel->queue.maxn; tb_size_t size = channel->queue.size; while (size--) { channel->free((tb_pointer_t)channel->queue.data[head], channel->priv); head = (head + 1) % maxn; } } // free it tb_free(channel->queue.data); } channel->queue.data = tb_null; channel->queue.size = 0; // check waiting coroutines tb_assert(!tb_single_list_entry_size(&channel->waiting_send)); tb_assert(!tb_single_list_entry_size(&channel->waiting_recv)); // exit waiting coroutines tb_single_list_entry_exit(&channel->waiting_send); tb_single_list_entry_exit(&channel->waiting_recv); // exit the channel tb_free(channel); } tb_void_t tb_co_channel_send(tb_co_channel_ref_t self, tb_cpointer_t data) { // check tb_co_channel_t* channel = (tb_co_channel_t*)self; tb_assert_and_check_return(channel); // send it if (channel->queue.data) tb_co_channel_send_buffer(channel, data); else tb_co_channel_send_buffer0(channel, data); } tb_pointer_t tb_co_channel_recv(tb_co_channel_ref_t self) { // check tb_co_channel_t* channel = (tb_co_channel_t*)self; tb_assert_and_check_return_val(channel, tb_null); // recv it return channel->queue.data? tb_co_channel_recv_buffer(channel) : tb_co_channel_recv_buffer0(channel); } tb_bool_t tb_co_channel_send_try(tb_co_channel_ref_t self, tb_cpointer_t data) { // check tb_co_channel_t* channel = (tb_co_channel_t*)self; tb_assert_and_check_return_val(channel, tb_false); // try sending it return channel->queue.data? tb_co_channel_send_buffer_try(channel, data) : tb_false; } tb_bool_t tb_co_channel_recv_try(tb_co_channel_ref_t self, tb_pointer_t* pdata) { // check tb_co_channel_t* channel = (tb_co_channel_t*)self; tb_assert_and_check_return_val(channel && pdata, tb_false); // try recving it return channel->queue.data? tb_co_channel_recv_buffer_try(channel, pdata) : tb_false; } tbox-1.6.7/src/tbox/coroutine/channel.h 0000664 0000000 0000000 00000006457 14142237372 0020055 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file channel.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_CHANNEL_H #define TB_COROUTINE_CHANNEL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the coroutine channel ref type typedef __tb_typeref__(co_channel); /*! the free function type * * @param data the channel data * @param priv the user private data */ typedef tb_void_t (*tb_co_channel_free_func_t)(tb_pointer_t data, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init channel * * @param size the buffer size, 0: no buffer * @param free the free function * @param priv the user private data * * @return the channel */ tb_co_channel_ref_t tb_co_channel_init(tb_size_t size, tb_co_channel_free_func_t free, tb_cpointer_t priv); /*! exit channel * * @param channel the channel */ tb_void_t tb_co_channel_exit(tb_co_channel_ref_t channel); /*! send data into channel * * the current coroutine will be suspend if this channel is full * * @param channel the channel * @param data the channel data */ tb_void_t tb_co_channel_send(tb_co_channel_ref_t channel, tb_cpointer_t data); /*! recv data from channel * * the current coroutine will be suspend if no data * * @param channel the channel * * @return the channel data */ tb_pointer_t tb_co_channel_recv(tb_co_channel_ref_t channel); /*! try sending data into channel only with buffer * * the current coroutine will be suspend if this channel is full * * @param channel the channel * @param data the channel data * * @return tb_true or tb_false */ tb_bool_t tb_co_channel_send_try(tb_co_channel_ref_t channel, tb_cpointer_t data); /*! try recving data from channel only with buffer * * the current coroutine will be suspend if no data * * @param channel the channel * @param pdata the channel data pointer * * @return tb_true or tb_false */ tb_bool_t tb_co_channel_recv_try(tb_co_channel_ref_t channel, tb_pointer_t* pdata); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/coroutine.c 0000664 0000000 0000000 00000006753 14142237372 0020446 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file coroutine.h * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "coroutine" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "coroutine.h" #include "scheduler.h" #include "impl/impl.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_coroutine_start(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) { // check tb_assert_and_check_return_val(func, tb_false); // start it return tb_co_scheduler_start((tb_co_scheduler_t*)scheduler, func, priv, stacksize); } tb_bool_t tb_coroutine_yield() { // get current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // yield the current coroutine return scheduler? tb_co_scheduler_yield(scheduler) : tb_false; } tb_pointer_t tb_coroutine_resume(tb_coroutine_ref_t coroutine, tb_cpointer_t priv) { // get current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // resume the given coroutine return scheduler? tb_co_scheduler_resume(scheduler, (tb_coroutine_t*)coroutine, priv) : tb_null; } tb_pointer_t tb_coroutine_suspend(tb_cpointer_t priv) { // get current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // suspend the current coroutine return scheduler? tb_co_scheduler_suspend(scheduler, priv) : tb_null; } tb_pointer_t tb_coroutine_sleep(tb_long_t interval) { // get current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // sleep the current coroutine return scheduler? tb_co_scheduler_sleep(scheduler, interval) : tb_null; } tb_long_t tb_coroutine_waitio(tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout) { // get current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // wait events return scheduler? tb_co_scheduler_wait(scheduler, object, events, timeout) : -1; } tb_long_t tb_coroutine_waitproc(tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout) { // get current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // wait process status return scheduler? tb_co_scheduler_wait_proc(scheduler, object, pstatus, timeout) : -1; } tb_coroutine_ref_t tb_coroutine_self() { // get coroutine tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // get running coroutine return scheduler? (tb_coroutine_ref_t)tb_co_scheduler_running(scheduler) : tb_null; } tbox-1.6.7/src/tbox/coroutine/coroutine.h 0000664 0000000 0000000 00000007755 14142237372 0020456 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file coroutine.h * @defgroup coroutine * */ #ifndef TB_COROUTINE_H #define TB_COROUTINE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "lock.h" #include "channel.h" #include "semaphore.h" #include "scheduler.h" #include "../platform/poller.h" #include "stackless/stackless.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the coroutine ref type typedef __tb_typeref__(coroutine); /// the coroutine function type typedef tb_void_t (*tb_coroutine_func_t)(tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! start coroutine * * @param scheduler the scheduler, uses the current scheduler if be null * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param stacksize the stack size * * @return tb_true or tb_false */ tb_bool_t tb_coroutine_start(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); /*! yield the current coroutine * * @return tb_true(yield ok) or tb_false(yield failed, no more coroutines) */ tb_bool_t tb_coroutine_yield(tb_noarg_t); /*! resume the given coroutine (suspended) * * @param coroutine the suspended coroutine * @param priv the user private data as the return value of suspend() or sleep() * * @return the user private data from suspend(priv) */ tb_pointer_t tb_coroutine_resume(tb_coroutine_ref_t coroutine, tb_cpointer_t priv); /*! suspend the current coroutine * * @param priv the user private data as the return value of resume() * * @return the user private data from resume(priv) */ tb_pointer_t tb_coroutine_suspend(tb_cpointer_t priv); /*! sleep some times (ms) * * @param interval the interval (ms), infinity: -1 * * @return the user private data from resume(priv) */ tb_pointer_t tb_coroutine_sleep(tb_long_t interval); /*! wait io events * * @param object the poller object * @param events the waited events, will remove this object from io scheduler if be TB_SOCKET_EVENT_NONE * @param timeout the timeout, infinity: -1 * * @return > 0: the events, 0: timeout, -1: failed */ tb_long_t tb_coroutine_waitio(tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout); /*! wait process status * * @param object the poller object * @param pstatus the process exited status pointer, maybe null * @param timeout the timeout, infinity: -1 * * @return > 0: process exited, 0: timeout, -1: failed */ tb_long_t tb_coroutine_waitproc(tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout); /*! get the current coroutine * * @return the current coroutine */ tb_coroutine_ref_t tb_coroutine_self(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/ 0000775 0000000 0000000 00000000000 14142237372 0017221 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/coroutine/impl/coroutine.c 0000664 0000000 0000000 00000021104 14142237372 0021372 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file coroutine.h * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "coroutine" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "coroutine.h" #include "scheduler.h" #include "../../memory/memory.h" #if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER) # include "valgrind/valgrind.h" #endif /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the stack guard magic #define TB_COROUTINE_STACK_GUARD (0xbeef) // the default stack size, @note we will allocate it from large/virtual allocator if size >= TB_VIRTUAL_MEMORY_DATA_MINN #define TB_COROUTINE_STACK_DEFSIZE TB_VIRTUAL_MEMORY_DATA_MINN /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_void_t tb_coroutine_entry(tb_context_from_t from) { // get the from-coroutine tb_coroutine_t* coroutine_from = (tb_coroutine_t*)from.priv; tb_assert(coroutine_from && from.context); // update the context coroutine_from->context = from.context; tb_assert(from.context); // get the current coroutine tb_coroutine_t* coroutine = (tb_coroutine_t*)tb_coroutine_self(); tb_assert(coroutine); // trace tb_trace_d("entry: %p stack: %p - %p from coroutine(%p)", coroutine, coroutine->stackbase - coroutine->stacksize, coroutine->stackbase, coroutine_from); #ifdef __tb_debug__ // check it tb_coroutine_check(coroutine); #endif // get function and private data tb_coroutine_func_t func = coroutine->rs.func.func; tb_cpointer_t priv = coroutine->rs.func.priv; tb_assert(func); // reset rs data first for waiting io tb_memset(&coroutine->rs, 0, sizeof(coroutine->rs)); // call the coroutine function func(priv); // finish the current coroutine and switch to the other coroutine tb_co_scheduler_finish((tb_co_scheduler_t*)tb_co_scheduler_self()); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_coroutine_t* tb_coroutine_init(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) { // check tb_assert_and_check_return_val(scheduler && func, tb_null); // done tb_bool_t ok = tb_false; tb_coroutine_t* coroutine = tb_null; do { // init stack size if (!stacksize) stacksize = TB_COROUTINE_STACK_DEFSIZE; #ifdef __tb_debug__ // patch debug stack size for (assert, trace ..) stacksize <<= 1; #endif /* make coroutine * * TODO: * * - segment stack * * ----------------------------------------------- * | coroutine | guard | ... stacksize ... | guard | * ----------------------------------------------- */ coroutine = (tb_coroutine_t*)tb_malloc_bytes(sizeof(tb_coroutine_t) + stacksize + sizeof(tb_uint16_t)); tb_assert_and_check_break(coroutine); // save scheduler coroutine->scheduler = scheduler; // init stack coroutine->stackbase = (tb_byte_t*)&(coroutine[1]) + stacksize; coroutine->stacksize = stacksize; // fill guard coroutine->guard = TB_COROUTINE_STACK_GUARD; tb_bits_set_u16_ne(coroutine->stackbase, TB_COROUTINE_STACK_GUARD); // init function and user private data coroutine->rs.func.func = func; coroutine->rs.func.priv = priv; // make context coroutine->context = tb_context_make(coroutine->stackbase - stacksize, stacksize, tb_coroutine_entry); tb_assert_and_check_break(coroutine->context); #if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER) // register valgrind stack coroutine->valgrind_stack_id = VALGRIND_STACK_REGISTER(coroutine->stackbase - stacksize, coroutine->stackbase); #endif #ifdef __tb_debug__ // check it tb_coroutine_check(coroutine); #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (coroutine) tb_coroutine_exit(coroutine); coroutine = tb_null; } // trace tb_trace_d("init %p", coroutine); // ok? return coroutine; } tb_coroutine_t* tb_coroutine_reinit(tb_coroutine_t* coroutine, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) { // check tb_assert_and_check_return_val(coroutine && func, tb_null); // done tb_bool_t ok = tb_false; do { // init stack size if (!stacksize) stacksize = TB_COROUTINE_STACK_DEFSIZE; #ifdef __tb_debug__ // patch debug stack size for (assert, trace ..) stacksize <<= 1; // check coroutine tb_coroutine_check(coroutine); #endif #if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER) // deregister valgrind stack VALGRIND_STACK_DEREGISTER(coroutine->valgrind_stack_id); #endif // remake coroutine if (stacksize > coroutine->stacksize) coroutine = (tb_coroutine_t*)tb_ralloc_bytes(coroutine, sizeof(tb_coroutine_t) + stacksize + sizeof(tb_uint16_t)); else stacksize = coroutine->stacksize; tb_assert_and_check_break(coroutine && coroutine->scheduler); // init stack coroutine->stackbase = (tb_byte_t*)&(coroutine[1]) + stacksize; coroutine->stacksize = stacksize; // fill guard coroutine->guard = TB_COROUTINE_STACK_GUARD; tb_bits_set_u16_ne(coroutine->stackbase, TB_COROUTINE_STACK_GUARD); // init function and user private data coroutine->rs.func.func = func; coroutine->rs.func.priv = priv; // make context coroutine->context = tb_context_make(coroutine->stackbase - stacksize, stacksize, tb_coroutine_entry); tb_assert_and_check_break(coroutine->context); #if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER) // re-register valgrind stack coroutine->valgrind_stack_id = VALGRIND_STACK_REGISTER(coroutine->stackbase - stacksize, coroutine->stackbase); #endif // ok ok = tb_true; } while (0); // failed? reset it if (!ok) coroutine = tb_null; // trace tb_trace_d("reinit %p", coroutine); // ok? return coroutine; } tb_void_t tb_coroutine_exit(tb_coroutine_t* coroutine) { // check tb_assert_and_check_return(coroutine); // trace tb_trace_d("exit: %p", coroutine); #ifdef __tb_debug__ // check it tb_coroutine_check(coroutine); #endif #if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER) // deregister valgrind stack VALGRIND_STACK_DEREGISTER(coroutine->valgrind_stack_id); #endif // exit it tb_free(coroutine); } #ifdef __tb_debug__ tb_void_t tb_coroutine_check(tb_coroutine_t* coroutine) { // check tb_assert(coroutine); // this coroutine is original for scheduler? tb_check_return(!tb_coroutine_is_original(coroutine)); // check stack underflow if (coroutine->guard != TB_COROUTINE_STACK_GUARD) { // trace tb_trace_e("this coroutine stack is underflow!"); // dump stack tb_dump_data((tb_byte_t const*)coroutine, sizeof(tb_coroutine_t)); // abort tb_abort(); } // check stack overflow if (tb_bits_get_u16_ne(coroutine->stackbase) != TB_COROUTINE_STACK_GUARD) { // trace tb_trace_e("this coroutine stack is overflow!"); // dump stack tb_dump_data(coroutine->stackbase - 64, 64 + 2); // abort tb_abort(); } // check tb_assert(coroutine->context); } #endif tbox-1.6.7/src/tbox/coroutine/impl/coroutine.h 0000664 0000000 0000000 00000011726 14142237372 0021410 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file coroutine.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_IMPL_COROUTINE_H #define TB_COROUTINE_IMPL_COROUTINE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // get scheduler #define tb_coroutine_scheduler(coroutine) ((coroutine)->scheduler) // is original? #define tb_coroutine_is_original(coroutine) ((coroutine)->scheduler == (tb_co_scheduler_ref_t)(coroutine)) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the coroutine function type typedef struct __tb_coroutine_rs_func_t { // the function tb_coroutine_func_t func; // the user private data as the argument of function tb_cpointer_t priv; }tb_coroutine_rs_func_t; // the coroutine wait type typedef struct __tb_coroutine_rs_wait_t { // the waited poller object tb_poller_object_t object; // the timer task pointer for ltimer or timer tb_cpointer_t task; // the process status tb_int_t proc_status; // has pending process status? tb_uint16_t proc_pending : 1; // waiting process? tb_uint16_t proc_waiting : 1; // is ltimer? tb_uint16_t is_ltimer : 1; }tb_coroutine_rs_wait_t; // the coroutine type typedef struct __tb_coroutine_t { /* the list entry for ready, suspend and dead lists * * be placed in the head for optimization */ tb_list_entry_t entry; // the scheduler tb_co_scheduler_ref_t scheduler; // the context tb_context_ref_t context; // the stack base (top) tb_byte_t* stackbase; // the stack size tb_size_t stacksize; // the passed user private data between priv = resume(priv) and priv = suspend(priv) tb_cpointer_t rs_priv; // the passed private data between resume() and suspend() union { // the function tb_coroutine_rs_func_t func; // the arguments for wait() tb_coroutine_rs_wait_t wait; // the single entry tb_single_list_entry_t single_entry; } rs; // the guard tb_uint16_t guard; #if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER) // the valgrind stack id, helo valgrind to understand coroutine tb_uint_t valgrind_stack_id; #endif }tb_coroutine_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init coroutine * * @param scheduler the scheduler * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param stacksize the stack size, uses the default stack size if be zero * * @return the coroutine */ tb_coroutine_t* tb_coroutine_init(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); /* reinit the given coroutine * * @param coroutine the coroutine * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param stacksize the stack size, uses the default stack size if be zero * * @return the coroutine */ tb_coroutine_t* tb_coroutine_reinit(tb_coroutine_t* coroutine, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); /* exit coroutine * * @param coroutine the coroutine */ tb_void_t tb_coroutine_exit(tb_coroutine_t* coroutine); #ifdef __tb_debug__ /* check coroutine * * @param coroutine the coroutine */ tb_void_t tb_coroutine_check(tb_coroutine_t* coroutine); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/impl.h 0000664 0000000 0000000 00000001743 14142237372 0020340 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file impl.h * */ #ifndef TB_COROUTINE_IMPL_H #define TB_COROUTINE_IMPL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "coroutine.h" #include "scheduler.h" #include "scheduler_io.h" #include "stackless/stackless.h" #endif tbox-1.6.7/src/tbox/coroutine/impl/prefix.h 0000664 0000000 0000000 00000002060 14142237372 0020665 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_COROUTINE_IMPL_PREFIX_H #define TB_COROUTINE_IMPL_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../coroutine.h" #include "../../libc/libc.h" #include "../../utils/utils.h" #include "../../platform/platform.h" #include "../../container/container.h" #endif tbox-1.6.7/src/tbox/coroutine/impl/scheduler.c 0000664 0000000 0000000 00000031025 14142237372 0021344 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler.c * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "scheduler" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "scheduler.h" #include "coroutine.h" #include "scheduler_io.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the dead cache maximum count #ifdef __tb_small__ # define TB_SCHEDULER_DEAD_CACHE_MAXN (64) #else # define TB_SCHEDULER_DEAD_CACHE_MAXN (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_void_t tb_co_scheduler_make_dead(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) { // check tb_assert(scheduler && coroutine); // cannot be original coroutine tb_assert(!tb_coroutine_is_original(coroutine)); // remove this coroutine from the ready coroutines tb_list_entry_remove(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine); // append this coroutine to dead coroutines tb_list_entry_insert_tail(&scheduler->coroutines_dead, (tb_list_entry_ref_t)coroutine); } static tb_void_t tb_co_scheduler_make_ready(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) { // check tb_assert(scheduler && coroutine); // insert this coroutine to ready coroutines if (__tb_unlikely__(tb_coroutine_is_original(scheduler->running))) { // .. last -> coroutine(inserted) tb_list_entry_insert_tail(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine); } else { // .. -> coroutine(inserted) -> running -> .. tb_list_entry_insert_prev(&scheduler->coroutines_ready, (tb_list_entry_ref_t)scheduler->running, (tb_list_entry_ref_t)coroutine); } } static tb_void_t tb_co_scheduler_make_suspend(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) { // check tb_assert(scheduler && coroutine); // cannot be original coroutine tb_assert(!tb_coroutine_is_original(coroutine)); // remove this coroutine from the ready coroutines tb_list_entry_remove(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine); // append this coroutine to suspend coroutines tb_list_entry_insert_tail(&scheduler->coroutines_suspend, (tb_list_entry_ref_t)coroutine); } static __tb_inline__ tb_coroutine_t* tb_co_scheduler_next_ready(tb_co_scheduler_t* scheduler) { // check tb_assert(scheduler && scheduler->running && tb_list_entry_size(&scheduler->coroutines_ready)); // get the next entry tb_list_entry_ref_t entry_next = tb_list_entry_next((tb_list_entry_ref_t)scheduler->running); tb_assert(entry_next); // is list header? skip it and get the first entry if (entry_next == (tb_list_entry_ref_t)&scheduler->coroutines_ready) entry_next = tb_list_entry_next(entry_next); // get the next ready coroutine return (tb_coroutine_t*)tb_list_entry0(entry_next); } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_co_scheduler_start(tb_co_scheduler_t* scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) { // check tb_assert(func); // done tb_bool_t ok = tb_false; tb_coroutine_t* coroutine = tb_null; do { // trace tb_trace_d("start .."); // uses the current scheduler if be null if (!scheduler) scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); tb_assert_and_check_break(scheduler); // have been stopped? do not continue to start new coroutines tb_check_break(!scheduler->stopped); // reuses dead coroutines in init function if (tb_list_entry_size(&scheduler->coroutines_dead)) { // get the next entry from head tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); tb_assert_and_check_break(entry); // remove it from the ready coroutines tb_list_entry_remove_head(&scheduler->coroutines_dead); // get the dead coroutine tb_coroutine_t* coroutine_dead = (tb_coroutine_t*)tb_list_entry0(entry); // reinit this coroutine coroutine = tb_coroutine_reinit(coroutine_dead, func, priv, stacksize); // failed? exit this coroutine if (!coroutine) tb_coroutine_exit(coroutine_dead); } // init coroutine if (!coroutine) coroutine = tb_coroutine_init((tb_co_scheduler_ref_t)scheduler, func, priv, stacksize); tb_assert_and_check_break(coroutine); // ready coroutine tb_co_scheduler_make_ready(scheduler, coroutine); // the dead coroutines is too much? free some coroutines while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN) { // get the next entry from head tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); tb_assert(entry); // remove it from the ready coroutines tb_list_entry_remove_head(&scheduler->coroutines_dead); // exit this coroutine tb_coroutine_exit((tb_coroutine_t*)tb_list_entry0(entry)); } // ok ok = tb_true; } while (0); // trace tb_trace_d("start %s", ok? "ok" : "no"); // ok? return ok; } tb_bool_t tb_co_scheduler_yield(tb_co_scheduler_t* scheduler) { // check tb_assert(scheduler && scheduler->running); tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); // trace tb_trace_d("yield coroutine(%p)", scheduler->running); #ifdef __tb_debug__ // check it tb_coroutine_check(scheduler->running); #endif // get the next ready coroutine tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler); if (coroutine_next != scheduler->running) { // switch to the next coroutine tb_co_scheduler_switch(scheduler, coroutine_next); // ok return tb_true; } // no more coroutine (only running)? else { // trace tb_trace_d("continue to run current coroutine(%p)", tb_coroutine_self()); // check tb_assert((tb_list_entry_ref_t)scheduler->running == tb_list_entry_head(&scheduler->coroutines_ready)); } // return it directly and continue to run this coroutine return tb_false; } tb_pointer_t tb_co_scheduler_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv) { // check tb_assert(scheduler && coroutine); // trace tb_trace_d("resume coroutine(%p)", coroutine); // remove it from the suspend coroutines tb_list_entry_remove(&scheduler->coroutines_suspend, (tb_list_entry_ref_t)coroutine); // get the passed private data from suspend(priv) tb_pointer_t retval = (tb_pointer_t)coroutine->rs_priv; // pass the user private data to suspend() coroutine->rs_priv = priv; // make it as ready tb_co_scheduler_make_ready(scheduler, coroutine); // return it return retval; } tb_pointer_t tb_co_scheduler_suspend(tb_co_scheduler_t* scheduler, tb_cpointer_t priv) { // check tb_assert(scheduler && scheduler->running); tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); // have been stopped? return it directly tb_check_return_val(!scheduler->stopped, tb_null); // trace tb_trace_d("suspend coroutine(%p)", scheduler->running); #ifdef __tb_debug__ // check it tb_coroutine_check(scheduler->running); #endif // pass the private data to resume() first scheduler->running->rs_priv = priv; // get the next ready coroutine first tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler); // make the running coroutine as suspend tb_co_scheduler_make_suspend(scheduler, scheduler->running); // switch to next coroutine if (coroutine_next != scheduler->running) tb_co_scheduler_switch(scheduler, coroutine_next); // no more coroutine? else { // trace tb_trace_d("switch to original coroutine"); // switch to the original coroutine tb_co_scheduler_switch(scheduler, &scheduler->original); } // check tb_assert(scheduler->running); // return the user private data from resume(priv) return (tb_pointer_t)scheduler->running->rs_priv; } tb_void_t tb_co_scheduler_finish(tb_co_scheduler_t* scheduler) { // check tb_assert(scheduler && scheduler->running); tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); // trace tb_trace_d("finish coroutine(%p)", scheduler->running); #ifdef __tb_debug__ // check it tb_coroutine_check(scheduler->running); #endif // get the next ready coroutine first tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler); // make the running coroutine as dead tb_co_scheduler_make_dead(scheduler, scheduler->running); // switch to next coroutine if (coroutine_next != scheduler->running) tb_co_scheduler_switch(scheduler, coroutine_next); // no more coroutine? else { // trace tb_trace_d("switch to original coroutine"); // switch to the original coroutine tb_co_scheduler_switch(scheduler, &scheduler->original); } } tb_pointer_t tb_co_scheduler_sleep(tb_co_scheduler_t* scheduler, tb_long_t interval) { // check tb_assert(scheduler && scheduler->running); tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); // have been stopped? return it directly tb_check_return_val(!scheduler->stopped, tb_null); // need io scheduler if (!tb_co_scheduler_io_need(scheduler)) return tb_null; // sleep it return tb_co_scheduler_io_sleep(scheduler->scheduler_io, interval); } tb_void_t tb_co_scheduler_switch(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) { // check tb_assert(scheduler && scheduler->running); tb_assert(coroutine && coroutine->context); // the current running coroutine tb_coroutine_t* running = scheduler->running; // mark the given coroutine as running scheduler->running = coroutine; // trace tb_trace_d("switch to coroutine(%p) from coroutine(%p)", coroutine, running); // jump to the given coroutine tb_context_from_t from = tb_context_jump(coroutine->context, running); // the from-coroutine tb_coroutine_t* coroutine_from = (tb_coroutine_t*)from.priv; tb_assert(coroutine_from && from.context); #ifdef __tb_debug__ // check it tb_coroutine_check(coroutine_from); #endif // update the context coroutine_from->context = from.context; } tb_long_t tb_co_scheduler_wait(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout) { // check tb_assert(scheduler && scheduler->running); tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); // have been stopped? return it directly tb_check_return_val(!scheduler->stopped, -1); // need io scheduler if (!tb_co_scheduler_io_need(scheduler)) return -1; // wait it return tb_co_scheduler_io_wait(scheduler->scheduler_io, object, events, timeout); } tb_long_t tb_co_scheduler_wait_proc(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout) { // check tb_assert(scheduler && scheduler->running); tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); // have been stopped? return it directly tb_check_return_val(!scheduler->stopped, -1); // need io scheduler if (!tb_co_scheduler_io_need(scheduler)) return -1; // wait it return tb_co_scheduler_io_wait_proc(scheduler->scheduler_io, object, pstatus, timeout); } tbox-1.6.7/src/tbox/coroutine/impl/scheduler.h 0000664 0000000 0000000 00000014065 14142237372 0021356 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_IMPL_SCHEDULER_H #define TB_COROUTINE_IMPL_SCHEDULER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "coroutine.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // get the running coroutine #define tb_co_scheduler_running(scheduler) ((scheduler)->running) // get the ready coroutines count #define tb_co_scheduler_ready_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_ready) // get the suspended coroutines count #define tb_co_scheduler_suspend_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_suspend) // get the io scheduler #define tb_co_scheduler_io(scheduler) ((scheduler)->scheduler_io) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the io scheduler type struct __tb_co_scheduler_io_t; // the scheduler type typedef struct __tb_co_scheduler_t { /* the original coroutine (in main loop) * * coroutine->scheduler == (tb_co_scheduler_ref_t)coroutine */ tb_coroutine_t original; // is stopped tb_bool_t stopped; // the running coroutine tb_coroutine_t* running; // the io scheduler struct __tb_co_scheduler_io_t* scheduler_io; // the dead coroutines tb_list_entry_head_t coroutines_dead; /* the ready coroutines * * ready: head -> ready -> .. -> running -> .. -> ready -> ..-> * | | * ---------------------------<----------------------- */ tb_list_entry_head_t coroutines_ready; // the suspend coroutines tb_list_entry_head_t coroutines_suspend; }tb_co_scheduler_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* start the coroutine function * * @param scheduler the scheduler, uses the default scheduler if be null * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param stacksize the stack size * * @return tb_true or tb_false */ tb_bool_t tb_co_scheduler_start(tb_co_scheduler_t* scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); /* yield the current coroutine * * @param scheduler the scheduler * * @return tb_true(yield ok) or tb_false(yield failed, no more coroutines) */ tb_bool_t tb_co_scheduler_yield(tb_co_scheduler_t* scheduler); /*! resume the given coroutine (suspended) * * @param scheduler the scheduler * @param coroutine the suspended coroutine * @param priv the user private data as the return value of suspend() or sleep() * * @return the user private data from suspend(priv) */ tb_pointer_t tb_co_scheduler_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv); /* suspend the current coroutine * * @param scheduler the scheduler * @param priv the user private data as the return value of resume() * * @return the user private data from resume(priv) */ tb_pointer_t tb_co_scheduler_suspend(tb_co_scheduler_t* scheduler, tb_cpointer_t priv); /* finish the current coroutine * * @param scheduler the scheduler */ tb_void_t tb_co_scheduler_finish(tb_co_scheduler_t* scheduler); /* sleep the current coroutine * * @param scheduler the scheduler * @param interval the interval (ms), infinity: -1 * * @return the user private data from resume(priv) */ tb_pointer_t tb_co_scheduler_sleep(tb_co_scheduler_t* scheduler, tb_long_t interval); /* switch to the given coroutine * * @param scheduler the scheduler * @param coroutine the coroutine */ tb_void_t tb_co_scheduler_switch(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine); /* wait io events * * @param scheduler the scheduler * @param object the poller object * @param events the waited events * @param timeout the timeout, infinity: -1 * * @return > 0: the events, 0: timeout, -1: failed */ tb_long_t tb_co_scheduler_wait(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout); /* wait process status * * @param scheduler the scheduler * @param object the process poller object * @param pstatus the process exited status pointer, maybe null * @param timeout the timeout, infinity: -1 * * @return > 0: process exited, 0: timeout, -1: failed */ tb_long_t tb_co_scheduler_wait_proc(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/scheduler_io.c 0000664 0000000 0000000 00000057043 14142237372 0022043 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler_io.c * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "scheduler_io" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "scheduler_io.h" #include "coroutine.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the ltimer grow #ifdef __tb_small__ # define TB_SCHEDULER_IO_LTIMER_GROW (64) #else # define TB_SCHEDULER_IO_LTIMER_GROW (4096) #endif // the timer grow #define TB_SCHEDULER_IO_TIMER_GROW (TB_SCHEDULER_IO_LTIMER_GROW >> 4) // the poller object data grow #ifdef __tb_small__ # define TB_SCHEDULER_IO_POLLERDATA_GROW (64) #else # define TB_SCHEDULER_IO_POLLERDATA_GROW (4096) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_void_t tb_co_scheduler_io_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_size_t events) { // exists the timer task? remove it tb_cpointer_t task = coroutine->rs.wait.task; if (task) { // get io scheduler tb_co_scheduler_io_ref_t scheduler_io = tb_co_scheduler_io(scheduler); tb_assert(scheduler_io && scheduler_io->poller); // remove the timer task if (coroutine->rs.wait.is_ltimer) tb_ltimer_task_exit(scheduler_io->ltimer, (tb_ltimer_task_ref_t)task); else tb_timer_task_exit(scheduler_io->timer, (tb_timer_task_ref_t)task); coroutine->rs.wait.task = tb_null; } // resume the coroutine tb_co_scheduler_resume(scheduler, coroutine, (tb_cpointer_t)((events & TB_POLLER_EVENT_ERROR)? -1 : events)); } static tb_void_t tb_co_scheduler_io_timeout(tb_bool_t killed, tb_cpointer_t priv) { // check tb_coroutine_t* coroutine = (tb_coroutine_t*)priv; tb_assert(coroutine); // get scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_coroutine_scheduler(coroutine); tb_assert(scheduler); // trace tb_trace_d("coroutine(%p): timer(%s) %s", coroutine, coroutine->rs.wait.object.type? "poller object" : "sleep", killed? "killed" : "timeout"); // resume the waited coroutine if timer task has been not canceled if (!killed) { // reset the waited coroutines in the poller object data tb_size_t object_type = coroutine->rs.wait.object.type; if (object_type == TB_POLLER_OBJECT_PROC) coroutine->rs.wait.proc_waiting = 0; else if (object_type) { tb_co_scheduler_io_ref_t scheduler_io = tb_co_scheduler_io(scheduler); tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)(scheduler_io? tb_pollerdata_get(&scheduler_io->pollerdata, &coroutine->rs.wait.object) : tb_null); if (pollerdata) { if (coroutine == pollerdata->co_recv) pollerdata->co_recv = tb_null; if (coroutine == pollerdata->co_send) pollerdata->co_send = tb_null; } } // resume the coroutine tb_co_scheduler_io_resume(scheduler, coroutine, TB_POLLER_EVENT_NONE); } } static tb_void_t tb_co_scheduler_io_events(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv) { // check tb_co_scheduler_io_ref_t scheduler_io = (tb_co_scheduler_io_ref_t)tb_poller_priv(poller); tb_assert(scheduler_io && scheduler_io->scheduler && object); // is process object? if (object->type == TB_POLLER_OBJECT_PROC) { // resume coroutine and return the process exit status tb_coroutine_t* coroutine = (tb_coroutine_t*)priv; tb_assert(coroutine); coroutine->rs.wait.proc_status = (tb_int_t)events; // waiting process? resume this coroutine if (coroutine->rs.wait.proc_waiting) { coroutine->rs.wait.proc_waiting = 0; tb_co_scheduler_io_resume(scheduler_io->scheduler, coroutine, 1); } else coroutine->rs.wait.proc_pending = 1; return ; } // get pollerdata data tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object); tb_assert(pollerdata); // get poller object events tb_size_t events_prev_wait = pollerdata->poller_events_wait; tb_size_t events_prev_save = pollerdata->poller_events_save; // eof for edge trigger? if (events & TB_POLLER_EVENT_EOF) { // cache this eof as next recv/send event events &= ~TB_POLLER_EVENT_EOF; events_prev_save |= events_prev_wait; pollerdata->poller_events_save = (tb_uint16_t)events_prev_save; } // get the waiting coroutines tb_coroutine_t* co_recv = (events & TB_POLLER_EVENT_RECV)? pollerdata->co_recv : tb_null; tb_coroutine_t* co_send = (events & TB_POLLER_EVENT_SEND)? pollerdata->co_send : tb_null; // trace tb_trace_d("object: %p, trigger events %lu, co_recv(%p), co_send(%p)", object->ref.ptr, events, co_recv, co_send); // return the events result for the waiting coroutines if (co_recv && co_recv == co_send) { pollerdata->co_recv = tb_null; pollerdata->co_send = tb_null; tb_co_scheduler_io_resume(scheduler_io->scheduler, co_recv, events); } else { if (co_recv) { pollerdata->co_recv = tb_null; tb_co_scheduler_io_resume(scheduler_io->scheduler, co_recv, events & ~TB_POLLER_EVENT_SEND); events &= ~TB_POLLER_EVENT_RECV; } if (co_send) { pollerdata->co_send = tb_null; tb_co_scheduler_io_resume(scheduler_io->scheduler, co_send, events & ~TB_POLLER_EVENT_RECV); events &= ~TB_POLLER_EVENT_SEND; } // no coroutines are waiting? cache this events if ((events & TB_POLLER_EVENT_RECV) || (events & TB_POLLER_EVENT_SEND)) { // trace tb_trace_d("object: %p, cache events %lu", object->ref.ptr, events); // cache this events events_prev_save |= events; pollerdata->poller_events_save = (tb_uint16_t)events_prev_save; } } } static tb_bool_t tb_co_scheduler_io_timer_spak(tb_co_scheduler_io_ref_t scheduler_io) { // check tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); // spak ctime tb_cache_time_spak(); // spak timer if (!tb_timer_spak(scheduler_io->timer)) return tb_false; // spak ltimer if (!tb_ltimer_spak(scheduler_io->ltimer)) return tb_false; // pk return tb_true; } static tb_void_t tb_co_scheduler_io_loop(tb_cpointer_t priv) { // check tb_co_scheduler_io_ref_t scheduler_io = (tb_co_scheduler_io_ref_t)priv; tb_assert_and_check_return(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); // the scheduler tb_co_scheduler_t* scheduler = scheduler_io->scheduler; tb_assert_and_check_return(scheduler); // the poller tb_poller_ref_t poller = scheduler_io->poller; tb_assert_and_check_return(poller); // loop while (!scheduler->stopped) { // finish all other ready coroutines first while (tb_co_scheduler_yield(scheduler)) { // spak timer if (!tb_co_scheduler_io_timer_spak(scheduler_io)) break; } // no more suspended coroutines? loop end tb_check_break(tb_co_scheduler_suspend_count(scheduler)); // the delay tb_size_t delay = tb_timer_delay(scheduler_io->timer); // the ldelay tb_size_t ldelay = tb_ltimer_delay(scheduler_io->ltimer); // trace tb_trace_d("loop: wait %lu ms, %lu pending coroutines ..", tb_min(delay, ldelay), tb_co_scheduler_suspend_count(scheduler)); // no more ready coroutines? wait io events and timers if (tb_poller_wait(poller, tb_co_scheduler_io_events, tb_min(delay, ldelay)) < 0) { tb_trace_e("loop: wait poller failed!"); break; } // trace tb_trace_d("loop: wait ok, left %lu pending coroutines ..", tb_co_scheduler_suspend_count(scheduler)); // spak timer if (!tb_co_scheduler_io_timer_spak(scheduler_io)) break; } } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_co_scheduler_io_ref_t tb_co_scheduler_io_init(tb_co_scheduler_t* scheduler) { // done tb_bool_t ok = tb_false; tb_co_scheduler_io_ref_t scheduler_io = tb_null; do { // init io scheduler scheduler_io = tb_malloc0_type(tb_co_scheduler_io_t); tb_assert_and_check_break(scheduler_io); // save scheduler scheduler_io->scheduler = (tb_co_scheduler_t*)scheduler; // init timer and using cache time scheduler_io->timer = tb_timer_init(TB_SCHEDULER_IO_TIMER_GROW, tb_true); tb_assert_and_check_break(scheduler_io->timer); // init ltimer and using cache time scheduler_io->ltimer = tb_ltimer_init(TB_SCHEDULER_IO_LTIMER_GROW, TB_LTIMER_TICK_S, tb_true); tb_assert_and_check_break(scheduler_io->ltimer); // init poller scheduler_io->poller = tb_poller_init(scheduler_io); tb_assert_and_check_break(scheduler_io->poller); // attach poller tb_poller_attach(scheduler_io->poller); // init poller object data pool scheduler_io->pollerdata_pool = tb_fixed_pool_init(tb_null, TB_SCHEDULER_IO_POLLERDATA_GROW, sizeof(tb_co_pollerdata_io_t), tb_null, tb_null, tb_null); tb_assert_and_check_break(scheduler_io->pollerdata_pool); // init poller object data tb_pollerdata_init(&scheduler_io->pollerdata); // start the io loop coroutine if (!tb_co_scheduler_start(scheduler_io->scheduler, tb_co_scheduler_io_loop, scheduler_io, 0)) break; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit io scheduler if (scheduler_io) tb_co_scheduler_io_exit(scheduler_io); scheduler_io = tb_null; } // ok? return scheduler_io; } tb_void_t tb_co_scheduler_io_exit(tb_co_scheduler_io_ref_t scheduler_io) { // check tb_assert_and_check_return(scheduler_io); // exit poller object data tb_pollerdata_exit(&scheduler_io->pollerdata); // exit poller object data pool if (scheduler_io->pollerdata_pool) tb_fixed_pool_exit(scheduler_io->pollerdata_pool); scheduler_io->pollerdata_pool = tb_null; // exit poller if (scheduler_io->poller) tb_poller_exit(scheduler_io->poller); scheduler_io->poller = tb_null; // exit timer if (scheduler_io->timer) tb_timer_exit(scheduler_io->timer); scheduler_io->timer = tb_null; // exit ltimer if (scheduler_io->ltimer) tb_ltimer_exit(scheduler_io->ltimer); scheduler_io->ltimer = tb_null; // clear scheduler scheduler_io->scheduler = tb_null; // exit it tb_free(scheduler_io); } tb_co_scheduler_io_ref_t tb_co_scheduler_io_need(tb_co_scheduler_t* scheduler) { // get the current scheduler if (!scheduler) scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); if (scheduler) { // init io scheduler first if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_co_scheduler_io_init(scheduler); tb_assert(scheduler->scheduler_io); // get the current io scheduler return (tb_co_scheduler_io_ref_t)scheduler->scheduler_io; } return tb_null; } tb_void_t tb_co_scheduler_io_kill(tb_co_scheduler_io_ref_t scheduler_io) { // check tb_assert_and_check_return(scheduler_io); // trace tb_trace_d("kill: .."); // kill timer if (scheduler_io->timer) tb_timer_kill(scheduler_io->timer); // kill ltimer if (scheduler_io->ltimer) tb_ltimer_kill(scheduler_io->ltimer); // kill poller if (scheduler_io->poller) tb_poller_kill(scheduler_io->poller); } tb_pointer_t tb_co_scheduler_io_sleep(tb_co_scheduler_io_ref_t scheduler_io, tb_long_t interval) { // check tb_assert_and_check_return_val(scheduler_io && scheduler_io->poller && scheduler_io->scheduler, tb_null); // no sleep? tb_check_return_val(interval, tb_null); // get the current coroutine tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // trace tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval); // clear waiting task first coroutine->rs.wait.task = tb_null; coroutine->rs.wait.object.type = TB_POLLER_OBJECT_NONE; // infinity? if (interval > 0) { // high-precision interval? if (interval % 1000) { // post task to timer tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_co_scheduler_io_timeout, coroutine); } // low-precision interval? else { // post task to ltimer (faster) tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_co_scheduler_io_timeout, coroutine); } } // suspend it return tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null); } tb_long_t tb_co_scheduler_io_wait(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout) { // check tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler && events); // get the current coroutine tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // get the poller tb_poller_ref_t poller = scheduler_io->poller; tb_assert(poller); // trace tb_trace_d("coroutine(%p): wait events(%lu) with %ld ms for object(%p) ..", coroutine, events, timeout, object->ref.ptr); // get and allocate a poller object data tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object); if (!pollerdata) { tb_assert(scheduler_io->pollerdata_pool); pollerdata = (tb_co_pollerdata_io_ref_t)tb_fixed_pool_malloc0(scheduler_io->pollerdata_pool); tb_pollerdata_set(&scheduler_io->pollerdata, object, pollerdata); } tb_assert_and_check_return_val(pollerdata, -1); // enable edge-trigger mode if be supported if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR)) events |= TB_POLLER_EVENT_CLEAR; // get the previous poller object events tb_size_t events_wait = events; if (pollerdata->poller_events_wait) { // return the cached events directly if the waiting events exists cache tb_size_t events_prev_wait = pollerdata->poller_events_wait; tb_size_t events_prev_save = pollerdata->poller_events_save; if (events_prev_save && (events_prev_wait & events)) { // check error? if (events_prev_save & TB_POLLER_EVENT_ERROR) { pollerdata->poller_events_save = 0; return -1; } // clear cache events pollerdata->poller_events_save = (tb_uint16_t)(events_prev_save & ~events); // return the cached events return events_prev_save & events; } // modify the wait events and reserve the pending events in other coroutine events_wait = events_prev_wait; if ((events_wait & TB_POLLER_EVENT_RECV) && !pollerdata->co_recv) events_wait &= ~TB_POLLER_EVENT_RECV; if ((events_wait & TB_POLLER_EVENT_SEND) && !pollerdata->co_send) events_wait &= ~TB_POLLER_EVENT_SEND; events_wait |= events; // modify poller object from poller for waiting events if the waiting events has been changed if ((events_prev_wait & events_wait) != events_wait) { // trace tb_trace_d("modify poller object: %p events: %lx", object->ref.ptr, events_wait); // may be wait recv/send at same time if (!tb_poller_modify(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null)) { // trace tb_trace_e("failed to modify object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); return -1; } } } else { // trace tb_trace_d("insert poller object: %p events: %lx", object->ref.ptr, events_wait); // insert poller object to poller for waiting events if (!tb_poller_insert(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null)) { // trace tb_trace_e("failed to insert object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); return -1; } } // exists timeout? tb_cpointer_t task = tb_null; tb_bool_t is_ltimer = tb_false; if (timeout >= 0) { // high-precision interval? if (timeout % 1000) { // init task for timer task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); } // low-precision interval? else { // init task for ltimer (faster) task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); // mark as low-precision timer is_ltimer = tb_true; } } // save the timer task to coroutine coroutine->rs.wait.task = task; coroutine->rs.wait.object = *object; coroutine->rs.wait.is_ltimer = is_ltimer; // save waiting events pollerdata->poller_events_wait = (tb_uint16_t)events_wait; pollerdata->poller_events_save = 0; // save the current coroutine if (events & TB_POLLER_EVENT_RECV) pollerdata->co_recv = coroutine; if (events & TB_POLLER_EVENT_SEND) pollerdata->co_send = coroutine; // suspend the current coroutine and return the waited result return (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null); } tb_long_t tb_co_scheduler_io_wait_proc(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout) { // check tb_assert(scheduler_io && scheduler_io->poller && scheduler_io->scheduler); tb_assert(object && object->type == TB_POLLER_OBJECT_PROC && object->ref.proc); // get the current coroutine tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // get the poller tb_poller_ref_t poller = scheduler_io->poller; tb_assert(poller); // trace tb_trace_d("coroutine(%p): wait process object(%p) with %ld ms ..", coroutine, object->ref.proc, timeout); // has pending process status? if (coroutine->rs.wait.proc_pending) { if (pstatus) *pstatus = coroutine->rs.wait.proc_status; coroutine->rs.wait.proc_pending = 0; return 1; } // insert poller object to poller for waiting process if (!tb_poller_insert(poller, object, 0, coroutine)) { // trace tb_trace_e("failed to insert process object(%p) to poller on coroutine(%p)!", object->ref.proc, coroutine); return -1; } // exists timeout? tb_cpointer_t task = tb_null; tb_bool_t is_ltimer = tb_false; if (timeout >= 0) { // high-precision interval? if (timeout % 1000) { // init task for timer task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); } // low-precision interval? else { // init task for ltimer (faster) task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); // mark as low-precision timer is_ltimer = tb_true; } } // save the timer task to coroutine coroutine->rs.wait.task = task; coroutine->rs.wait.object = *object; coroutine->rs.wait.is_ltimer = is_ltimer; coroutine->rs.wait.proc_status = 0; coroutine->rs.wait.proc_pending = 0; coroutine->rs.wait.proc_waiting = 1; // suspend the current coroutine and return the waited result tb_long_t ok = (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null); if (ok > 0 && pstatus) *pstatus = coroutine->rs.wait.proc_status; return ok; } tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object) { // check tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler); // get the current coroutine tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); tb_check_return_val(coroutine, tb_false); // trace tb_trace_d("coroutine(%p): cancel poller object(%p) ..", coroutine, object->ref.ptr); // cancel process object if (object->type == TB_POLLER_OBJECT_PROC) { // clear process status coroutine->rs.wait.proc_status = 0; coroutine->rs.wait.proc_pending = 0; coroutine->rs.wait.proc_waiting = 0; // remove the previous poller object first if exists if (!tb_poller_remove(scheduler_io->poller, object)) { // trace tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); return tb_false; } return tb_true; } // reset the pollerdata data tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object); if (pollerdata) { // clear the waiting coroutines pollerdata->co_recv = tb_null; pollerdata->co_send = tb_null; // remove the this poller object from poller if (pollerdata->poller_events_wait) { // remove the previous poller object first if exists if (!tb_poller_remove(scheduler_io->poller, object)) { // trace tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); return tb_false; } // remove the poller object events pollerdata->poller_events_wait = 0; pollerdata->poller_events_save = 0; return tb_true; } } // no this poller object return tb_false; } tb_co_scheduler_io_ref_t tb_co_scheduler_io_self() { // get the current scheduler tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); // get the current io scheduler return scheduler? (tb_co_scheduler_io_ref_t)scheduler->scheduler_io : tb_null; } tbox-1.6.7/src/tbox/coroutine/impl/scheduler_io.h 0000664 0000000 0000000 00000012015 14142237372 0022036 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler_io.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_IMPL_SCHEDULER_IO_H #define TB_COROUTINE_IMPL_SCHEDULER_IO_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "scheduler.h" #include "../../memory/fixed_pool.h" #include "../../platform/poller.h" #include "../../platform/impl/pollerdata.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the io poller data type typedef struct __tb_co_pollerdata_io_t { // the suspended coroutine for waiting poller/recv tb_coroutine_t* co_recv; // the suspended coroutine for waiting poller/send tb_coroutine_t* co_send; // the waited events for poller tb_uint16_t poller_events_wait; // the saved events for poller (triggered) tb_uint16_t poller_events_save; }tb_co_pollerdata_io_t, *tb_co_pollerdata_io_ref_t; // the io scheduler type typedef struct __tb_co_scheduler_io_t { // is stopped? tb_bool_t stop; // the scheduler tb_co_scheduler_t* scheduler; // the poller tb_poller_ref_t poller; // the timer tb_timer_ref_t timer; // the low-precision timer (faster) tb_ltimer_ref_t ltimer; // the poller data tb_pollerdata_t pollerdata; // the poller data pool tb_fixed_pool_ref_t pollerdata_pool; }tb_co_scheduler_io_t, *tb_co_scheduler_io_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init io scheduler * * @param scheduler the scheduler * * @return the io scheduler */ tb_co_scheduler_io_ref_t tb_co_scheduler_io_init(tb_co_scheduler_t* scheduler); /*! exit io scheduler * * @param scheduler_io the io scheduler */ tb_void_t tb_co_scheduler_io_exit(tb_co_scheduler_io_ref_t scheduler_io); /* need io scheduler * * ensure the io scheduler has been initialized * * @param scheduler the scheduler, get self scheduler if be null * * @return the io scheduler */ tb_co_scheduler_io_ref_t tb_co_scheduler_io_need(tb_co_scheduler_t* scheduler); /* kill the current io scheduler * * @param scheduler_io the io scheduler */ tb_void_t tb_co_scheduler_io_kill(tb_co_scheduler_io_ref_t scheduler_io); /* sleep the current coroutine * * @param scheduler_io the io scheduler * @param interval the interval (ms), infinity: -1 * * @return the user private data from resume(priv) */ tb_pointer_t tb_co_scheduler_io_sleep(tb_co_scheduler_io_ref_t scheduler_io, tb_long_t interval); /*! wait io events * * @param scheduler_io the io scheduler * @param object the poller object, socket or pipe * @param events the waited events * @param timeout the timeout, infinity: -1 * * @return > 0: the events, 0: timeout, -1: failed */ tb_long_t tb_co_scheduler_io_wait(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout); /*! wait process status * * @param scheduler_io the io scheduler * @param object the process poller object * @param pstatus the process exited status pointer, maybe null * @param timeout the timeout, infinity: -1 * * @return > 0: process exited, 0: timeout, -1: failed */ tb_long_t tb_co_scheduler_io_wait_proc(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout); /*! cancel io events for the given poller object * * @param scheduler_io the io scheduler * @param object the poller object * * @return tb_true or tb_false */ tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object); /* get the current io scheduler * * @return the io scheduler */ tb_co_scheduler_io_ref_t tb_co_scheduler_io_self(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/stackless/ 0000775 0000000 0000000 00000000000 14142237372 0021215 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/coroutine/impl/stackless/coroutine.h 0000664 0000000 0000000 00000007431 14142237372 0023402 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file coroutine.h * */ #ifndef TB_COROUTINE_IMPL_STACKLESS_COROUTINE_H #define TB_COROUTINE_IMPL_STACKLESS_COROUTINE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the coroutine wait type typedef struct __tb_lo_coroutine_rs_wait_t { // the waited poller object tb_poller_object_t object; #ifndef TB_CONFIG_MICRO_ENABLE // the timer task pointer for ltimer or timer tb_cpointer_t task; // is ltimer? tb_sint32_t is_ltimer : 1; // the process status tb_int_t proc_status; // has pending process status? tb_uint16_t proc_pending : 1; // waiting process? tb_uint16_t proc_waiting : 1; #endif // the waited result tb_sint32_t result : 16; }tb_lo_coroutine_rs_wait_t; /// the stackless coroutine type typedef struct __tb_lo_coroutine_t { // the coroutine core tb_lo_core_t core; // the list entry tb_list_entry_t entry; // the coroutine function tb_lo_coroutine_func_t func; // the user private data of the coroutine function tb_cpointer_t priv; // the user private data free function tb_lo_coroutine_free_t free; // the scheduler tb_lo_scheduler_ref_t scheduler; // the passed private data between resume() and suspend() union { // the arguments for wait() tb_lo_coroutine_rs_wait_t wait; } rs; }tb_lo_coroutine_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init coroutine * * @param scheduler the scheduler * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param free the user private data free function * * @return the coroutine */ tb_lo_coroutine_t* tb_lo_coroutine_init(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); /* reinit the given coroutine * * @param coroutine the coroutine * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param free the user private data free function * * @return tb_true or tb_false */ tb_bool_t tb_lo_coroutine_reinit(tb_lo_coroutine_t* coroutine, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); /* exit coroutine * * @param coroutine the coroutine */ tb_void_t tb_lo_coroutine_exit(tb_lo_coroutine_t* coroutine); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/stackless/prefix.h 0000664 0000000 0000000 00000001763 14142237372 0022672 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_COROUTINE_IMPL_STACKLESS_PREFIX_H #define TB_COROUTINE_IMPL_STACKLESS_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../../stackless/coroutine.h" #include "../../../container/container.h" #endif tbox-1.6.7/src/tbox/coroutine/impl/stackless/scheduler.h 0000664 0000000 0000000 00000007124 14142237372 0023350 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler.h * */ #ifndef TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_H #define TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "coroutine.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // get the running coroutine #define tb_lo_scheduler_running(scheduler) ((scheduler)->running) // get the ready coroutines count #define tb_lo_scheduler_ready_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_ready) // get the suspended coroutines count #define tb_lo_scheduler_suspend_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_suspend) // get the io scheduler #define tb_lo_scheduler_io(scheduler) ((scheduler)->scheduler_io) /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the io scheduler type struct __tb_lo_scheduler_io_t; /// the stackless coroutine scheduler type typedef struct __tb_lo_scheduler_t { // is stopped tb_bool_t stopped; // the running coroutine tb_lo_coroutine_t* running; // the io scheduler struct __tb_lo_scheduler_io_t* scheduler_io; // the dead coroutines tb_list_entry_head_t coroutines_dead; /* the ready coroutines * * ready: head -> ready -> .. -> running -> .. -> ready -> ..-> * | | * ---------------------------<----------------------- */ tb_list_entry_head_t coroutines_ready; // the suspend coroutines tb_list_entry_head_t coroutines_suspend; }tb_lo_scheduler_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* start coroutine * * @param scheduler the scheduler * @param func the coroutine function * @param priv the passed user private data as the argument of function * @param free the user private data free function * * @return tb_true or tb_false */ tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); /* resume the given coroutine * * @param scheduler the scheduler * @param coroutine the coroutine */ tb_void_t tb_lo_scheduler_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine); /* get the current scheduler * * @return the scheduler */ tb_lo_scheduler_ref_t tb_lo_scheduler_self_(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/stackless/scheduler_io.c 0000664 0000000 0000000 00000060402 14142237372 0024030 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler_io.c * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "scheduler_io" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "scheduler_io.h" #include "coroutine.h" #include "../../stackless/coroutine.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the ltimer grow #ifdef __tb_small__ # define TB_SCHEDULER_IO_LTIMER_GROW (64) #else # define TB_SCHEDULER_IO_LTIMER_GROW (4096) #endif // the timer grow #define TB_SCHEDULER_IO_TIMER_GROW (TB_SCHEDULER_IO_LTIMER_GROW >> 4) // the poller data grow #ifdef __tb_small__ # define TB_SCHEDULER_IO_POLLERDATA_GROW (64) #else # define TB_SCHEDULER_IO_POLLERDATA_GROW (4096) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_void_t tb_lo_scheduler_io_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine, tb_size_t events) { #ifndef TB_CONFIG_MICRO_ENABLE // exists the timer task? remove it tb_cpointer_t task = coroutine->rs.wait.task; if (task) { // get io scheduler tb_lo_scheduler_io_ref_t scheduler_io = tb_lo_scheduler_io(scheduler); tb_assert(scheduler_io && scheduler_io->poller); // remove the timer task if (coroutine->rs.wait.is_ltimer) tb_ltimer_task_exit(scheduler_io->ltimer, (tb_ltimer_task_ref_t)task); else tb_timer_task_exit(scheduler_io->timer, (tb_timer_task_ref_t)task); coroutine->rs.wait.task = tb_null; } #endif // return events coroutine->rs.wait.result = (tb_sint32_t)((events & TB_POLLER_EVENT_ERROR)? -1 : events); // resume the coroutine tb_lo_scheduler_resume(scheduler, coroutine); } #ifndef TB_CONFIG_MICRO_ENABLE static tb_void_t tb_lo_scheduler_io_timeout(tb_bool_t killed, tb_cpointer_t priv) { // check tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv; tb_assert(coroutine); // get scheduler tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler; tb_assert(scheduler); // trace tb_trace_d("coroutine(%p): timer(%s) %s", coroutine, coroutine->rs.wait.object.type? "poller" : "sleep", killed? "killed" : "timeout"); // resume the waited coroutine if timer task has been not canceled if (!killed) { // reset the waited coroutines in the poller data tb_size_t object_type = coroutine->rs.wait.object.type; #ifndef TB_CONFIG_MICRO_ENABLE if (object_type == TB_POLLER_OBJECT_PROC) coroutine->rs.wait.proc_waiting = 0; else #endif if (object_type) { tb_lo_scheduler_io_ref_t scheduler_io = tb_lo_scheduler_io(scheduler); tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)(scheduler_io? tb_pollerdata_get(&scheduler_io->pollerdata, &coroutine->rs.wait.object) : tb_null); if (pollerdata) { if (coroutine == pollerdata->lo_recv) pollerdata->lo_recv = tb_null; if (coroutine == pollerdata->lo_send) pollerdata->lo_send = tb_null; } } // resume the coroutine tb_lo_scheduler_io_resume(scheduler, coroutine, TB_POLLER_EVENT_NONE); } } #endif static tb_void_t tb_lo_scheduler_io_events(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv) { // check tb_lo_scheduler_io_ref_t scheduler_io = (tb_lo_scheduler_io_ref_t)tb_poller_priv(poller); tb_assert(scheduler_io && scheduler_io->scheduler && object); #ifndef TB_CONFIG_MICRO_ENABLE // is process object? if (object->type == TB_POLLER_OBJECT_PROC) { // resume coroutine and return the process exit status tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv; tb_assert(coroutine); coroutine->rs.wait.proc_status = (tb_int_t)events; // waiting process? resume this coroutine if (coroutine->rs.wait.proc_waiting) { coroutine->rs.wait.proc_waiting = 0; tb_lo_scheduler_io_resume(scheduler_io->scheduler, coroutine, 1); } else coroutine->rs.wait.proc_pending = 1; return ; } #endif // get pollerdata data tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object); tb_assert(pollerdata); // get poller events tb_size_t events_prev_wait = pollerdata->poller_events_wait; tb_size_t events_prev_save = pollerdata->poller_events_save; // eof for edge trigger? if (events & TB_POLLER_EVENT_EOF) { // cache this eof as next recv/send event events &= ~TB_POLLER_EVENT_EOF; events_prev_save |= events_prev_wait; pollerdata->poller_events_save = (tb_uint16_t)events_prev_save; } // get the waiting coroutines tb_lo_coroutine_t* lo_recv = (events & TB_POLLER_EVENT_RECV)? pollerdata->lo_recv : tb_null; tb_lo_coroutine_t* lo_send = (events & TB_POLLER_EVENT_SEND)? pollerdata->lo_send : tb_null; // trace tb_trace_d("object: %p, trigger events %lu, lo_recv(%p), lo_send(%p)", object->ref.ptr, events, lo_recv, lo_send); // return the events result for the waiting coroutines if (lo_recv && lo_recv == lo_send) { pollerdata->lo_recv = tb_null; pollerdata->lo_send = tb_null; tb_lo_scheduler_io_resume(scheduler_io->scheduler, lo_recv, events); } else { if (lo_recv) { pollerdata->lo_recv = tb_null; tb_lo_scheduler_io_resume(scheduler_io->scheduler, lo_recv, events & ~TB_POLLER_EVENT_SEND); events &= ~TB_POLLER_EVENT_RECV; } if (lo_send) { pollerdata->lo_send = tb_null; tb_lo_scheduler_io_resume(scheduler_io->scheduler, lo_send, events & ~TB_POLLER_EVENT_RECV); events &= ~TB_POLLER_EVENT_SEND; } // no coroutines are waiting? cache this events if ((events & TB_POLLER_EVENT_RECV) || (events & TB_POLLER_EVENT_SEND)) { // trace tb_trace_d("object: %p, cache events %lu", object->ref.ptr, events); // cache this events events_prev_save |= events; pollerdata->poller_events_save = (tb_uint16_t)events_prev_save; } } } #ifndef TB_CONFIG_MICRO_ENABLE static tb_bool_t tb_lo_scheduler_io_timer_spak(tb_lo_scheduler_io_ref_t scheduler_io) { // check tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); // spak ctime tb_cache_time_spak(); // spak timer if (!tb_timer_spak(scheduler_io->timer)) return tb_false; // spak ltimer if (!tb_ltimer_spak(scheduler_io->ltimer)) return tb_false; // pk return tb_true; } static tb_long_t tb_lo_scheduler_io_timer_delay(tb_lo_scheduler_io_ref_t scheduler_io) { // check tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); // the delay tb_size_t delay = tb_timer_delay(scheduler_io->timer); // the ldelay tb_size_t ldelay = tb_ltimer_delay(scheduler_io->ltimer); // return the timer delay return tb_min(delay, ldelay); } #else static __tb_inline__ tb_long_t tb_lo_scheduler_io_timer_delay(tb_lo_scheduler_io_ref_t scheduler_io) { return 1000; } #endif static tb_void_t tb_lo_scheduler_io_loop(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv) { // check tb_lo_scheduler_io_ref_t scheduler_io = (tb_lo_scheduler_io_ref_t)priv; tb_assert(scheduler_io && scheduler_io->poller); // the scheduler tb_lo_scheduler_t* scheduler = scheduler_io->scheduler; tb_assert(scheduler); // enter coroutine tb_lo_coroutine_enter(coroutine) { // loop while (!scheduler->stopped) { // finish all other ready coroutines first while (tb_lo_scheduler_ready_count(scheduler) > 1) { // yield it tb_lo_coroutine_yield(); #ifndef TB_CONFIG_MICRO_ENABLE // spak timer if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break; #endif } // no more suspended coroutines? loop end tb_check_break(tb_lo_scheduler_suspend_count(scheduler)); // trace tb_trace_d("loop: wait %ld ms ..", tb_lo_scheduler_io_timer_delay(scheduler_io)); // no more ready coroutines? wait io events and timers (TODO) if (tb_poller_wait(scheduler_io->poller, tb_lo_scheduler_io_events, tb_lo_scheduler_io_timer_delay(scheduler_io)) < 0) break; #ifndef TB_CONFIG_MICRO_ENABLE // spak timer if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break; #endif } } } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_init(tb_lo_scheduler_t* scheduler) { // done tb_bool_t ok = tb_false; tb_lo_scheduler_io_ref_t scheduler_io = tb_null; do { // init io scheduler scheduler_io = tb_malloc0_type(tb_lo_scheduler_io_t); tb_assert_and_check_break(scheduler_io); // save scheduler scheduler_io->scheduler = (tb_lo_scheduler_t*)scheduler; // init poller scheduler_io->poller = tb_poller_init(scheduler_io); tb_assert_and_check_break(scheduler_io->poller); // attach poller tb_poller_attach(scheduler_io->poller); #ifndef TB_CONFIG_MICRO_ENABLE // init timer and using cache time scheduler_io->timer = tb_timer_init(TB_SCHEDULER_IO_TIMER_GROW, tb_true); tb_assert_and_check_break(scheduler_io->timer); // init ltimer and using cache time scheduler_io->ltimer = tb_ltimer_init(TB_SCHEDULER_IO_LTIMER_GROW, TB_LTIMER_TICK_S, tb_true); tb_assert_and_check_break(scheduler_io->ltimer); #endif // init poller data pool scheduler_io->pollerdata_pool = tb_fixed_pool_init(tb_null, TB_SCHEDULER_IO_POLLERDATA_GROW, sizeof(tb_lo_pollerdata_io_t), tb_null, tb_null, tb_null); tb_assert_and_check_break(scheduler_io->pollerdata_pool); // init poller data tb_pollerdata_init(&scheduler_io->pollerdata); // start the io loop coroutine if (!tb_lo_coroutine_start((tb_lo_scheduler_ref_t)scheduler, tb_lo_scheduler_io_loop, scheduler_io, tb_null)) break; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit io scheduler if (scheduler_io) tb_lo_scheduler_io_exit(scheduler_io); scheduler_io = tb_null; } // ok? return scheduler_io; } tb_void_t tb_lo_scheduler_io_exit(tb_lo_scheduler_io_ref_t scheduler_io) { // check tb_assert_and_check_return(scheduler_io); // exit poller data tb_pollerdata_exit(&scheduler_io->pollerdata); // exit poller data pool if (scheduler_io->pollerdata_pool) tb_fixed_pool_exit(scheduler_io->pollerdata_pool); scheduler_io->pollerdata_pool = tb_null; // exit poller if (scheduler_io->poller) tb_poller_exit(scheduler_io->poller); scheduler_io->poller = tb_null; #ifndef TB_CONFIG_MICRO_ENABLE // exit timer if (scheduler_io->timer) tb_timer_exit(scheduler_io->timer); scheduler_io->timer = tb_null; // exit ltimer if (scheduler_io->ltimer) tb_ltimer_exit(scheduler_io->ltimer); scheduler_io->ltimer = tb_null; #endif // clear scheduler scheduler_io->scheduler = tb_null; // exit it tb_free(scheduler_io); } tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_need(tb_lo_scheduler_t* scheduler) { // get the current scheduler if (!scheduler) scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_(); if (scheduler) { // init io scheduler first if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_lo_scheduler_io_init(scheduler); tb_assert(scheduler->scheduler_io); // get the current io scheduler return (tb_lo_scheduler_io_ref_t)scheduler->scheduler_io; } return tb_null; } tb_void_t tb_lo_scheduler_io_kill(tb_lo_scheduler_io_ref_t scheduler_io) { // check tb_assert_and_check_return(scheduler_io); // trace tb_trace_d("kill: .."); #ifndef TB_CONFIG_MICRO_ENABLE // kill timer if (scheduler_io->timer) tb_timer_kill(scheduler_io->timer); // kill ltimer if (scheduler_io->ltimer) tb_ltimer_kill(scheduler_io->ltimer); #endif // kill poller if (scheduler_io->poller) tb_poller_kill(scheduler_io->poller); } tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval) { #ifndef TB_CONFIG_MICRO_ENABLE // check tb_assert_and_check_return(scheduler_io && scheduler_io->poller && scheduler_io->scheduler); // get the current coroutine tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // trace tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval); // clear waiting task first coroutine->rs.wait.task = tb_null; coroutine->rs.wait.object.type = TB_POLLER_OBJECT_NONE; // infinity? if (interval > 0) { // high-precision interval? if (interval % 1000) { // post task to timer tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine); } // low-precision interval? else { // post task to ltimer (faster) tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine); } } #else // not impl tb_trace_noimpl(); #endif } tb_bool_t tb_lo_scheduler_io_wait(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout) { // check tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler && events); // get the current coroutine tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // get the poller tb_poller_ref_t poller = scheduler_io->poller; tb_assert(poller); // trace tb_trace_d("coroutine(%p): wait events(%lu) with %ld ms for poller(%p) ..", coroutine, events, timeout, object->ref.ptr); // get and allocate a poller data tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object); if (!pollerdata) { tb_assert(scheduler_io->pollerdata_pool); pollerdata = (tb_lo_pollerdata_io_ref_t)tb_fixed_pool_malloc0(scheduler_io->pollerdata_pool); tb_pollerdata_set(&scheduler_io->pollerdata, object, pollerdata); } tb_assert_and_check_return_val(pollerdata, -1); // enable edge-trigger mode if be supported if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR)) events |= TB_POLLER_EVENT_CLEAR; // get the previous poller events tb_size_t events_wait = events; if (pollerdata->poller_events_wait) { // return the cached events directly if the waiting events exists cache tb_size_t events_prev_wait = pollerdata->poller_events_wait; tb_size_t events_prev_save = pollerdata->poller_events_save; if (events_prev_save && (events_prev_wait & events)) { // check error? if (events_prev_save & TB_POLLER_EVENT_ERROR) { pollerdata->poller_events_save = 0; coroutine->rs.wait.result = -1; return tb_false; } // clear cache events pollerdata->poller_events_save = (tb_uint16_t)(events_prev_save & ~events); // return the cached events coroutine->rs.wait.result = events_prev_save & events; return tb_false; } // modify the wait events and reserve the pending events in other coroutine events_wait = events_prev_wait; if ((events_wait & TB_POLLER_EVENT_RECV) && !pollerdata->lo_recv) events_wait &= ~TB_POLLER_EVENT_RECV; if ((events_wait & TB_POLLER_EVENT_SEND) && !pollerdata->lo_send) events_wait &= ~TB_POLLER_EVENT_SEND; events_wait |= events; // modify poller from poller for waiting events if the waiting events has been changed if ((events_prev_wait & events_wait) != events_wait) { // trace tb_trace_d("modify poller object: %p events: %lx", object, events_wait); // may be wait recv/send at same time if (!tb_poller_modify(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null)) { // trace tb_trace_e("failed to modify object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); coroutine->rs.wait.result = -1; return tb_false; } } } else { // trace tb_trace_d("insert poller object: %p events: %lx", object->ref.ptr, events_wait); // insert poller to poller for waiting events if (!tb_poller_insert(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null)) { // trace tb_trace_e("failed to insert object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); coroutine->rs.wait.result = -1; return tb_false; } } #ifndef TB_CONFIG_MICRO_ENABLE // exists timeout? tb_cpointer_t task = tb_null; tb_bool_t is_ltimer = tb_false; if (timeout >= 0) { // high-precision interval? if (timeout % 1000) { // init task for timer task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); } // low-precision interval? else { // init task for ltimer (faster) task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); // mark as low-precision timer is_ltimer = tb_true; } } // save the timer task to coroutine coroutine->rs.wait.task = task; coroutine->rs.wait.is_ltimer = is_ltimer; #endif coroutine->rs.wait.object = *object; coroutine->rs.wait.result = 0; // save waiting events pollerdata->poller_events_wait = (tb_uint16_t)events_wait; pollerdata->poller_events_save = 0; // save the current coroutine if (events & TB_POLLER_EVENT_RECV) pollerdata->lo_recv = coroutine; if (events & TB_POLLER_EVENT_SEND) pollerdata->lo_send = coroutine; // suspend the current coroutine return tb_true; } #ifndef TB_CONFIG_MICRO_ENABLE tb_bool_t tb_lo_scheduler_io_wait_proc(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t timeout) { // check tb_assert(scheduler_io && scheduler_io->poller && scheduler_io->scheduler); tb_assert(object && object->type == TB_POLLER_OBJECT_PROC && object->ref.proc); // get the current coroutine tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // get the poller tb_poller_ref_t poller = scheduler_io->poller; tb_assert(poller); // trace tb_trace_d("coroutine(%p): wait process object(%p) with %ld ms ..", coroutine, object->ref.proc, timeout); // has pending process status? if (coroutine->rs.wait.proc_pending) { coroutine->rs.wait.proc_pending = 0; coroutine->rs.wait.result = 1; return tb_false; } // insert poller object to poller for waiting process if (!tb_poller_insert(poller, object, 0, coroutine)) { // trace tb_trace_e("failed to insert process object(%p) to poller on coroutine(%p)!", object->ref.proc, coroutine); coroutine->rs.wait.result = -1; return tb_false; } // exists timeout? tb_cpointer_t task = tb_null; tb_bool_t is_ltimer = tb_false; if (timeout >= 0) { // high-precision interval? if (timeout % 1000) { // init task for timer task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); } // low-precision interval? else { // init task for ltimer (faster) task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine); tb_assert_and_check_return_val(task, tb_false); // mark as low-precision timer is_ltimer = tb_true; } } // save the timer task to coroutine coroutine->rs.wait.task = task; coroutine->rs.wait.object = *object; coroutine->rs.wait.is_ltimer = is_ltimer; coroutine->rs.wait.proc_status = 0; coroutine->rs.wait.proc_pending = 0; coroutine->rs.wait.proc_waiting = 1; // suspend the current coroutine return tb_true; } #endif tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object) { // check tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler); // get the current coroutine tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); tb_check_return_val(coroutine, tb_false); // trace tb_trace_d("coroutine(%p): cancel poller object(%p) ..", coroutine, object->ref.ptr); #ifndef TB_CONFIG_MICRO_ENABLE // cancel process object if (object->type == TB_POLLER_OBJECT_PROC) { // clear process status coroutine->rs.wait.proc_status = 0; coroutine->rs.wait.proc_pending = 0; coroutine->rs.wait.proc_waiting = 0; // remove the previous poller object first if exists if (!tb_poller_remove(scheduler_io->poller, object)) { // trace tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); return tb_false; } return tb_true; } #endif // reset the pollerdata data tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object); if (pollerdata) { // clear the waiting coroutines pollerdata->lo_recv = tb_null; pollerdata->lo_send = tb_null; // remove the this poller from poller if (pollerdata->poller_events_wait) { // remove the previous poller first if exists if (!tb_poller_remove(scheduler_io->poller, object)) { // trace tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine); // failed coroutine->rs.wait.result = -1; return tb_false; } // remove the poller events coroutine->rs.wait.result = 0; pollerdata->poller_events_wait = 0; pollerdata->poller_events_save = 0; return tb_true; } } // no this poller return tb_false; } tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_self() { // get the current scheduler tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_(); // get the current io scheduler return scheduler? (tb_lo_scheduler_io_ref_t)scheduler->scheduler_io : tb_null; } tbox-1.6.7/src/tbox/coroutine/impl/stackless/scheduler_io.h 0000664 0000000 0000000 00000011526 14142237372 0024040 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler_io.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_IO_H #define TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_IO_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "scheduler.h" #include "../../../memory/fixed_pool.h" #include "../../../platform/poller.h" #include "../../../platform/impl/pollerdata.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the io poller data type typedef struct __tb_lo_pollerdata_io_t { // the suspended coroutine for waiting poller/recv tb_lo_coroutine_t* lo_recv; // the suspended coroutine for waiting poller/send tb_lo_coroutine_t* lo_send; // the waited events for poller tb_uint16_t poller_events_wait; // the saved events for poller (triggered) tb_uint16_t poller_events_save; }tb_lo_pollerdata_io_t, *tb_lo_pollerdata_io_ref_t; // the io scheduler type typedef struct __tb_lo_scheduler_io_t { // is stopped? tb_bool_t stop; // the scheduler tb_lo_scheduler_t* scheduler; // the poller tb_poller_ref_t poller; #ifndef TB_CONFIG_MICRO_ENABLE // the timer tb_timer_ref_t timer; // the low-precision timer (faster) tb_ltimer_ref_t ltimer; #endif // the poller data tb_pollerdata_t pollerdata; // the poller data pool tb_fixed_pool_ref_t pollerdata_pool; }tb_lo_scheduler_io_t, *tb_lo_scheduler_io_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init io scheduler * * @param scheduler the scheduler * * @return the io scheduler */ tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_init(tb_lo_scheduler_t* scheduler); /* exit io scheduler * * @param scheduler_io the io scheduler */ tb_void_t tb_lo_scheduler_io_exit(tb_lo_scheduler_io_ref_t scheduler_io); /* need io scheduler * * ensure the io scheduler has been initialized * * @param scheduler the scheduler * * @return the io scheduler */ tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_need(tb_lo_scheduler_t* scheduler); /* kill the current io scheduler * * @param scheduler_io the io scheduler */ tb_void_t tb_lo_scheduler_io_kill(tb_lo_scheduler_io_ref_t scheduler_io); /* sleep the current coroutine * * @param scheduler_io the io scheduler * @param interval the interval (ms), infinity: -1 */ tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval); /* wait io events * * @param scheduler_io the io scheduler * @param object the poller object * @param events the waited events * @param timeout the timeout, infinity: -1 * * @return suspend coroutine if be tb_true */ tb_bool_t tb_lo_scheduler_io_wait(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout); /* wait process status * * @param scheduler_io the io scheduler * @param object the poller object * @param timeout the timeout, infinity: -1 * * @return suspend coroutine if be tb_true */ tb_bool_t tb_lo_scheduler_io_wait_proc(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t timeout); /*! cancel io events for the given poller * * @param scheduler_io the io scheduler * @param object the poller object * * return tb_true or tb_false */ tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object); /* get the current io scheduler * * @return the io scheduler */ tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_self(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/impl/stackless/stackless.h 0000664 0000000 0000000 00000001707 14142237372 0023367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file coroutine.h * */ #ifndef TB_COROUTINE_IMPL_STACKLESS_H #define TB_COROUTINE_IMPL_STACKLESS_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "coroutine.h" #include "scheduler.h" #include "scheduler_io.h" #endif tbox-1.6.7/src/tbox/coroutine/lock.c 0000664 0000000 0000000 00000003445 14142237372 0017362 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file lock.h * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "lock" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "lock.h" #include "semaphore.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_co_lock_ref_t tb_co_lock_init() { // init lock return (tb_co_lock_ref_t)tb_co_semaphore_init(1); } tb_void_t tb_co_lock_exit(tb_co_lock_ref_t self) { // exit lock tb_co_semaphore_exit((tb_co_semaphore_ref_t)self); } tb_void_t tb_co_lock_enter(tb_co_lock_ref_t self) { // enter lock tb_co_semaphore_wait((tb_co_semaphore_ref_t)self, -1); } tb_bool_t tb_co_lock_enter_try(tb_co_lock_ref_t self) { // try to enter lock return tb_co_semaphore_wait((tb_co_semaphore_ref_t)self, 0) > 0; } tb_void_t tb_co_lock_leave(tb_co_lock_ref_t self) { // leave lock tb_co_semaphore_post((tb_co_semaphore_ref_t)self, 1); } tbox-1.6.7/src/tbox/coroutine/lock.h 0000664 0000000 0000000 00000004061 14142237372 0017362 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file lock.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_LOCK_H #define TB_COROUTINE_LOCK_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the coroutine lock ref type typedef __tb_typeref__(co_lock); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init lock * * @return the lock */ tb_co_lock_ref_t tb_co_lock_init(tb_noarg_t); /*! exit lock * * @param lock the lock */ tb_void_t tb_co_lock_exit(tb_co_lock_ref_t lock); /*! enter lock * * @param lock the lock */ tb_void_t tb_co_lock_enter(tb_co_lock_ref_t lock); /*! try to enter lock * * @param lock the lock * * @return tb_true or tb_false */ tb_bool_t tb_co_lock_enter_try(tb_co_lock_ref_t lock); /*! leave lock * * @param lock the lock */ tb_void_t tb_co_lock_leave(tb_co_lock_ref_t lock); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/prefix.h 0000664 0000000 0000000 00000001604 14142237372 0017727 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_COROUTINE_PREFIX_H #define TB_COROUTINE_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #endif tbox-1.6.7/src/tbox/coroutine/scheduler.c 0000664 0000000 0000000 00000015523 14142237372 0020410 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler.h * @ingroup scheduler * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "scheduler" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "scheduler.h" #include "impl/impl.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // the self scheduler local #ifndef __tb_thread_local__ static tb_thread_local_t g_scheduler_self = TB_THREAD_LOCAL_INIT; #endif // the global scheduler for the exclusive mode #ifdef __tb_thread_local__ static __tb_thread_local__ tb_co_scheduler_t* g_scheduler_self_ex = tb_null; #else static tb_co_scheduler_t* g_scheduler_self_ex = tb_null; #endif /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_void_t tb_co_scheduler_free(tb_list_entry_head_ref_t coroutines) { // check tb_assert(coroutines); // free all coroutines while (tb_list_entry_size(coroutines)) { // get the next entry from head tb_list_entry_ref_t entry = tb_list_entry_head(coroutines); tb_assert(entry); // remove it from the ready coroutines tb_list_entry_remove_head(coroutines); // exit this coroutine tb_coroutine_exit((tb_coroutine_t*)tb_list_entry0(entry)); } } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_co_scheduler_ref_t tb_co_scheduler_init() { // done tb_bool_t ok = tb_false; tb_co_scheduler_t* scheduler = tb_null; do { // make scheduler scheduler = tb_malloc0_type(tb_co_scheduler_t); tb_assert_and_check_break(scheduler); // init dead coroutines tb_list_entry_init(&scheduler->coroutines_dead, tb_coroutine_t, entry, tb_null); // init ready coroutines tb_list_entry_init(&scheduler->coroutines_ready, tb_coroutine_t, entry, tb_null); // init suspend coroutines tb_list_entry_init(&scheduler->coroutines_suspend, tb_coroutine_t, entry, tb_null); // init original coroutine scheduler->original.scheduler = (tb_co_scheduler_ref_t)scheduler; // init running scheduler->running = &scheduler->original; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (scheduler) tb_co_scheduler_exit((tb_co_scheduler_ref_t)scheduler); scheduler = tb_null; } // ok? return (tb_co_scheduler_ref_t)scheduler; } tb_void_t tb_co_scheduler_exit(tb_co_scheduler_ref_t self) { // check tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self; tb_assert_and_check_return(scheduler); // must be stopped tb_assert(scheduler->stopped); // exit io scheduler first if (scheduler->scheduler_io) tb_co_scheduler_io_exit(scheduler->scheduler_io); scheduler->scheduler_io = tb_null; // clear running scheduler->running = tb_null; // check coroutines tb_assert(!tb_list_entry_size(&scheduler->coroutines_ready)); tb_assert(!tb_list_entry_size(&scheduler->coroutines_suspend)); // free all dead coroutines tb_co_scheduler_free(&scheduler->coroutines_dead); // free all ready coroutines tb_co_scheduler_free(&scheduler->coroutines_ready); // free all suspend coroutines tb_co_scheduler_free(&scheduler->coroutines_suspend); // exit dead coroutines tb_list_entry_exit(&scheduler->coroutines_dead); // exit ready coroutines tb_list_entry_exit(&scheduler->coroutines_ready); // exit suspend coroutines tb_list_entry_exit(&scheduler->coroutines_suspend); // exit the scheduler tb_free(scheduler); } tb_void_t tb_co_scheduler_kill(tb_co_scheduler_ref_t self) { // check tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self; tb_assert_and_check_return(scheduler); // stop it scheduler->stopped = tb_true; // kill the io scheduler if (scheduler->scheduler_io) tb_co_scheduler_io_kill(scheduler->scheduler_io); } tb_void_t tb_co_scheduler_loop(tb_co_scheduler_ref_t self, tb_bool_t exclusive) { // check tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self; tb_assert_and_check_return(scheduler); #ifdef __tb_thread_local__ g_scheduler_self_ex = scheduler; #else // is exclusive mode? if (exclusive) g_scheduler_self_ex = scheduler; else { // init self scheduler local if (!tb_thread_local_init(&g_scheduler_self, tb_null)) return ; // update and overide the current scheduler tb_thread_local_set(&g_scheduler_self, self); } #endif #ifdef TB_CONFIG_OS_WINDOWS // we need attach poller in the current thread first for iocp/windows tb_co_scheduler_io_need(scheduler); #endif // schedule all ready coroutines while (tb_list_entry_size(&scheduler->coroutines_ready)) { // check tb_assert(tb_coroutine_is_original(scheduler->running)); // get the next entry from head tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_ready); tb_assert(entry); // switch to the next coroutine tb_co_scheduler_switch(scheduler, (tb_coroutine_t*)tb_list_entry0(entry)); // trace tb_trace_d("[loop]: ready %lu", tb_list_entry_size(&scheduler->coroutines_ready)); } // stop it scheduler->stopped = tb_true; #ifdef __tb_thread_local__ g_scheduler_self_ex = tb_null; #else // is exclusive mode? if (exclusive) g_scheduler_self_ex = tb_null; else { // clear the current scheduler tb_thread_local_set(&g_scheduler_self, tb_null); } #endif } tb_co_scheduler_ref_t tb_co_scheduler_self() { // get self scheduler on the current thread #ifdef __tb_thread_local__ return (tb_co_scheduler_ref_t)g_scheduler_self_ex; #else return (tb_co_scheduler_ref_t)(g_scheduler_self_ex? g_scheduler_self_ex : tb_thread_local_get(&g_scheduler_self)); #endif } tbox-1.6.7/src/tbox/coroutine/scheduler.h 0000664 0000000 0000000 00000004555 14142237372 0020420 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file scheduler.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_SCHEDULER_H #define TB_COROUTINE_SCHEDULER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the coroutine scheduler ref type typedef __tb_typeref__(co_scheduler); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init scheduler * * @return the scheduler */ tb_co_scheduler_ref_t tb_co_scheduler_init(tb_noarg_t); /*! exit scheduler * * @param scheduler the scheduler */ tb_void_t tb_co_scheduler_exit(tb_co_scheduler_ref_t scheduler); /* kill the scheduler * * @param scheduler the scheduler */ tb_void_t tb_co_scheduler_kill(tb_co_scheduler_ref_t scheduler); /*! run the scheduler loop * * @param schedule the scheduler * @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time, * but it will be faster using thr global scheduler instead of TLS storage */ tb_void_t tb_co_scheduler_loop(tb_co_scheduler_ref_t schedule, tb_bool_t exclusive); /*! get the scheduler of the current coroutine * * @return the scheduler */ tb_co_scheduler_ref_t tb_co_scheduler_self(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/semaphore.c 0000664 0000000 0000000 00000011457 14142237372 0020417 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file semaphore.h * @ingroup coroutine * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "semaphore" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "semaphore.h" #include "coroutine.h" #include "scheduler.h" #include "impl/impl.h" #include "../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the coroutine semaphore type typedef struct __tb_co_semaphore_t { // the semaphore value tb_size_t value; // the waiting coroutines tb_single_list_entry_head_t waiting; }tb_co_semaphore_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_co_semaphore_ref_t tb_co_semaphore_init(tb_size_t value) { // done tb_bool_t ok = tb_false; tb_co_semaphore_t* semaphore = tb_null; do { // make semaphore semaphore = tb_malloc0_type(tb_co_semaphore_t); tb_assert_and_check_break(semaphore); // init value semaphore->value = value; // init waiting coroutines tb_single_list_entry_init(&semaphore->waiting, tb_coroutine_t, rs.single_entry, tb_null); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (semaphore) tb_co_semaphore_exit((tb_co_semaphore_ref_t)semaphore); semaphore = tb_null; } // ok? return (tb_co_semaphore_ref_t)semaphore; } tb_void_t tb_co_semaphore_exit(tb_co_semaphore_ref_t self) { // check tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; tb_assert_and_check_return(semaphore); // check waiting coroutines tb_assert(!tb_single_list_entry_size(&semaphore->waiting)); // exit waiting coroutines tb_single_list_entry_exit(&semaphore->waiting); // exit the semaphore tb_free(semaphore); } tb_void_t tb_co_semaphore_post(tb_co_semaphore_ref_t self, tb_size_t post) { // check tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; tb_assert_and_check_return(semaphore); // add the semaphore value tb_size_t value = semaphore->value + post; // resume the waiting coroutines while (value && tb_single_list_entry_size(&semaphore->waiting)) { // get the next entry from head tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&semaphore->waiting); tb_assert_and_check_break(entry); // remove it from the waiting coroutines tb_single_list_entry_remove_head(&semaphore->waiting); // get the waiting coroutine tb_coroutine_ref_t coroutine = (tb_coroutine_ref_t)tb_single_list_entry(&semaphore->waiting, entry); // resume this coroutine tb_coroutine_resume(coroutine, (tb_cpointer_t)tb_true); // decrease the semaphore value value--; } // update the semaphore value semaphore->value = value; } tb_size_t tb_co_semaphore_value(tb_co_semaphore_ref_t self) { // check tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; tb_assert_and_check_return_val(semaphore, 0); // get the semaphore value return semaphore->value; } tb_long_t tb_co_semaphore_wait(tb_co_semaphore_ref_t self, tb_long_t timeout) { // check tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; tb_assert_and_check_return_val(semaphore, -1); // attempt to get the semaphore value tb_long_t ok = 1; if (semaphore->value) semaphore->value--; // no semaphore? else if (timeout) { // get the running coroutine tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self(); tb_assert(running); // save this coroutine to the waiting coroutines tb_single_list_entry_insert_tail(&semaphore->waiting, &running->rs.single_entry); // wait semaphore ok = (tb_long_t)tb_coroutine_sleep(timeout); } // timeout and no waiting else ok = 0; // ok? return ok; } tbox-1.6.7/src/tbox/coroutine/semaphore.h 0000664 0000000 0000000 00000004572 14142237372 0020424 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file semaphore.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_SEMAPHORE_H #define TB_COROUTINE_SEMAPHORE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the coroutine semaphore ref type typedef __tb_typeref__(co_semaphore); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init semaphore * * @param value the initial semaphore value * * @return the semaphore */ tb_co_semaphore_ref_t tb_co_semaphore_init(tb_size_t value); /*! exit semaphore * */ tb_void_t tb_co_semaphore_exit(tb_co_semaphore_ref_t semaphore); /*! post semaphore * * @param semaphore the semaphore * @param post the post semaphore value * */ tb_void_t tb_co_semaphore_post(tb_co_semaphore_ref_t semaphore, tb_size_t post); /*! the semaphore value * * @param semaphore the semaphore * * @return the semaphore value */ tb_size_t tb_co_semaphore_value(tb_co_semaphore_ref_t semaphore); /*! wait semaphore * * @param semaphore the semaphore * @param timeout the timeout * * @return ok: 1, timeout: 0, fail: -1 */ tb_long_t tb_co_semaphore_wait(tb_co_semaphore_ref_t semaphore, tb_long_t timeout); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/coroutine/stackless/ 0000775 0000000 0000000 00000000000 14142237372 0020254 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/coroutine/stackless/core.h 0000664 0000000 0000000 00000013502 14142237372 0021356 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file core.h * @ingroup coroutine * */ #ifndef TB_COROUTINE_STACKLESS_CORE_H #define TB_COROUTINE_STACKLESS_CORE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /* * Copyright (c) 2004-2005, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ // get core from coroutine #define tb_lo_core(co) ((tb_lo_core_ref_t)(co)) // get core state #define tb_lo_core_state(co) (tb_lo_core(co)->state) // set core state #define tb_lo_core_state_set(co, val) tb_lo_core(co)->state = (val) #ifdef TB_COMPILER_IS_GCC /* * Implementation of local continuations based on the "Labels as * values" feature of gcc * * @author Adam Dunkels
* .e.g * * "1001" => 9 * "0b1001" => 9 ** * @param s the string * * @return the uint64 number */ tb_uint64_t tb_s2tou64(tb_char_t const* s); /*! convert the octal string to uint64 * *
* .e.g * * "11" => 9 * "011" => 9 ** * @param s the string * * @return the uint64 number */ tb_uint64_t tb_s8tou64(tb_char_t const* s); /*! convert the decimal string to uint64 * * .e.g "9" => 9 * * @param s the string * * @return the uint64 number */ tb_uint64_t tb_s10tou64(tb_char_t const* s); /*! convert the hex string to uint64 * *
* .e.g * * "9" => 9 * "0x9" => 9 ** * @param s the string * * @return the uint64 number */ tb_uint64_t tb_s16tou64(tb_char_t const* s); /*! auto convert string to uint64 * *
* .e.g * * "0b1001" => 9 * "011" => 9 * "9" => 9 * "0x9" => 9 ** * @param s the string * * @return the uint64 number */ tb_uint64_t tb_stou64(tb_char_t const* s); /*! convert string to uint64 using the given base number * * @param s the string * * @return the uint64 number */ tb_uint64_t tb_sbtou64(tb_char_t const* s, tb_int_t base); #ifdef TB_CONFIG_TYPE_HAVE_FLOAT /*! convert the binary string to double * *
* .e.g * * "1001" => 9 * "0b1001" => 9 ** * @param s the string * * @return the double number */ tb_double_t tb_s2tod(tb_char_t const* s); /*! convert the binary string to double * *
* .e.g * * "11" => 9 * "011" => 9 ** * @param s the string * * @return the double number */ tb_double_t tb_s8tod(tb_char_t const* s); /*! convert the decimal string to double * * .e.g "9" => 9 * * @param s the string * * @return the double number */ tb_double_t tb_s10tod(tb_char_t const* s); /*! convert the hex string to double * *
* .e.g * * "9" => 9 * "0x9" => 9 ** * @param s the string * * @return the double number */ tb_double_t tb_s16tod(tb_char_t const* s); /*! auto convert string to double * *
* .e.g * * "0b1001" => 9 * "011" => 9 * "9" => 9 * "0x9" => 9 ** * @param s the string * * @return the double number */ tb_double_t tb_stod(tb_char_t const* s); /*! convert string to double using the given base number * * @param s the string * * @return the double number */ tb_double_t tb_sbtod(tb_char_t const* s, tb_int_t base); #endif /*! mbstowcs, convert string to wstring * * @param s1 the wstring data * @param s2 the string data * @param n the string length * * @return the wstring length */ tb_size_t tb_mbstowcs(tb_wchar_t* s1, tb_char_t const* s2, tb_size_t n); /*! wcstombs, convert wstring to string * * @param s1 the string data * @param s2 the wstring data * @param n the wstring length * * @return the string length */ tb_size_t tb_wcstombs(tb_char_t* s1, tb_wchar_t const* s2, tb_size_t n); /*! update random seed * * @param seed the random seed */ tb_void_t tb_srandom(tb_size_t seed); /*! generate the random with range: [0, max) * * @return the random value */ tb_long_t tb_random(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/libc/stdlib/wcstombs.c 0000664 0000000 0000000 00000005675 14142237372 0020465 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file wcstombs.c * @ingroup libc * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "stdlib.h" #ifdef TB_CONFIG_LIBC_HAVE_WCSTOMBS # include "setlocale.h" # include
* * ---------------- ------------------------------------------------------- * | native memory | or | data | * ---------------- ------------------------------------------------------- * | if data be null | * `---------------------------------------> | * | * ----------------------------------------------------------------------------- * | large allocator | * ----------------------------------------------------------------------------- * | | * | --------------------------------------- * | | small allocator | * | --------------------------------------- * | | * ----------------------------------------------------------------------------- * | >3KB | <=3KB | * |-----------------------------------------------------------------------------| * | default allocator | * ----------------------------------------------------------------------------- * ** * @param large_allocator the large allocator, cannot be null * * @return the allocator */ tb_allocator_ref_t tb_default_allocator_init(tb_allocator_ref_t large_allocator); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/fixed_pool.c 0000664 0000000 0000000 00000054457 14142237372 0020074 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file fixed_pool.c * @ingroup memory */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "fixed_pool" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "fixed_pool.h" #include "large_allocator.h" #include "impl/static_fixed_pool.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the item belong to this slot? #define tb_fixed_pool_slot_exists(slot, item) (((tb_byte_t*)(item) > (tb_byte_t*)(slot)) && ((tb_byte_t*)(item) < (tb_byte_t*)slot + (slot)->size)) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the fixed pool slot type typedef struct __tb_fixed_pool_slot_t { // the size: sizeof(slot) + data tb_size_t size; // the pool tb_static_fixed_pool_ref_t pool; // the list entry tb_list_entry_t entry; }tb_fixed_pool_slot_t; // the fixed pool type typedef struct __tb_fixed_pool_impl_t { // the large allocator tb_allocator_ref_t large_allocator; // the slot size tb_size_t slot_size; // the item size tb_size_t item_size; // the item count tb_size_t item_count; // the init func tb_fixed_pool_item_init_func_t func_init; // the exit func tb_fixed_pool_item_exit_func_t func_exit; // the private data tb_cpointer_t func_priv; // the current slot tb_fixed_pool_slot_t* current_slot; // the partial slot tb_list_entry_head_t partial_slots; // the full slot tb_list_entry_head_t full_slots; // the slot list tb_fixed_pool_slot_t** slot_list; // the slot count tb_size_t slot_count; // the slot space tb_size_t slot_space; // for small allocator tb_bool_t for_small; }tb_fixed_pool_t; /* ////////////////////////////////////////////////////////////////////////////////////// * declaration */ __tb_extern_c__ tb_fixed_pool_ref_t tb_fixed_pool_init_(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_bool_t for_small, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t tb_fixed_pool_item_exit(tb_pointer_t data, tb_cpointer_t priv) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)priv; tb_assert(pool && pool->func_exit); // done exit pool->func_exit(data, pool->func_priv); // continue return tb_true; } static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_t* pool, tb_fixed_pool_slot_t* slot) { // check tb_assert_and_check_return(pool && pool->large_allocator && slot); tb_assert_and_check_return(pool->slot_list && pool->slot_count); // trace tb_trace_d("slot[%lu]: exit: size: %lu", pool->item_size, slot->size); // make the iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count); tb_assert(iterator); // find the slot from the slot list tb_size_t itor = tb_binary_find_all(iterator, (tb_cpointer_t)slot); tb_assert(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]); tb_check_return(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]); // remove the slot if (itor + 1 < pool->slot_count) tb_memmov_(pool->slot_list + itor, pool->slot_list + itor + 1, (pool->slot_count - itor - 1) * sizeof(tb_fixed_pool_slot_t*)); // update the slot count pool->slot_count--; // exit slot tb_allocator_large_free(pool->large_allocator, slot); } static tb_fixed_pool_slot_t* tb_fixed_pool_slot_init(tb_fixed_pool_t* pool) { // check tb_assert_and_check_return_val(pool && pool->large_allocator && pool->slot_size && pool->item_size, tb_null); // done tb_bool_t ok = tb_false; tb_fixed_pool_slot_t* slot = tb_null; do { #ifdef __tb_debug__ // init patch for checking underflow tb_size_t patch = 1; #else tb_size_t patch = 0; #endif // the item space tb_size_t item_space = sizeof(tb_pool_data_head_t) + pool->item_size + patch; // the need space tb_size_t need_space = sizeof(tb_fixed_pool_slot_t) + pool->slot_size * item_space; // make slot tb_size_t real_space = 0; slot = (tb_fixed_pool_slot_t*)tb_allocator_large_malloc(pool->large_allocator, need_space, &real_space); tb_assert_and_check_break(slot); tb_assert_and_check_break(real_space > sizeof(tb_fixed_pool_slot_t) + item_space); // init slot slot->size = real_space; slot->pool = tb_static_fixed_pool_init((tb_byte_t*)&slot[1], real_space - sizeof(tb_fixed_pool_slot_t), pool->item_size, pool->for_small); tb_assert_and_check_break(slot->pool); // no list? if (!pool->slot_list) { // init the slot list tb_size_t size = 0; pool->slot_list = (tb_fixed_pool_slot_t**)tb_allocator_large_nalloc(pool->large_allocator, 64, sizeof(tb_fixed_pool_slot_t*), &size); tb_assert_and_check_break(pool->slot_list && size); // init the slot count pool->slot_count = 0; // init the slot space pool->slot_space = size / sizeof(tb_fixed_pool_slot_t*); tb_assert_and_check_break(pool->slot_space); } // no enough space? else if (pool->slot_count == pool->slot_space) { // grow the slot list tb_size_t size = 0; pool->slot_list = (tb_fixed_pool_slot_t**)tb_allocator_large_ralloc(pool->large_allocator, pool->slot_list, (pool->slot_space << 1) * sizeof(tb_fixed_pool_slot_t*), &size); tb_assert_and_check_break(pool->slot_list && size); // update the slot space pool->slot_space = size / sizeof(tb_fixed_pool_slot_t*); tb_assert_and_check_break(pool->slot_space); } // check tb_assert_and_check_break(pool->slot_count < pool->slot_space); // insert the slot to the slot list in the increasing order (TODO binary search) tb_size_t i = 0; tb_size_t n = pool->slot_count; for (i = 0; i < n; i++) if (slot <= pool->slot_list[i]) break; if (i < n) tb_memmov_(pool->slot_list + i + 1, pool->slot_list + i, (n - i) * sizeof(tb_fixed_pool_slot_t*)); pool->slot_list[i] = slot; // update the slot count pool->slot_count++; // trace tb_trace_d("slot[%lu]: init: size: %lu => %lu, item: %lu => %lu", pool->item_size, need_space, real_space, pool->slot_size, tb_static_fixed_pool_maxn(slot->pool)); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (slot) tb_fixed_pool_slot_exit(pool, slot); slot = tb_null; } // ok? return slot; } #if 0 static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_t* pool, tb_pointer_t data) { // check tb_assert_and_check_return_val(pool && data, tb_null); // done tb_fixed_pool_slot_t* slot = tb_null; do { // belong to the current slot? if (pool->current_slot && tb_fixed_pool_slot_exists(pool->current_slot, data)) { slot = pool->current_slot; break; } // find the slot from the partial slots tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&pool->partial_slots), partial_slot) { // is this? if (tb_fixed_pool_slot_exists(partial_slot, data)) { slot = partial_slot; break; } } // no found? tb_check_break(!slot); // find the slot from the full slots tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&pool->full_slots), full_slot) { // is this? if (tb_fixed_pool_slot_exists(full_slot, data)) { slot = full_slot; break; } } } while (0); // ok? return slot; } #else static tb_long_t tb_fixed_pool_slot_comp(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t data) { // the slot tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)item; tb_assert(slot); // comp return (tb_byte_t*)data < (tb_byte_t*)slot? 1 : ((tb_byte_t*)data >= (tb_byte_t*)slot + slot->size? -1 : 0); } static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_t* pool, tb_pointer_t data) { // check tb_assert_and_check_return_val(pool && data, tb_null); // make the iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count); tb_assert(iterator); // find it tb_size_t itor = tb_binary_find_all_if(iterator, tb_fixed_pool_slot_comp, data); tb_check_return_val(itor != tb_iterator_tail(iterator), tb_null); // the slot tb_fixed_pool_slot_t* slot = pool->slot_list[itor]; tb_assert_and_check_return_val(slot, tb_null); // check tb_assert(tb_fixed_pool_slot_exists(slot, data)); // ok? return slot; } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_fixed_pool_ref_t tb_fixed_pool_init_(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_bool_t for_small, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(item_size, tb_null); // done tb_bool_t ok = tb_false; tb_fixed_pool_t* pool = tb_null; do { // no allocator? uses the global allocator if (!large_allocator) large_allocator = tb_allocator(); tb_assert_and_check_break(large_allocator); // make pool pool = (tb_fixed_pool_t*)tb_allocator_large_malloc0(large_allocator, sizeof(tb_fixed_pool_t), tb_null); tb_assert_and_check_break(pool); // init pool pool->large_allocator = large_allocator; pool->slot_size = slot_size? slot_size : (tb_page_size() >> 4); pool->item_size = item_size; pool->func_init = item_init; pool->func_exit = item_exit; pool->func_priv = priv; pool->for_small = for_small; tb_assert_and_check_break(pool->slot_size); // init partial slots tb_list_entry_init(&pool->partial_slots, tb_fixed_pool_slot_t, entry, tb_null); // init full slots tb_list_entry_init(&pool->full_slots, tb_fixed_pool_slot_t, entry, tb_null); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (pool) tb_fixed_pool_exit((tb_fixed_pool_ref_t)pool); pool = tb_null; } // ok? return (tb_fixed_pool_ref_t)pool; } tb_fixed_pool_ref_t tb_fixed_pool_init(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv) { return tb_fixed_pool_init_(large_allocator, slot_size, item_size, tb_false, item_init, item_exit, priv); } tb_void_t tb_fixed_pool_exit(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return(pool); // clear it tb_fixed_pool_clear(self); // exit the current slot if (pool->current_slot) tb_fixed_pool_slot_exit(pool, pool->current_slot); pool->current_slot = tb_null; // exit the slot list if (pool->slot_list) tb_allocator_large_free(pool->large_allocator, pool->slot_list); pool->slot_list = tb_null; pool->slot_count = 0; pool->slot_space = 0; // exit it tb_allocator_large_free(pool->large_allocator, pool); } tb_size_t tb_fixed_pool_size(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, 0); // the item count return pool->item_count; } tb_size_t tb_fixed_pool_item_size(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, 0); // the item size return pool->item_size; } tb_void_t tb_fixed_pool_clear(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return(pool); // exit items if (pool->func_exit) tb_fixed_pool_walk(self, tb_fixed_pool_item_exit, (tb_pointer_t)pool); // exit the partial slots tb_iterator_ref_t partial_iterator = tb_list_entry_itor(&pool->partial_slots); if (partial_iterator) { // walk it tb_size_t itor = tb_iterator_head(partial_iterator); while (itor != tb_iterator_tail(partial_iterator)) { // the slot tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)tb_iterator_item(partial_iterator, itor); tb_assert_and_check_break(slot); // check tb_assert(slot != pool->current_slot); // save next tb_size_t next = tb_iterator_next(partial_iterator, itor); // exit slot tb_fixed_pool_slot_exit(pool, slot); // next itor = next; } } // exit the full slots tb_iterator_ref_t full_iterator = tb_list_entry_itor(&pool->full_slots); if (full_iterator) { // walk it tb_size_t itor = tb_iterator_head(full_iterator); while (itor != tb_iterator_tail(full_iterator)) { // the slot tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)tb_iterator_item(full_iterator, itor); tb_assert_and_check_break(slot); // check tb_assert(slot != pool->current_slot); // save next tb_size_t next = tb_iterator_next(full_iterator, itor); // exit slot tb_fixed_pool_slot_exit(pool, slot); // next itor = next; } } // clear current slot if (pool->current_slot && pool->current_slot->pool) tb_static_fixed_pool_clear(pool->current_slot->pool); // clear item count pool->item_count = 0; // clear partial slots tb_list_entry_clear(&pool->partial_slots); // clear full slots tb_list_entry_clear(&pool->full_slots); } tb_pointer_t tb_fixed_pool_malloc_(tb_fixed_pool_ref_t self __tb_debug_decl__) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, tb_null); // done tb_bool_t ok = tb_false; tb_pointer_t data = tb_null; do { // no current slot or the current slot is full? update the current slot if (!pool->current_slot || tb_static_fixed_pool_full(pool->current_slot->pool)) { // move the current slot to the full slots if exists if (pool->current_slot) tb_list_entry_insert_tail(&pool->full_slots, &pool->current_slot->entry); // clear the current slot pool->current_slot = tb_null; // attempt to get a slot from the partial slots if (!tb_list_entry_is_null(&pool->partial_slots)) { // the head entry tb_list_entry_ref_t entry = tb_list_entry_head(&pool->partial_slots); tb_assert_and_check_break(entry); // the head slot pool->current_slot = (tb_fixed_pool_slot_t*)tb_list_entry(&pool->partial_slots, entry); tb_assert_and_check_break(pool->current_slot); // remove this slot from the partial slots tb_list_entry_remove(&pool->partial_slots, entry); } // make a new slot else pool->current_slot = tb_fixed_pool_slot_init(pool); } // check tb_assert_and_check_break(pool->current_slot && pool->current_slot->pool); tb_assert_and_check_break(!tb_static_fixed_pool_full(pool->current_slot->pool)); // make data from the current slot data = tb_static_fixed_pool_malloc(pool->current_slot->pool __tb_debug_args__); tb_assert_and_check_break(data); // done init if (pool->func_init && !pool->func_init(data, pool->func_priv)) break; // update the item count pool->item_count++; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit data if (data && pool->current_slot && pool->current_slot->pool) tb_static_fixed_pool_free(pool->current_slot->pool, data __tb_debug_args__); data = tb_null; } // check tb_assertf(data, "malloc(%lu) failed!", pool->item_size); // ok? return data; } tb_pointer_t tb_fixed_pool_malloc0_(tb_fixed_pool_ref_t self __tb_debug_decl__) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, tb_null); // done tb_pointer_t data = tb_fixed_pool_malloc_(self __tb_debug_args__); tb_assert_and_check_return_val(data, tb_null); // clear it tb_memset_(data, 0, pool->item_size); // ok return data; } tb_bool_t tb_fixed_pool_free_(tb_fixed_pool_ref_t self, tb_pointer_t data __tb_debug_decl__) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, tb_false); // done tb_bool_t ok = tb_false; do { // check tb_assertf_pass_and_check_break(pool->item_count, "double free data: %p", data); // find the slot tb_fixed_pool_slot_t* slot = tb_fixed_pool_slot_find(pool, data); tb_assertf_pass_and_check_break(slot, "the data: %p not belong to pool: %p", data, self); tb_assert_pass_and_check_break(slot->pool); // the slot is full? tb_bool_t full = tb_static_fixed_pool_full(slot->pool); // done exit if (pool->func_exit) pool->func_exit(data, pool->func_priv); // free it if (!tb_static_fixed_pool_free(slot->pool, data __tb_debug_args__)) break; // not the current slot? if (slot != pool->current_slot) { // is full? move the slot to the partial slots if (full) { tb_list_entry_remove(&pool->full_slots, &slot->entry); tb_list_entry_insert_tail(&pool->partial_slots, &slot->entry); } // is null? exit the slot else if (tb_static_fixed_pool_null(slot->pool)) { tb_list_entry_remove(&pool->partial_slots, &slot->entry); tb_fixed_pool_slot_exit(pool, slot); } } // update the item count pool->item_count--; // ok ok = tb_true; } while (0); // failed? dump it #ifdef __tb_debug__ if (!ok) { // trace tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[fixed_pool]: [error]: "); // abort tb_abort(); } #endif // ok? return ok; } tb_void_t tb_fixed_pool_walk(tb_fixed_pool_ref_t self, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return(pool && func); // walk the current slot first if (pool->current_slot && pool->current_slot->pool) tb_static_fixed_pool_walk(pool->current_slot->pool, func, priv); // walk the partial slots tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&pool->partial_slots), partial_slot && partial_slot->pool) { // check tb_assert(!tb_static_fixed_pool_full(partial_slot->pool)); // walk tb_static_fixed_pool_walk(partial_slot->pool, func, priv); } // walk the full slots tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&pool->full_slots), full_slot && full_slot->pool) { // check tb_assert(tb_static_fixed_pool_full(full_slot->pool)); // walk tb_static_fixed_pool_walk(full_slot->pool, func, priv); } } #ifdef __tb_debug__ tb_void_t tb_fixed_pool_dump(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return(pool); // dump the current slot first if (pool->current_slot && pool->current_slot->pool) tb_static_fixed_pool_dump(pool->current_slot->pool); // dump the partial slots tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&pool->partial_slots), partial_slot && partial_slot->pool) { // check tb_assert(!tb_static_fixed_pool_full(partial_slot->pool)); // dump tb_static_fixed_pool_dump(partial_slot->pool); } // dump the full slots tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&pool->full_slots), full_slot && full_slot->pool) { // check tb_assert(tb_static_fixed_pool_full(full_slot->pool)); // dump tb_static_fixed_pool_dump(full_slot->pool); } } #endif tbox-1.6.7/src/tbox/memory/fixed_pool.h 0000664 0000000 0000000 00000017420 14142237372 0020066 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file fixed_pool.h * @ingroup memory * */ #ifndef TB_MEMORY_FIXED_POOL_H #define TB_MEMORY_FIXED_POOL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "large_allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ #define tb_fixed_pool_malloc(pool) tb_fixed_pool_malloc_(pool __tb_debug_vals__) #define tb_fixed_pool_malloc0(pool) tb_fixed_pool_malloc0_(pool __tb_debug_vals__) #define tb_fixed_pool_free(pool, item) tb_fixed_pool_free_(pool, (tb_pointer_t)(item) __tb_debug_vals__) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the fixed pool ref type * *
* * current: * ----------- * | | * -------------- | * | slot |<-- * |--------------| * |||||||||||||||| * |--------------| * | | * |--------------| * | | * |--------------| * |||||||||||||||| * |--------------| * |||||||||||||||| * |--------------| * | | * -------------- * * partial: * * -------------- -------------- -------------- * | slot | <=> | slot | <=> ... <=> | slot | * |--------------| |--------------| |--------------| * |||||||||||||||| | | | | * |--------------| |--------------| |--------------| * | | |||||||||||||||| | | * |--------------| |--------------| |--------------| * | | |||||||||||||||| |||||||||||||||| * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| | | * |--------------| |--------------| |--------------| * |||||||||||||||| | | | | * |--------------| |--------------| |--------------| * | | | | |||||||||||||||| * -------------- -------------- -------------- * * full: * * -------------- -------------- -------------- * | slot | <=> | slot | <=> ... <=> | slot | * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| |||||||||||||||| * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| |||||||||||||||| * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| |||||||||||||||| * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| |||||||||||||||| * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| |||||||||||||||| * |--------------| |--------------| |--------------| * |||||||||||||||| |||||||||||||||| |||||||||||||||| * -------------- -------------- -------------- * * slot: * * -------------- ------------------------>| * | head | | * |--------------| | * ||| item | | * |--------------| | * ||| item | | * |--------------| | data * ||| item | | * |--------------| | * | ... | | * |--------------| | * ||| item | | * -------------- ------------------------>| * **/ typedef __tb_typeref__(fixed_pool); /// the item init func type typedef tb_bool_t (*tb_fixed_pool_item_init_func_t)(tb_pointer_t data, tb_cpointer_t priv); /// the item exit func type typedef tb_void_t (*tb_fixed_pool_item_exit_func_t)(tb_pointer_t data, tb_cpointer_t priv); /// the item walk func type typedef tb_bool_t (*tb_fixed_pool_item_walk_func_t)(tb_pointer_t data, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init fixed pool * * @param large_allocator the large allocator, uses the global allocator if be null * @param slot_size the item count per-slot, using the default size if be zero * @param item_size the item size * @param item_init the item init func * @param item_exit the item exit func * @param priv the private data * * @return the pool */ tb_fixed_pool_ref_t tb_fixed_pool_init(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv); /*! exit pool * * @param pool the pool */ tb_void_t tb_fixed_pool_exit(tb_fixed_pool_ref_t pool); /*! the item count * * @param pool the pool * * @return the item count */ tb_size_t tb_fixed_pool_size(tb_fixed_pool_ref_t pool); /*! the item size * * @param pool the pool * * @return the item size */ tb_size_t tb_fixed_pool_item_size(tb_fixed_pool_ref_t pool); /*! clear pool * * @param pool the pool */ tb_void_t tb_fixed_pool_clear(tb_fixed_pool_ref_t pool); /*! malloc data * * @param pool the pool * * @return the data */ tb_pointer_t tb_fixed_pool_malloc_(tb_fixed_pool_ref_t pool __tb_debug_decl__); /*! malloc data and clear it * * @param pool the pool * * @return the data */ tb_pointer_t tb_fixed_pool_malloc0_(tb_fixed_pool_ref_t pool __tb_debug_decl__); /*! free data * * @param pool the pool * @param data the data * * @return tb_true or tb_false */ tb_bool_t tb_fixed_pool_free_(tb_fixed_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__); /*! walk item * * @code tb_bool_t tb_fixed_pool_item_func(tb_pointer_t data, tb_cpointer_t priv) { // ok or break return tb_true; } * @endcode * * @param pool the pool * @param func the walk func * @param priv the private data */ tb_void_t tb_fixed_pool_walk(tb_fixed_pool_ref_t pool, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv); #ifdef __tb_debug__ /*! dump pool * * @param pool the pool */ tb_void_t tb_fixed_pool_dump(tb_fixed_pool_ref_t pool); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/impl/ 0000775 0000000 0000000 00000000000 14142237372 0016522 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/memory/impl/impl.h 0000664 0000000 0000000 00000001721 14142237372 0017635 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file impl.h * */ #ifndef TB_MEMORY_IMPL_H #define TB_MEMORY_IMPL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "memory.h" #include "native_large_allocator.h" #include "static_large_allocator.h" #endif tbox-1.6.7/src/tbox/memory/impl/memory.c 0000664 0000000 0000000 00000004343 14142237372 0020202 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file memory.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "memory" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "memory.h" #include "../memory.h" #include "../../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // the allocator __tb_extern_c__ extern tb_allocator_ref_t g_allocator; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_memory_init_env(tb_allocator_ref_t allocator) { // done tb_bool_t ok = tb_false; do { // init page if (!tb_page_init()) break; // init the native memory if (!tb_native_memory_init()) break; // init the allocator #if defined(TB_CONFIG_MICRO_ENABLE) || \ (defined(__tb_small__) && !defined(__tb_debug__)) g_allocator = allocator? allocator : tb_native_allocator(); #else g_allocator = allocator? allocator : tb_default_allocator(tb_null, 0); #endif tb_assert_and_check_break(g_allocator); // ok ok = tb_true; } while (0); // failed? exit it if (!ok) tb_memory_exit_env(); // ok? return ok; } tb_void_t tb_memory_exit_env() { // exit the native memory tb_native_memory_exit(); // exit page tb_page_exit(); } tbox-1.6.7/src/tbox/memory/impl/memory.h 0000664 0000000 0000000 00000003035 14142237372 0020204 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file memory.h * @ingroup memory * */ #ifndef TB_MEMORY_IMPL_MEMORY_H #define TB_MEMORY_IMPL_MEMORY_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init memory environment * * @param allocator the allocator * * @return tb_true or tb_false */ tb_bool_t tb_memory_init_env(tb_allocator_ref_t allocator); // exit memory environment tb_void_t tb_memory_exit_env(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/impl/native_large_allocator.c 0000664 0000000 0000000 00000052766 14142237372 0023406 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file native_large_allocator.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "native_large_allocator" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "native_large_allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the native large allocator data size #define tb_native_large_allocator_data_base(data_head) (&(((tb_pool_data_head_t*)((tb_native_large_data_head_t*)(data_head) + 1))[-1])) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the native large data head type typedef __tb_pool_data_aligned__ struct __tb_native_large_data_head_t { #ifdef __tb_debug__ // the allocator reference tb_pointer_t allocator; #endif // the entry tb_list_entry_t entry; // the data head base tb_byte_t base[sizeof(tb_pool_data_head_t)]; }__tb_pool_data_aligned__ tb_native_large_data_head_t; /*! the native large allocator type * *
* ----------- ----------- ----------- * ||| data | <=> ||| data | <=> ... <=> ||| data | <=> | * ----------- ----------- ----------- | * | | * `------------------------------------------------------` **/ typedef struct __tb_native_large_allocator_t { // the base tb_allocator_t base; // the data list tb_list_entry_head_t data_list; #ifdef __tb_debug__ // the peak size tb_size_t peak_size; // the total size tb_size_t total_size; // the real size tb_size_t real_size; // the occupied size tb_size_t occupied_size; // the malloc count tb_size_t malloc_count; // the ralloc count tb_size_t ralloc_count; // the free count tb_size_t free_count; #endif }tb_native_large_allocator_t, *tb_native_large_allocator_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ #ifdef __tb_debug__ static tb_void_t tb_native_large_allocator_check_data(tb_native_large_allocator_ref_t allocator, tb_native_large_data_head_t const* data_head) { // check tb_assert_and_check_return(allocator && data_head); // done tb_bool_t ok = tb_false; tb_byte_t const* data = (tb_byte_t const*)&(data_head[1]); do { // the base head tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head); // check tb_assertf_pass_break(base_head->debug.magic != (tb_uint16_t)~TB_POOL_DATA_MAGIC, "data have been freed: %p", data); tb_assertf_pass_break(base_head->debug.magic == TB_POOL_DATA_MAGIC, "the invalid data: %p", data); tb_assertf_pass_break(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow"); // ok ok = tb_true; } while (0); // failed? dump it #ifdef __tb_debug__ if (!ok) { // dump data tb_pool_data_dump(data, tb_true, "[native_large_allocator]: [error]: "); // abort tb_abort(); } #endif } static tb_void_t tb_native_large_allocator_check_last(tb_native_large_allocator_ref_t allocator) { // check tb_assert_and_check_return(allocator); // non-empty? if (!tb_list_entry_is_null(&allocator->data_list)) { // the last entry tb_list_entry_ref_t data_last = tb_list_entry_last(&allocator->data_list); tb_assert_and_check_return(data_last); // check it tb_native_large_allocator_check_data(allocator, (tb_native_large_data_head_t*)tb_list_entry(&allocator->data_list, data_last)); } } static tb_void_t tb_native_large_allocator_check_prev(tb_native_large_allocator_ref_t allocator, tb_native_large_data_head_t const* data_head) { // check tb_assert_and_check_return(allocator && data_head); // non-empty? if (!tb_list_entry_is_null(&allocator->data_list)) { // the prev entry tb_list_entry_ref_t data_prev = tb_list_entry_prev((tb_list_entry_ref_t)&data_head->entry); tb_assert_and_check_return(data_prev); // not tail entry tb_check_return(data_prev != tb_list_entry_tail(&allocator->data_list)); // check it tb_native_large_allocator_check_data(allocator, (tb_native_large_data_head_t*)tb_list_entry(&allocator->data_list, data_prev)); } } static tb_void_t tb_native_large_allocator_check_next(tb_native_large_allocator_ref_t allocator, tb_native_large_data_head_t const* data_head) { // check tb_assert_and_check_return(allocator && data_head); // non-empty? if (!tb_list_entry_is_null(&allocator->data_list)) { // the next entry tb_list_entry_ref_t data_next = tb_list_entry_next((tb_list_entry_ref_t)&data_head->entry); tb_assert_and_check_return(data_next); // not tail entry tb_check_return(data_next != tb_list_entry_tail(&allocator->data_list)); // check it tb_native_large_allocator_check_data(allocator, (tb_native_large_data_head_t*)tb_list_entry(&allocator->data_list, data_next)); } } #endif static tb_pointer_t tb_native_large_allocator_malloc(tb_allocator_ref_t self, tb_size_t size, tb_size_t* real __tb_debug_decl__) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return_val(allocator, tb_null); // done #ifdef __tb_debug__ tb_size_t patch = 1; // patch 0xcc #else tb_size_t patch = 0; #endif tb_bool_t ok = tb_false; tb_size_t need = sizeof(tb_native_large_data_head_t) + size + patch; tb_byte_t* data = tb_null; tb_byte_t* data_real = tb_null; tb_native_large_data_head_t* data_head = tb_null; do { #ifdef __tb_debug__ // check the last data tb_native_large_allocator_check_last(allocator); #endif // make data data = (tb_byte_t*)(size >= TB_VIRTUAL_MEMORY_DATA_MINN? tb_virtual_memory_malloc(need) : tb_native_memory_malloc(need)); tb_assert_and_check_break(data); tb_assert_and_check_break(!(((tb_size_t)data) & 0x1)); // make the real data data_real = data + sizeof(tb_native_large_data_head_t); // init the data head data_head = (tb_native_large_data_head_t*)data; // the base head tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head); // save the real size base_head->size = (tb_uint32_t)size; #ifdef __tb_debug__ base_head->debug.magic = TB_POOL_DATA_MAGIC; base_head->debug.file = file_; base_head->debug.func = func_; base_head->debug.line = (tb_uint16_t)line_; // save backtrace tb_pool_data_save_backtrace(&base_head->debug, 5); // make the dirty data and patch 0xcc for checking underflow tb_memset_(data_real, TB_POOL_DATA_PATCH, size + patch); // save allocator reference for checking data range data_head->allocator = (tb_pointer_t)allocator; #endif // save the data to the data_list tb_list_entry_insert_tail(&allocator->data_list, &data_head->entry); // save the real size if (real) *real = size; #ifdef __tb_debug__ // update the real size allocator->real_size += size; // update the occupied size allocator->occupied_size += need - TB_POOL_DATA_HEAD_DIFF_SIZE - patch; // update the total size allocator->total_size += size; // update the peak size if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size; // update the malloc count allocator->malloc_count++; #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit the data if (data) tb_native_memory_free(data); data = tb_null; data_real = tb_null; } // ok? return (tb_pointer_t)data_real; } static tb_pointer_t tb_native_large_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return_val(allocator, tb_null); // done #ifdef __tb_debug__ tb_size_t patch = 1; // patch 0xcc #else tb_size_t patch = 0; #endif tb_bool_t ok = tb_false; tb_bool_t removed = tb_false; tb_size_t need = sizeof(tb_native_large_data_head_t) + size + patch; tb_byte_t* data_real = tb_null; tb_native_large_data_head_t* data_head = tb_null; do { // the data head data_head = &(((tb_native_large_data_head_t*)data)[-1]); // the base head tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head); // check tb_assertf(base_head->debug.magic != (tb_uint16_t)~TB_POOL_DATA_MAGIC, "ralloc freed data: %p", data); tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data); tb_assertf(data_head->allocator == (tb_pointer_t)allocator, "the data: %p not belong to allocator: %p", data, allocator); tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow"); #ifdef __tb_debug__ // check the last data tb_native_large_allocator_check_last(allocator); // check the prev data tb_native_large_allocator_check_prev(allocator, data_head); // check the next data tb_native_large_allocator_check_next(allocator, data_head); // update the real size allocator->real_size -= base_head->size; // update the occupied size allocator->occupied_size -= base_head->size; // update the total size allocator->total_size -= base_head->size; // the previous size tb_size_t prev_size = base_head->size; #endif // remove the data from the data_list tb_list_entry_remove(&allocator->data_list, &data_head->entry); removed = tb_true; // ralloc data if (size >= TB_VIRTUAL_MEMORY_DATA_MINN) { if (base_head->size >= TB_VIRTUAL_MEMORY_DATA_MINN) data = (tb_byte_t*)tb_virtual_memory_ralloc(data_head, need); else { data = (tb_byte_t*)tb_virtual_memory_malloc(need); if (data) { tb_memcpy_(data, data_head, base_head->size); tb_native_memory_free(data_head); } } } else { if (base_head->size < TB_VIRTUAL_MEMORY_DATA_MINN) data = (tb_byte_t*)tb_native_memory_ralloc(data_head, need); else { data = (tb_byte_t*)tb_native_memory_malloc(need); if (data) { tb_memcpy_(data, data_head, base_head->size); tb_virtual_memory_free(data_head); } } } tb_assert_and_check_break(data); tb_assert_and_check_break(!(((tb_size_t)data) & 0x1)); // update the real data data_real = (tb_byte_t*)data + sizeof(tb_native_large_data_head_t); // update the data head data_head = (tb_native_large_data_head_t*)data; // update the base head base_head = tb_native_large_allocator_data_base(data_head); // save the real size base_head->size = (tb_uint32_t)size; #ifdef __tb_debug__ base_head->debug.file = file_; base_head->debug.func = func_; base_head->debug.line = (tb_uint16_t)line_; // check tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc data have been changed: %p", data); // update backtrace tb_pool_data_save_backtrace(&base_head->debug, 5); // make the dirty data if (size > prev_size) tb_memset_(data_real + prev_size, TB_POOL_DATA_PATCH, size - prev_size); // patch 0xcc for checking underflow data_real[size] = TB_POOL_DATA_PATCH; #endif // save the data to the data_list tb_list_entry_insert_tail(&allocator->data_list, &data_head->entry); removed = tb_false; // save the real size if (real) *real = size; #ifdef __tb_debug__ // update the real size allocator->real_size += size; // update the occupied size allocator->occupied_size += size; // update the total size allocator->total_size += size; // update the peak size if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size; // update the ralloc count allocator->ralloc_count++; #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // restore data to data_list if (data_head && removed) tb_list_entry_insert_tail(&allocator->data_list, &data_head->entry); // clear it data = tb_null; data_real = tb_null; } // ok? return (tb_pointer_t)data_real; } static tb_bool_t tb_native_large_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return_val(allocator && data, tb_false); // done tb_bool_t ok = tb_false; tb_native_large_data_head_t* data_head = tb_null; do { // the data head data_head = &(((tb_native_large_data_head_t*)data)[-1]); // the base head tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head); // check tb_assertf(base_head->debug.magic != (tb_uint16_t)~TB_POOL_DATA_MAGIC, "double free data: %p", data); tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data); tb_assertf(data_head->allocator == (tb_pointer_t)allocator, "the data: %p not belong to allocator: %p", data, allocator); tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow"); #ifdef __tb_debug__ // check the last data tb_native_large_allocator_check_last(allocator); // check the prev data tb_native_large_allocator_check_prev(allocator, data_head); // check the next data tb_native_large_allocator_check_next(allocator, data_head); // for checking double-free base_head->debug.magic = (tb_uint16_t)~TB_POOL_DATA_MAGIC; // update the total size allocator->total_size -= base_head->size; // update the free count allocator->free_count++; #endif // remove the data from the data_list tb_list_entry_remove(&allocator->data_list, &data_head->entry); // free it if (base_head->size >= TB_VIRTUAL_MEMORY_DATA_MINN) tb_virtual_memory_free(data_head); else tb_native_memory_free(data_head); // ok ok = tb_true; } while (0); // ok? return ok; } static tb_void_t tb_native_large_allocator_clear(tb_allocator_ref_t self) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return(allocator); // done do { // the iterator tb_iterator_ref_t iterator = tb_list_entry_itor(&allocator->data_list); tb_assert_and_check_break(iterator); // walk it tb_size_t itor = tb_iterator_head(iterator); while (itor != tb_iterator_tail(iterator)) { // the data head tb_native_large_data_head_t* data_head = (tb_native_large_data_head_t*)tb_iterator_item(iterator, itor); tb_assert_and_check_break(data_head); // save next tb_size_t next = tb_iterator_next(iterator, itor); // exit data tb_native_large_allocator_free(self, (tb_pointer_t)&data_head[1] __tb_debug_vals__); // next itor = next; } } while (0); // clear info #ifdef __tb_debug__ allocator->peak_size = 0; allocator->total_size = 0; allocator->real_size = 0; allocator->occupied_size = 0; allocator->malloc_count = 0; allocator->ralloc_count = 0; allocator->free_count = 0; #endif } static tb_void_t tb_native_large_allocator_exit(tb_allocator_ref_t self) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return(allocator); // exit lock tb_spinlock_exit(&allocator->base.lock); // exit it tb_native_memory_free(allocator); } #ifdef __tb_debug__ static tb_void_t tb_native_large_allocator_dump(tb_allocator_ref_t self) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return(allocator); // trace tb_trace_i(""); // exit all data_list tb_for_all_if (tb_native_large_data_head_t*, data_head, tb_list_entry_itor(&allocator->data_list), data_head) { // check it tb_native_large_allocator_check_data(allocator, data_head); // trace tb_trace_e("leak: %p", &data_head[1]); // dump data tb_pool_data_dump((tb_byte_t const*)&data_head[1], tb_false, "[native_large_allocator]: [error]: "); } // trace debug info tb_trace_i("peak_size: %lu", allocator->peak_size); tb_trace_i("wast_rate: %llu/10000", allocator->occupied_size? (((tb_hize_t)allocator->occupied_size - allocator->real_size) * 10000) / (tb_hize_t)allocator->occupied_size : 0); tb_trace_i("free_count: %lu", allocator->free_count); tb_trace_i("malloc_count: %lu", allocator->malloc_count); tb_trace_i("ralloc_count: %lu", allocator->ralloc_count); } static tb_bool_t tb_native_large_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data) { // check tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self; tb_assert_and_check_return_val(allocator, tb_false); /* always ok for checking memory * * TODO: need better implementation for distinguishing it */ return tb_true; } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_native_large_allocator_init() { // done tb_bool_t ok = tb_false; tb_native_large_allocator_ref_t allocator = tb_null; do { // check tb_assert_static(!(sizeof(tb_native_large_data_head_t) & (TB_POOL_DATA_ALIGN - 1))); // make allocator allocator = (tb_native_large_allocator_ref_t)tb_native_memory_malloc0(sizeof(tb_native_large_allocator_t)); tb_assert_and_check_break(allocator); // init base allocator->base.type = TB_ALLOCATOR_TYPE_LARGE; allocator->base.flag = TB_ALLOCATOR_FLAG_NONE; allocator->base.large_malloc = tb_native_large_allocator_malloc; allocator->base.large_ralloc = tb_native_large_allocator_ralloc; allocator->base.large_free = tb_native_large_allocator_free; allocator->base.clear = tb_native_large_allocator_clear; allocator->base.exit = tb_native_large_allocator_exit; #ifdef __tb_debug__ allocator->base.dump = tb_native_large_allocator_dump; allocator->base.have = tb_native_large_allocator_have; #endif // init lock if (!tb_spinlock_init(&allocator->base.lock)) break; // init data_list tb_list_entry_init(&allocator->data_list, tb_native_large_data_head_t, entry, tb_null); // register lock profiler #ifdef TB_LOCK_PROFILER_ENABLE tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&allocator->base.lock, TB_TRACE_MODULE_NAME); #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (allocator) tb_native_large_allocator_exit((tb_allocator_ref_t)allocator); allocator = tb_null; } // ok? return (tb_allocator_ref_t)allocator; } tbox-1.6.7/src/tbox/memory/impl/native_large_allocator.h 0000664 0000000 0000000 00000002754 14142237372 0023403 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file native_large_allocator.h * */ #ifndef TB_MEMORY_IMPL_NATIVE_LARGE_ALLOCATOR_H #define TB_MEMORY_IMPL_NATIVE_LARGE_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init the native large allocator and the allocated data will be aligned by the page size * * @return the allocator */ tb_allocator_ref_t tb_native_large_allocator_init(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/impl/prefix.c 0000664 0000000 0000000 00000013223 14142237372 0020164 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../../tbox.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ #ifdef __tb_debug__ __tb_no_sanitize_address__ tb_size_t tb_pool_data_size(tb_cpointer_t data) { // check tb_check_return_val(data, 0); // done tb_size_t size = 0; tb_pool_data_head_t* data_head = tb_null; do { // tbox must be running normally tb_check_break(tb_state() == TB_STATE_OK); // get global allocator tb_allocator_ref_t allocator = tb_allocator(); tb_check_break(allocator); // have this data address? tb_check_break(tb_allocator_have(allocator, data)); // the data head data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_check_break(data_head->debug.magic == TB_POOL_DATA_MAGIC); // ok size = data_head->size; } while (0); // ok? return size; } tb_void_t tb_pool_data_dump(tb_cpointer_t data, tb_bool_t verbose, tb_char_t const* prefix) { // done tb_pool_data_head_t* data_head = tb_null; do { // no data? tb_assert_and_check_break(data); // the data head data_head = &(((tb_pool_data_head_t*)data)[-1]); // dump the head info tb_size_t data_limit = 256; if (data_head->debug.magic == TB_POOL_DATA_MAGIC) { // the data size tb_size_t data_size = (tb_size_t)data_head->size; // format the backtrace prefix tb_char_t backtrace_prefix[256] = {0}; tb_snprintf(backtrace_prefix, sizeof(backtrace_prefix), "%s ", prefix? prefix : ""); // dump backtrace tb_size_t nframe = 0; while (nframe < tb_arrayn(data_head->debug.backtrace) && data_head->debug.backtrace[nframe]) nframe++; tb_trace_i("%sdata: from: %s(): %u, %s", prefix? prefix : "", data_head->debug.func, data_head->debug.line, data_head->debug.file); tb_backtrace_dump(backtrace_prefix, data_head->debug.backtrace, nframe); // dump the data info tb_trace_i("%sdata: %p, size: %lu, patch: %x", prefix? prefix : "", data, data_size, ((tb_byte_t const*)data)[data_size]); // dump the first 256-bytes data if (data_size && verbose) { // the dump size tb_size_t dump_size = tb_min(data_size, data_limit); // dump it tb_trace_i("%sdata: first %lu-bytes:", prefix? prefix : "", dump_size); tb_dump_data((tb_byte_t const*)data, dump_size); // dump the last 256-bytes data if (data_size > dump_size) { // the last data tb_byte_t const* data_last = tb_max((tb_byte_t const*)data + data_size - data_limit, (tb_byte_t const*)data + dump_size); // update the dump size dump_size = (tb_byte_t const*)data + data_size - data_last; // dump it tb_trace_i("%sdata: last %lu-bytes:", prefix? prefix : "", dump_size); tb_dump_data(data_last, dump_size); } } } // for the public fixed_pool else if (data_head->debug.magic == TB_POOL_DATA_EMPTY_MAGIC) { // format the backtrace prefix tb_char_t backtrace_prefix[256] = {0}; tb_snprintf(backtrace_prefix, sizeof(backtrace_prefix), "%s ", prefix? prefix : ""); // dump backtrace tb_size_t nframe = 0; while (nframe < tb_arrayn(data_head->debug.backtrace) && data_head->debug.backtrace[nframe]) nframe++; tb_trace_i("%sdata: from: %s(): %u, %s", prefix? prefix : "", data_head->debug.func, data_head->debug.line, data_head->debug.file); tb_backtrace_dump(backtrace_prefix, data_head->debug.backtrace, nframe); // dump the data info tb_trace_i("%sdata: %p, size: fixed", prefix? prefix : "", data); } else { // dump the data head tb_trace_i("%sdata: invalid head:", prefix? prefix : ""); tb_dump_data((tb_byte_t const*)data_head, sizeof(tb_pool_data_head_t)); // dump the first 256-bytes data tb_trace_i("%sdata: first %lu-bytes:", prefix? prefix : "", data_limit); tb_dump_data((tb_byte_t const*)data, data_limit); } } while (0); } tb_void_t tb_pool_data_save_backtrace(tb_pool_data_debug_head_t* debug_head, tb_size_t skip_frames) { tb_size_t nframe = tb_backtrace_frames(debug_head->backtrace, tb_arrayn(debug_head->backtrace), skip_frames + 2); if (nframe < tb_arrayn(debug_head->backtrace)) tb_memset_(debug_head->backtrace + nframe, 0, (tb_arrayn(debug_head->backtrace) - nframe) * sizeof(tb_cpointer_t)); } #endif tbox-1.6.7/src/tbox/memory/impl/prefix.h 0000664 0000000 0000000 00000010212 14142237372 0020164 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_MEMORY_IMPL_PREFIX_H #define TB_MEMORY_IMPL_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../allocator.h" #include "../large_allocator.h" #include "../../libc/libc.h" #include "../../math/math.h" #include "../../utils/utils.h" #include "../../platform/platform.h" #include "../../container/container.h" #include "../../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the pool data magic number #define TB_POOL_DATA_MAGIC (0xdead) // the pool data empty magic number #define TB_POOL_DATA_EMPTY_MAGIC (0xdeaf) // the pool data patch value #define TB_POOL_DATA_PATCH (0xcc) // the pool data size maximum #define TB_POOL_DATA_SIZE_MAXN (TB_MAXU32) // the pool data address alignment #define TB_POOL_DATA_ALIGN TB_CPU_BITBYTE // the pool data alignment keyword #define __tb_pool_data_aligned__ __tb_cpu_aligned__ // the pool data head different size for computing the wasted space size #ifdef __tb_debug__ # define TB_POOL_DATA_HEAD_DIFF_SIZE (sizeof(tb_pool_data_head_t) - sizeof(tb_uint32_t)) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ #ifdef __tb_debug__ // the pool data debug head type typedef __tb_pool_data_aligned__ struct __tb_pool_data_debug_head_t { // the file tb_char_t const* file; // the func tb_char_t const* func; // the backtrace frames tb_pointer_t backtrace[16]; // the line tb_uint16_t line; /* the magic * * @note the address may be not accessed if we place the magic to head. */ tb_uint16_t magic; }__tb_pool_data_aligned__ tb_pool_data_debug_head_t; #endif // the pool data head type typedef struct __tb_pool_data_head_t { #ifdef __tb_debug__ // the debug head tb_pool_data_debug_head_t debug; #endif // the size tb_size_t size; }tb_pool_data_head_t; // the pool data empty head type typedef struct __tb_pool_data_empty_head_t { #ifdef __tb_debug__ // the debug head tb_pool_data_debug_head_t debug; #endif }tb_pool_data_empty_head_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ #ifdef __tb_debug__ /* the data size * * @param data the data address * * @return the data size */ tb_size_t tb_pool_data_size(tb_cpointer_t data); /* dump data info * * @param data the data address * @param verbose dump verbose info? * @param prefix the prefix info */ tb_void_t tb_pool_data_dump(tb_cpointer_t data, tb_bool_t verbose, tb_char_t const* prefix); /* save backtrace * * @param data_head the data head * @param skip_frames the skiped frame count */ tb_void_t tb_pool_data_save_backtrace(tb_pool_data_debug_head_t* debug_head, tb_size_t skip_frames); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/impl/static_fixed_pool.c 0000664 0000000 0000000 00000057172 14142237372 0022401 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_fixed_pool.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "static_fixed_pool" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "static_fixed_pool.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ #ifdef TB_WORDS_BIGENDIAN // allocate the index # define tb_static_fixed_pool_used_set1(used, i) do {(used)[(i) >> 3] |= (0x1 << (7 - ((i) & 7)));} while (0) // free the index # define tb_static_fixed_pool_used_set0(used, i) do {(used)[(i) >> 3] &= ~(0x1 << (7 - ((i) & 7)));} while (0) // the index have been allocated? # define tb_static_fixed_pool_used_bset(used, i) ((used)[(i) >> 3] & (0x1 << (7 - ((i) & 7)))) // find the first free index # define tb_static_fixed_pool_find_free(v) tb_bits_fb0_be(v) #else // allocate the index # define tb_static_fixed_pool_used_set1(used, i) do {(used)[(i) >> 3] |= (0x1 << ((i) & 7));} while (0) // free the index # define tb_static_fixed_pool_used_set0(used, i) do {(used)[(i) >> 3] &= ~(0x1 << ((i) & 7));} while (0) // the index have been allocated? # define tb_static_fixed_pool_used_bset(used, i) ((used)[(i) >> 3] & (0x1 << ((i) & 7))) // find the first free index # define tb_static_fixed_pool_find_free(v) tb_bits_fb0_le(v) #endif // cache the predicted index #define tb_static_fixed_pool_cache_pred(pool, i) do { (pool)->pred_index = ((i) >> TB_CPU_SHIFT) + 1; } while (0) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the static fixed pool type typedef __tb_pool_data_aligned__ struct __tb_static_fixed_pool_t { // the real data address after the used_info info tb_byte_t* data; // the data tail tb_byte_t* tail; // the used info tb_byte_t* used_info; // the used info size tb_size_t info_size; // the predict index tb_size_t pred_index; // the item size tb_size_t item_size; // the item space: head + item_size tb_size_t item_space; // the item count tb_size_t item_count; // the item maximum count tb_size_t item_maxn; // the data head size tb_uint16_t data_head_size; // for small allocator? tb_uint16_t for_small; #ifdef __tb_debug__ // the peak size tb_size_t peak_size; // the total size tb_size_t total_size; // the real size tb_size_t real_size; // the occupied size tb_size_t occupied_size; // the malloc count tb_size_t malloc_count; // the free count tb_size_t free_count; // the predict failed count tb_size_t pred_failed; #endif }__tb_pool_data_aligned__ tb_static_fixed_pool_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_pred(tb_static_fixed_pool_t* pool) { // check tb_assert_and_check_return_val(pool, tb_null); // done tb_pool_data_empty_head_t* data_head = tb_null; do { // exists the predict index? tb_check_break(pool->pred_index); // the predict index tb_size_t pred_index = pool->pred_index - 1; tb_assert((pred_index << TB_CPU_SHIFT) < pool->item_maxn); // the predict data tb_size_t* data = (tb_size_t*)pool->used_info + pred_index; // full? tb_check_break((*data) + 1); // the free bit index tb_size_t index = (pred_index << TB_CPU_SHIFT) + tb_static_fixed_pool_find_free(*data); // out of range? if (index >= pool->item_maxn) { // clear the pred index pool->pred_index = 0; break; } // check tb_assert(!tb_static_fixed_pool_used_bset(pool->used_info, index)); // the data head data_head = (tb_pool_data_empty_head_t*)(pool->data + index * pool->item_space); // allocate it tb_static_fixed_pool_used_set1(pool->used_info, index); // the predict data is full if (!((*data) + 1)) { // clear the predict index pool->pred_index = 0; // predict the next index if (index + 1 < pool->item_maxn && !tb_static_fixed_pool_used_bset(pool->used_info, index + 1)) tb_static_fixed_pool_cache_pred(pool, index + 1); } } while (0); #ifdef __tb_debug__ // update the predict failed count if (!data_head) pool->pred_failed++; #endif // ok? return data_head; } #if 1 static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_find(tb_static_fixed_pool_t* pool) { // check tb_assert_and_check_return_val(pool, tb_null); // init tb_size_t i = 0; tb_size_t* p = (tb_size_t*)pool->used_info; tb_size_t* e = (tb_size_t*)(pool->used_info + pool->info_size); tb_byte_t* d = tb_null; // check align tb_assert_and_check_return_val(!(((tb_size_t)p) & (TB_CPU_BITBYTE - 1)), tb_null); // find the free chunk, item_space * 32|64 items #ifdef __tb_small__ // while (p < e && *p == 0xffffffff) p++; // while (p < e && *p == 0xffffffffffffffffL) p++; while (p < e && !((*p) + 1)) p++; #else while (p + 7 < e) { if (p[0] + 1) { p += 0; break; } if (p[1] + 1) { p += 1; break; } if (p[2] + 1) { p += 2; break; } if (p[3] + 1) { p += 3; break; } if (p[4] + 1) { p += 4; break; } if (p[5] + 1) { p += 5; break; } if (p[6] + 1) { p += 6; break; } if (p[7] + 1) { p += 7; break; } p += 8; } while (p < e && !(*p + 1)) p++; #endif tb_check_return_val(p < e, tb_null); // find the free bit index tb_size_t m = pool->item_maxn; i = (((tb_byte_t*)p - pool->used_info) << 3) + tb_static_fixed_pool_find_free(*p); tb_check_return_val(i < m, tb_null); // allocate it d = pool->data + i * pool->item_space; tb_static_fixed_pool_used_set1(pool->used_info, i); // predict this index if no full? if ((*p) + 1) tb_static_fixed_pool_cache_pred(pool, i); // ok? return (tb_pool_data_empty_head_t*)d; } #else static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_find(tb_static_fixed_pool_t* pool) { // check tb_assert_and_check_return_val(pool, tb_null); // done tb_size_t i = 0; tb_size_t m = pool->item_maxn; tb_byte_t* p = pool->used_info; tb_byte_t u = *p; tb_byte_t b = 0; tb_byte_t* d = tb_null; for (i = 0; i < m; ++i) { // bit b = i & 0x07; // u++ if (!b) { u = *p++; // skip the non-free byte //if (u == 0xff) if (!(u + 1)) { i += 7; continue ; } } // is free? // if (!tb_static_fixed_pool_used_bset(pool->used_info, i)) if (!(u & (0x01 << b))) { // ok d = pool->data + i * pool->item_space; // tb_static_fixed_pool_used_set1(pool->used_info, i); *(p - 1) |= (0x01 << b); // predict the next block if (i + 1 < m && !tb_static_fixed_pool_used_bset(pool->used_info, i + 1)) tb_static_fixed_pool_cache_pred(pool, i + 1); break; } } // ok? return (tb_pool_data_empty_head_t*)d; } #endif #ifdef __tb_debug__ static tb_void_t tb_static_fixed_pool_check_data(tb_static_fixed_pool_t* pool, tb_pool_data_empty_head_t const* data_head) { // check tb_assert_and_check_return(pool && data_head); // done tb_bool_t ok = tb_false; tb_byte_t const* data = (tb_byte_t const*)data_head + pool->data_head_size; do { // the index tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space; // check tb_assertf_pass_break(!(((tb_byte_t*)data_head - pool->data) % pool->item_space), "the invalid data: %p", data); tb_assertf_pass_break(tb_static_fixed_pool_used_bset(pool->used_info, index), "data have been freed: %p", data); tb_assertf_pass_break(data_head->debug.magic == (pool->for_small? TB_POOL_DATA_MAGIC : TB_POOL_DATA_EMPTY_MAGIC), "the invalid data: %p", data); tb_assertf_pass_break(((tb_byte_t*)data)[pool->item_size] == TB_POOL_DATA_PATCH, "data underflow"); // ok ok = tb_true; } while (0); // failed? dump it if (!ok) { // dump data tb_pool_data_dump(data, tb_true, "[static_fixed_pool]: [error]: "); // abort tb_abort(); } } static tb_void_t tb_static_fixed_pool_check_next(tb_static_fixed_pool_t* pool, tb_pool_data_empty_head_t const* data_head) { // check tb_assert_and_check_return(pool && data_head); // the index tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space; // check the next data if (index + 1 < pool->item_maxn && tb_static_fixed_pool_used_bset(pool->used_info, index + 1)) tb_static_fixed_pool_check_data(pool, (tb_pool_data_empty_head_t*)((tb_byte_t*)data_head + pool->item_space)); } static tb_void_t tb_static_fixed_pool_check_prev(tb_static_fixed_pool_t* pool, tb_pool_data_empty_head_t const* data_head) { // check tb_assert_and_check_return(pool && data_head); // the index tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space; // check the prev data if (index && tb_static_fixed_pool_used_bset(pool->used_info, index - 1)) tb_static_fixed_pool_check_data(pool, (tb_pool_data_empty_head_t*)((tb_byte_t*)data_head - pool->item_space)); } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_static_fixed_pool_ref_t tb_static_fixed_pool_init(tb_byte_t* data, tb_size_t size, tb_size_t item_size, tb_bool_t for_small) { // check tb_assert_and_check_return_val(data && size && item_size, tb_null); // align data and size tb_size_t diff = tb_align((tb_size_t)data, TB_POOL_DATA_ALIGN) - (tb_size_t)data; tb_assert_and_check_return_val(size > diff + sizeof(tb_static_fixed_pool_t), tb_null); size -= diff; data += diff; // init pool tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)data; tb_memset_(pool, 0, sizeof(tb_static_fixed_pool_t)); // for small allocator? pool->for_small = !!for_small; pool->data_head_size = for_small? sizeof(tb_pool_data_head_t) : sizeof(tb_pool_data_empty_head_t); #ifndef __tb_debug__ // fix data alignment, because sizeof(tb_pool_data_empty_head_t) == 1 now. if (!for_small) pool->data_head_size = 0; #endif tb_assert_and_check_return_val(!(pool->data_head_size & (TB_POOL_DATA_ALIGN - 1)), tb_null); #ifdef __tb_debug__ // init patch for checking underflow tb_size_t patch = 1; #else tb_size_t patch = 0; #endif // init the item space pool->item_space = pool->data_head_size + item_size + patch; pool->item_space = tb_align(pool->item_space, TB_POOL_DATA_ALIGN); tb_assert_and_check_return_val(pool->item_space > pool->data_head_size, tb_null); // init the used info pool->used_info = (tb_byte_t*)tb_align((tb_size_t)&pool[1], TB_POOL_DATA_ALIGN); tb_assert_and_check_return_val(data + size > pool->used_info, tb_null); /* init the item maxn * * used_info + maxn * item_space < left * align8(maxn) / 8 + maxn * item_space < left * (maxn + 7) / 8 + maxn * item_space < left * (maxn / 8) + (7 / 8) + maxn * item_space < left * maxn * (1 / 8 + item_space) < left - (7 / 8) * maxn < (left - (7 / 8)) / (1 / 8 + item_space) * maxn < (left * 8 - 7) / (1 + item_space * 8) */ pool->item_maxn = (((data + size - pool->used_info) << 3) - 7) / (1 + (pool->item_space << 3)); tb_assert_and_check_return_val(pool->item_maxn, tb_null); // init the used info size pool->info_size = tb_align(pool->item_maxn, TB_CPU_BITSIZE) >> 3; tb_assert_and_check_return_val(pool->info_size && !(pool->info_size & (TB_CPU_BITBYTE - 1)), tb_null); // clear the used info tb_memset_(pool->used_info, 0, pool->info_size); // init data pool->data = (tb_byte_t*)tb_align((tb_size_t)pool->used_info + pool->info_size, TB_POOL_DATA_ALIGN); tb_assert_and_check_return_val(data + size > pool->data, tb_null); tb_assert_and_check_return_val(pool->item_maxn * pool->item_space <= (tb_size_t)(data + size - pool->data + 1), tb_null); // init data tail pool->tail = pool->data + pool->item_maxn * pool->item_space; // init the item size pool->item_size = item_size; // init the item count pool->item_count = 0; // init the predict index pool->pred_index = 1; // trace tb_trace_d("init: data: %p, size: %lu, head_size: %lu, item_size: %lu, item_maxn: %lu, item_space: %lu", pool->data, size, pool->data - (tb_byte_t*)pool, item_size, pool->item_maxn, pool->item_space); // ok return (tb_static_fixed_pool_ref_t)pool; } tb_void_t tb_static_fixed_pool_exit(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return(pool); // clear it tb_static_fixed_pool_clear(self); // exit it tb_memset_(pool, 0, sizeof(tb_static_fixed_pool_t)); } tb_size_t tb_static_fixed_pool_size(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, 0); // the item count return pool->item_count; } tb_size_t tb_static_fixed_pool_maxn(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, 0); // the item maximum count return pool->item_maxn; } tb_bool_t tb_static_fixed_pool_full(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, 0); // full? return pool->item_count == pool->item_maxn? tb_true : tb_false; } tb_bool_t tb_static_fixed_pool_null(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return_val(pool, 0); // null? return !pool->item_count? tb_true : tb_false; } tb_void_t tb_static_fixed_pool_clear(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return(pool); // clear used_info if (pool->used_info) tb_memset_(pool->used_info, 0, pool->info_size); // clear size pool->item_count = 0; // init the predict index pool->pred_index = 1; // clear info #ifdef __tb_debug__ pool->peak_size = 0; pool->total_size = 0; pool->real_size = 0; pool->occupied_size = 0; pool->malloc_count = 0; pool->free_count = 0; pool->pred_failed = 0; #endif } tb_pointer_t tb_static_fixed_pool_malloc(tb_static_fixed_pool_ref_t self __tb_debug_decl__) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return_val(pool && pool->item_space, tb_null); // done tb_pointer_t data = tb_null; tb_pool_data_empty_head_t* data_head = tb_null; do { // full? tb_check_break(pool->item_count < pool->item_maxn); // predict it? data_head = tb_static_fixed_pool_malloc_pred(pool); // find it if (!data_head) data_head = tb_static_fixed_pool_malloc_find(pool); tb_check_break(data_head); // the real data data = (tb_byte_t*)data_head + pool->data_head_size; // save the real size if (pool->for_small) ((tb_pool_data_head_t*)data_head)->size = pool->item_size; // count++ pool->item_count++; #ifdef __tb_debug__ // init the debug info data_head->debug.magic = pool->for_small? TB_POOL_DATA_MAGIC : TB_POOL_DATA_EMPTY_MAGIC; data_head->debug.file = file_; data_head->debug.func = func_; data_head->debug.line = (tb_uint16_t)line_; // save backtrace tb_pool_data_save_backtrace(&data_head->debug, 6); // make the dirty data and patch 0xcc for checking underflow tb_memset_(data, TB_POOL_DATA_PATCH, pool->item_space - pool->data_head_size); // update the real size pool->real_size += pool->item_size; // update the occupied size pool->occupied_size += pool->item_space - TB_POOL_DATA_HEAD_DIFF_SIZE - 1; // update the total size pool->total_size += pool->item_size; // update the peak size if (pool->total_size > pool->peak_size) pool->peak_size = pool->total_size; // update the malloc count pool->malloc_count++; // check the prev data tb_static_fixed_pool_check_prev(pool, data_head); // check the next data tb_static_fixed_pool_check_next(pool, data_head); #endif } while (0); // check tb_assertf(data, "malloc(%lu) failed!", pool->item_size); tb_assertf(!(((tb_size_t)data) & (TB_POOL_DATA_ALIGN - 1)), "malloc(%lu): unaligned data: %p", pool->item_size, data); // ok? return data; } tb_bool_t tb_static_fixed_pool_free(tb_static_fixed_pool_ref_t self, tb_pointer_t data __tb_debug_decl__) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return_val(pool && pool->item_space, tb_false); // done tb_bool_t ok = tb_false; tb_pool_data_empty_head_t* data_head = (tb_pool_data_empty_head_t*)((tb_byte_t*)data - pool->data_head_size); do { // the index tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space; // check tb_assertf_pass_and_check_break((tb_byte_t*)data_head >= pool->data && (tb_byte_t*)data_head + pool->item_space <= pool->tail, "the data: %p not belong to pool: %p", data, pool); tb_assertf_pass_break(!(((tb_byte_t*)data_head - pool->data) % pool->item_space), "free the invalid data: %p", data); tb_assertf_pass_and_check_break(pool->item_count, "double free data: %p", data); tb_assertf_pass_and_check_break(tb_static_fixed_pool_used_bset(pool->used_info, index), "double free data: %p", data); tb_assertf_pass_break(data_head->debug.magic == (pool->for_small? TB_POOL_DATA_MAGIC : TB_POOL_DATA_EMPTY_MAGIC), "the invalid data: %p", data); tb_assertf_pass_break(((tb_byte_t*)data)[pool->item_size] == TB_POOL_DATA_PATCH, "data underflow"); #ifdef __tb_debug__ // check the prev data tb_static_fixed_pool_check_prev(pool, data_head); // check the next data tb_static_fixed_pool_check_next(pool, data_head); // update the total size pool->total_size -= pool->item_size; // update the free count pool->free_count++; #endif // free it tb_static_fixed_pool_used_set0(pool->used_info, index); // predict it if no cache if (!pool->pred_index) tb_static_fixed_pool_cache_pred(pool, index); // size-- pool->item_count--; // ok ok = tb_true; } while (0); // failed? dump it #ifdef __tb_debug__ if (!ok) { // trace tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[static_fixed_pool]: [error]: "); // abort tb_abort(); } #endif // ok? return ok; } tb_void_t tb_static_fixed_pool_walk(tb_static_fixed_pool_ref_t self, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return(pool && pool->item_maxn && pool->item_space && func); // walk tb_size_t i = 0; tb_size_t m = pool->item_maxn; tb_byte_t* p = pool->used_info; tb_byte_t* d = pool->data + pool->data_head_size; tb_byte_t u = *p; tb_byte_t b = 0; for (i = 0; i < m; ++i) { // bit b = i & 0x07; // u++ if (!b) { u = *p++; // this byte is all occupied? //if (u == 0xff) if (!(u + 1)) { // done func func(d + (i + 0) * pool->item_space, priv); func(d + (i + 1) * pool->item_space, priv); func(d + (i + 2) * pool->item_space, priv); func(d + (i + 3) * pool->item_space, priv); func(d + (i + 4) * pool->item_space, priv); func(d + (i + 5) * pool->item_space, priv); func(d + (i + 6) * pool->item_space, priv); func(d + (i + 7) * pool->item_space, priv); // skip this byte and continue it i += 7; continue ; } } // is occupied? // if (tb_static_fixed_pool_used_bset(pool->used_info, i)) if ((u & (0x01 << b))) { // done func func(d + i * pool->item_space, priv); } } } #ifdef __tb_debug__ tb_void_t tb_static_fixed_pool_dump(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return(pool && pool->used_info); // dump tb_size_t index = 0; for (index = 0; index < pool->item_maxn; ++index) { // leak? if (tb_static_fixed_pool_used_bset(pool->used_info, index)) { // the data head tb_pool_data_empty_head_t* data_head = (tb_pool_data_empty_head_t*)(pool->data + index * pool->item_space); // check it tb_static_fixed_pool_check_data(pool, data_head); // the data tb_byte_t const* data = (tb_byte_t const*)data_head + pool->data_head_size; // trace tb_trace_e("leak: %p", data); // dump data tb_pool_data_dump(data, tb_false, "[static_fixed_pool]: [error]: "); } } // trace debug info tb_trace_i("[%lu]: peak_size: %lu, wast_rate: %llu/10000, pred_failed: %lu, item_maxn: %lu, free_count: %lu, malloc_count: %lu" , pool->item_size , pool->peak_size , pool->occupied_size? (((tb_hize_t)pool->occupied_size - pool->real_size) * 10000) / (tb_hize_t)pool->occupied_size : 0 , pool->pred_failed , pool->item_maxn , pool->free_count , pool->malloc_count); } #endif tbox-1.6.7/src/tbox/memory/impl/static_fixed_pool.h 0000664 0000000 0000000 00000010512 14142237372 0022371 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_fixed_pool.h * */ #ifndef TB_MEMORY_IMPL_STATIC_FIXED_POOL_H #define TB_MEMORY_IMPL_STATIC_FIXED_POOL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../fixed_pool.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the static fixed pool ref type * *
* --------------------------------------------------------------------------- * | head | used | data | * --------------------------------------------------------------------------- * | * pred **/ typedef __tb_typeref__(static_fixed_pool); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init pool * * @param data the data address * @param size the data size * @param item_size the item size * @param for_small add data size field at head for the small allocator * * @return the pool */ tb_static_fixed_pool_ref_t tb_static_fixed_pool_init(tb_byte_t* data, tb_size_t size, tb_size_t item_size, tb_bool_t for_small); /*! exit pool * * @param pool the pool */ tb_void_t tb_static_fixed_pool_exit(tb_static_fixed_pool_ref_t pool); /*! the item count * * @param pool the pool * * @return the item count */ tb_size_t tb_static_fixed_pool_size(tb_static_fixed_pool_ref_t pool); /*! the item maximum count * * @param pool the pool * * @return the item maximum count */ tb_size_t tb_static_fixed_pool_maxn(tb_static_fixed_pool_ref_t pool); /*! is full? * * @param pool the pool * * @return tb_true or tb_false */ tb_bool_t tb_static_fixed_pool_full(tb_static_fixed_pool_ref_t pool); /*! is null? * * @param pool the pool * * @return tb_true or tb_false */ tb_bool_t tb_static_fixed_pool_null(tb_static_fixed_pool_ref_t pool); /*! clear pool * * @param pool the pool */ tb_void_t tb_static_fixed_pool_clear(tb_static_fixed_pool_ref_t pool); /*! malloc data * * @param pool the pool * * @return the data */ tb_pointer_t tb_static_fixed_pool_malloc(tb_static_fixed_pool_ref_t pool __tb_debug_decl__); /*! free data * * @param pool the pool * @param data the data * * @return tb_true or tb_false */ tb_bool_t tb_static_fixed_pool_free(tb_static_fixed_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__); /*! walk data * * @code * tb_bool_t tb_static_fixed_pool_item_func(tb_pointer_t data, tb_cpointer_t priv) * { * // ok or break * return tb_true; * } * @endcode * * @param pool the pool * @param func the walk func * @param priv the walk data * */ tb_void_t tb_static_fixed_pool_walk(tb_static_fixed_pool_ref_t pool, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv); #ifdef __tb_debug__ /*! dump pool * * @param pool the pool */ tb_void_t tb_static_fixed_pool_dump(tb_static_fixed_pool_ref_t pool); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/impl/static_large_allocator.c 0000664 0000000 0000000 00000104531 14142237372 0023373 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_large_allocator.c */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "static_large_allocator" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "static_large_allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the static large allocator data size #define tb_static_large_allocator_data_base(data_head) (&(((tb_pool_data_head_t*)((tb_static_large_data_head_t*)(data_head) + 1))[-1])) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the static large data head type typedef __tb_pool_data_aligned__ struct __tb_static_large_data_head_t { // the data space size: the allocated size + left size tb_uint32_t space : 31; // is free? tb_uint32_t bfree : 1; /* patch 4 bytes for align(8) for tinycc/x86_64 * * __tb_aligned__(8) struct doesn't seem to work */ #if defined(TB_COMPILER_IS_TINYC) && defined(TB_CPU_BIT64) tb_uint32_t padding; #endif // the data head base tb_byte_t base[sizeof(tb_pool_data_head_t)]; }__tb_pool_data_aligned__ tb_static_large_data_head_t; // the static large data pred type typedef struct __tb_static_large_data_pred_t { // the data head tb_static_large_data_head_t* data_head; #ifdef __tb_debug__ // the total count tb_size_t total_count; // the failed count tb_size_t failed_count; #endif }tb_static_large_data_pred_t; /*! the static large allocator type * *
* * .e.g page_size == 4KB * * -------------------------------------------------------------------------- * | data | * -------------------------------------------------------------------------- * | * -------------------------------------------------------------------------- * | head | 4KB | 16KB | 8KB | 128KB | ... | 32KB | ... | 4KB*N | * -------------------------------------------------------------------------- * | | | * | `---------------` * | merge free space when alloc or free * | * ------------------------------------------ * | tb_static_large_data_head_t | data space | * ------------------------------------------ * * -------------------------------------- * pred: | >0KB : 4KB | > 0*page | 1 * |-----------------------|-------------- * | >4KB : 8KB | > 1*page | 2 * |-----------------------|-------------- * | >8KB : 12-16KB | > 2*page | 3-4 * |-----------------------|-------------- * | >16KB : 20-32KB | > 4*page | 5-8 * |-----------------------|-------------- * | >32KB : 36-64KB | > 8*page | 9-16 * |-----------------------|-------------- * | >64KB : 68-128KB | > 16*page | 17-32 * |-----------------------|-------------- * | >128KB : 132-256KB | > 32*page | 33-64 * |-----------------------|-------------- * | >256KB : 260-512KB | > 64*page | 65 - 128 * |-----------------------|-------------- * | >512KB : 516-1024KB | > 128*page | 129 - 256 * |-----------------------|-------------- * | >1024KB : 1028-...KB | > 256*page | 257 - .. * -------------------------------------- * **/ typedef __tb_pool_data_aligned__ struct __tb_static_large_allocator_t { // the base tb_allocator_t base; // the page size tb_size_t page_size; // the data size tb_size_t data_size; // the data head tb_static_large_data_head_t* data_head; // the data tail tb_static_large_data_head_t* data_tail; // the data pred #ifdef TB_CONFIG_MICRO_ENABLE tb_static_large_data_pred_t data_pred[1]; #else tb_static_large_data_pred_t data_pred[10]; #endif #ifdef __tb_debug__ // the peak size tb_size_t peak_size; // the total size tb_size_t total_size; // the real size tb_size_t real_size; // the occupied size tb_size_t occupied_size; // the malloc count tb_size_t malloc_count; // the ralloc count tb_size_t ralloc_count; // the free count tb_size_t free_count; #endif }__tb_pool_data_aligned__ tb_static_large_allocator_t, *tb_static_large_allocator_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * checker implementation */ #ifdef __tb_debug__ static tb_void_t tb_static_large_allocator_check_data(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t const* data_head) { // check tb_assert_and_check_return(allocator && data_head); // done tb_bool_t ok = tb_false; tb_byte_t const* data = (tb_byte_t const*)&(data_head[1]); do { // the base head tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head); // check tb_assertf_pass_break(!data_head->bfree, "data have been freed: %p", data); tb_assertf_pass_break(base_head->debug.magic == TB_POOL_DATA_MAGIC, "the invalid data: %p", data); tb_assertf_pass_break(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow"); // ok ok = tb_true; } while (0); // failed? dump it if (!ok) { // dump data tb_pool_data_dump(data, tb_true, "[static_large_allocator]: [error]: "); // abort tb_abort(); } } static tb_void_t tb_static_large_allocator_check_next(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t const* data_head) { // check tb_assert_and_check_return(allocator && data_head); // check the next data tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space); if (next_head < allocator->data_tail && !next_head->bfree) tb_static_large_allocator_check_data(allocator, next_head); } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * malloc implementation */ static __tb_inline__ tb_size_t tb_static_large_allocator_pred_index(tb_static_large_allocator_ref_t allocator, tb_size_t space) { #ifndef TB_CONFIG_MICRO_ENABLE // the size tb_size_t size = sizeof(tb_static_large_data_head_t) + space; tb_assert(!(size & (allocator->page_size - 1))); // the page count size /= allocator->page_size; // the pred index #if 0 tb_size_t indx = tb_ilog2i(tb_align_pow2(size)); #else // faster tb_size_t indx = size > 1? (tb_ilog2i((tb_uint32_t)(size - 1)) + 1) : 0; #endif if (indx >= tb_arrayn(allocator->data_pred)) indx = tb_arrayn(allocator->data_pred) - 1; return indx; #else return 0; #endif } static __tb_inline__ tb_void_t tb_static_large_allocator_pred_update(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head) { // check tb_assert(allocator && data_head && data_head->bfree); // cannot be tail tb_check_return(data_head != allocator->data_tail); // the pred index tb_size_t indx = tb_static_large_allocator_pred_index(allocator, data_head->space); // the pred head tb_static_large_data_head_t* pred_head = allocator->data_pred[indx].data_head; // cache this data head if (!pred_head || data_head->space > pred_head->space) allocator->data_pred[indx].data_head = data_head; } static __tb_inline__ tb_void_t tb_static_large_allocator_pred_remove(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head) { // check tb_assert(allocator && data_head); // the pred index tb_size_t indx = tb_static_large_allocator_pred_index(allocator, data_head->space); // clear this data head if (allocator->data_pred[indx].data_head == data_head) allocator->data_pred[indx].data_head = tb_null; } static tb_static_large_data_head_t* tb_static_large_allocator_malloc_find(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head, tb_size_t walk_size, tb_size_t space) { // check tb_assert_and_check_return_val(allocator && data_head && space, tb_null); // the data tail tb_static_large_data_head_t* data_tail = allocator->data_tail; tb_check_return_val(data_head < data_tail, tb_null); // find the free data while ((data_head + 1) <= data_tail && walk_size) { // the data space size tb_size_t data_space = data_head->space; // check the space size tb_assert(!((sizeof(tb_static_large_data_head_t) + data_space) & (allocator->page_size - 1))); #ifdef __tb_debug__ // check the data if (!data_head->bfree) tb_static_large_allocator_check_data(allocator, data_head); #endif // allocate if the data is free if (data_head->bfree) { // is enough? if (data_space >= space) { // remove this free data from the pred cache tb_static_large_allocator_pred_remove(allocator, data_head); // split it if this free data is too large if (data_space > sizeof(tb_static_large_data_head_t) + space) { // split this free data tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + space); next_head->space = data_space - space - sizeof(tb_static_large_data_head_t); next_head->bfree = 1; data_head->space = space; // add next free data to the pred cache tb_static_large_allocator_pred_update(allocator, next_head); } else { // the next data head tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space); // the next data is free? if (next_head + 1 < data_tail && next_head->bfree) { // add next free data to the pred cache tb_static_large_allocator_pred_update(allocator, next_head); } } // allocate the data data_head->bfree = 0; // return the data head return data_head; } else // attempt to merge next free data if this free data is too small { // the next data head tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space); // break if doesn't exist next data tb_check_break(next_head + 1 < data_tail); // the next data is free? if (next_head->bfree) { // remove next free data from the pred cache tb_static_large_allocator_pred_remove(allocator, next_head); // remove this free data from the pred cache tb_static_large_allocator_pred_remove(allocator, data_head); // trace tb_trace_d("malloc: find: merge: %lu", next_head->space); // merge next data data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space; // add this free data to the pred cache tb_static_large_allocator_pred_update(allocator, data_head); // continue handle this data continue ; } } } // walk_size-- walk_size--; // skip it if the data is non-free or too small data_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space); } // failed return tb_null; } static tb_static_large_data_head_t* tb_static_large_allocator_malloc_pred(tb_static_large_allocator_ref_t allocator, tb_size_t space) { // check tb_assert_and_check_return_val(allocator && allocator->data_head, tb_null); // walk the pred cache tb_size_t indx = tb_static_large_allocator_pred_index(allocator, space); tb_size_t size = tb_arrayn(allocator->data_pred); tb_static_large_data_pred_t* pred = allocator->data_pred; tb_static_large_data_head_t* data_head = tb_null; tb_static_large_data_head_t* pred_head = tb_null; for (; indx < size && !data_head; indx++) { // the pred data head pred_head = pred[indx].data_head; if (pred_head) { // find the free data from the pred data head data_head = tb_static_large_allocator_malloc_find(allocator, pred_head, 1, space); #ifdef __tb_debug__ // update the total count pred[indx].total_count++; // update the failed count if (!data_head) pred[indx].failed_count++; #endif } } // trace tb_trace_d("malloc: pred: %lu: %s", space, data_head? "ok" : "no"); // ok? return data_head; } static tb_static_large_data_head_t* tb_static_large_allocator_malloc_done(tb_static_large_allocator_ref_t allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__) { // check tb_assert_and_check_return_val(allocator && allocator->data_head, tb_null); // done tb_bool_t ok = tb_false; tb_static_large_data_head_t* data_head = tb_null; do { #ifdef __tb_debug__ // patch 0xcc tb_size_t patch = 1; #else tb_size_t patch = 0; #endif // compile the need space for the page alignment tb_size_t need_space = tb_align(size + patch, allocator->page_size) - sizeof(tb_static_large_data_head_t); if (size + patch > need_space) need_space = tb_align(size + patch + allocator->page_size, allocator->page_size) - sizeof(tb_static_large_data_head_t); // attempt to predict the free data first data_head = tb_static_large_allocator_malloc_pred(allocator, need_space); if (!data_head) { // find the free data from the first data head data_head = tb_static_large_allocator_malloc_find(allocator, allocator->data_head, -1, need_space); tb_check_break(data_head); } tb_assert(data_head->space >= size + patch); // the base head tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head); // the real size tb_size_t size_real = real? (data_head->space - patch) : size; // save the real size if (real) *real = size_real; base_head->size = (tb_uint32_t)size_real; #ifdef __tb_debug__ // init the debug info base_head->debug.magic = TB_POOL_DATA_MAGIC; base_head->debug.file = file_; base_head->debug.func = func_; base_head->debug.line = (tb_uint16_t)line_; // calculate the skip frames tb_size_t skip_nframe = (tb_allocator() && tb_allocator_type(tb_allocator()) == TB_ALLOCATOR_TYPE_DEFAULT)? 6 : 3; // save backtrace tb_pool_data_save_backtrace(&base_head->debug, skip_nframe); // make the dirty data and patch 0xcc for checking underflow tb_memset_((tb_pointer_t)&(data_head[1]), TB_POOL_DATA_PATCH, size_real + patch); // update the real size allocator->real_size += base_head->size; // update the occupied size allocator->occupied_size += sizeof(tb_static_large_data_head_t) + data_head->space - 1 - TB_POOL_DATA_HEAD_DIFF_SIZE; // update the total size allocator->total_size += base_head->size; // update the peak size if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size; // update the malloc count allocator->malloc_count++; #endif // ok ok = tb_true; } while (0); // trace tb_trace_d("malloc: %lu: %s", size, ok? "ok" : "no"); // failed? clear it if (!ok) data_head = tb_null; // ok? return data_head; } static tb_static_large_data_head_t* tb_static_large_allocator_ralloc_fast(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head, tb_size_t size, tb_size_t* real __tb_debug_decl__) { // check tb_assert_and_check_return_val(allocator && data_head && size, tb_null); // done tb_bool_t ok = tb_false; do { // the base head tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head); #ifdef __tb_debug__ // patch 0xcc tb_size_t patch = 1; // the prev size tb_size_t prev_size = base_head->size; // the prev space tb_size_t prev_space = data_head->space; #else // no patch tb_size_t patch = 0; #endif // compile the need space for the page alignment tb_size_t need_space = tb_align(size + patch, allocator->page_size) - sizeof(tb_static_large_data_head_t); if (size + patch > need_space) need_space = tb_align(size + patch + allocator->page_size, allocator->page_size) - sizeof(tb_static_large_data_head_t); // this data space is not enough? if (need_space > data_head->space) { // attempt to merge the next free data tb_static_large_data_head_t* data_tail = allocator->data_tail; tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space); while (next_head < data_tail && next_head->bfree) { // remove next free data from the pred cache tb_static_large_allocator_pred_remove(allocator, next_head); // trace tb_trace_d("ralloc: fast: merge: %lu", next_head->space); // merge it data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space; // the next data head next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space); } } // enough? tb_check_break(need_space <= data_head->space); // split it if this data is too large after merging if (data_head->space > sizeof(tb_static_large_data_head_t) + need_space) { // split this free data tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + need_space); next_head->space = data_head->space - need_space - sizeof(tb_static_large_data_head_t); next_head->bfree = 1; data_head->space = need_space; // add next free data to the pred cache tb_static_large_allocator_pred_update(allocator, next_head); } // the real size tb_size_t size_real = real? (data_head->space - patch) : size; // save the real size if (real) *real = size_real; base_head->size = (tb_uint32_t)size_real; #ifdef __tb_debug__ // init the debug info base_head->debug.magic = TB_POOL_DATA_MAGIC; base_head->debug.file = file_; base_head->debug.func = func_; base_head->debug.line = (tb_uint16_t)line_; // calculate the skip frames tb_size_t skip_nframe = (tb_allocator() && tb_allocator_type(tb_allocator()) == TB_ALLOCATOR_TYPE_DEFAULT)? 6 : 3; // save backtrace tb_pool_data_save_backtrace(&base_head->debug, skip_nframe); // make the dirty data if (size_real > prev_size) tb_memset_((tb_byte_t*)&(data_head[1]) + prev_size, TB_POOL_DATA_PATCH, size_real - prev_size); // patch 0xcc for checking underflow ((tb_byte_t*)&(data_head[1]))[size_real] = TB_POOL_DATA_PATCH; // update the real size allocator->real_size += size_real; allocator->real_size -= prev_size; // update the occupied size allocator->occupied_size += data_head->space; allocator->occupied_size -= prev_space; // update the total size allocator->total_size += size_real; allocator->total_size -= prev_size; // update the peak size if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size; #endif // ok ok = tb_true; } while (0); // failed? clear it if (!ok) data_head = tb_null; // trace tb_trace_d("ralloc: fast: %lu: %s", size, ok? "ok" : "no"); // ok? return data_head; } static tb_bool_t tb_static_large_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return_val(allocator && data, tb_false); // done tb_bool_t ok = tb_false; tb_static_large_data_head_t* data_head = tb_null; do { // the data head data_head = &(((tb_static_large_data_head_t*)data)[-1]); #ifdef __tb_debug__ // the base head tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head); #endif // check tb_assertf_and_check_break(!data_head->bfree, "double free data: %p", data); tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data); tb_assertf_and_check_break(data_head >= allocator->data_head && data_head < allocator->data_tail, "the data: %p not belong to allocator: %p", data, allocator); tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow"); #ifdef __tb_debug__ // check the next data tb_static_large_allocator_check_next(allocator, data_head); // update the total size allocator->total_size -= base_head->size; // update the free count allocator->free_count++; #endif // trace tb_trace_d("free: %lu: %s", base_head->size, ok? "ok" : "no"); // attempt merge the next free data tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space); if (next_head < allocator->data_tail && next_head->bfree) { // remove next free data from the pred cache tb_static_large_allocator_pred_remove(allocator, next_head); // trace tb_trace_d("free: merge: %lu", next_head->space); // merge it data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space; } // free it data_head->bfree = 1; // add this free data to the pred cache tb_static_large_allocator_pred_update(allocator, data_head); // ok ok = tb_true; } while (0); // ok? return ok; } static tb_pointer_t tb_static_large_allocator_malloc(tb_allocator_ref_t self, tb_size_t size, tb_size_t* real __tb_debug_decl__) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return_val(allocator && size, tb_null); // done tb_static_large_data_head_t* data_head = tb_static_large_allocator_malloc_done(allocator, size, real __tb_debug_args__); // ok return data_head? (tb_pointer_t)&(data_head[1]) : tb_null; } static tb_pointer_t tb_static_large_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return_val(allocator && data && size, tb_null); // done tb_bool_t ok = tb_false; tb_byte_t* data_real = tb_null; tb_static_large_data_head_t* data_head = tb_null; tb_static_large_data_head_t* aloc_head = tb_null; do { // the data head data_head = &(((tb_static_large_data_head_t*)data)[-1]); #ifdef __tb_debug__ // the base head tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head); #endif // check tb_assertf_and_check_break(!data_head->bfree, "ralloc freed data: %p", data); tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data); tb_assertf_and_check_break(data_head >= allocator->data_head && data_head < allocator->data_tail, "the data: %p not belong to allocator: %p", data, allocator); tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow"); #ifdef __tb_debug__ // check the next data tb_static_large_allocator_check_next(allocator, data_head); #endif // attempt to allocate it fastly if enough aloc_head = tb_static_large_allocator_ralloc_fast(allocator, data_head, size, real __tb_debug_args__); if (!aloc_head) { // allocate it aloc_head = tb_static_large_allocator_malloc_done(allocator, size, real __tb_debug_args__); tb_check_break(aloc_head); // not same? if (aloc_head != data_head) { // copy the real data tb_memcpy_((tb_pointer_t)&aloc_head[1], data, tb_min(size, (((tb_pool_data_head_t*)(data_head + 1))[-1]).size)); // free the previous data tb_static_large_allocator_free(self, data __tb_debug_args__); } } // the real data data_real = (tb_byte_t*)&aloc_head[1]; #ifdef __tb_debug__ // update the ralloc count allocator->ralloc_count++; #endif // ok ok = tb_true; } while (0); // trace tb_trace_d("ralloc: %lu: %s", size, ok? "ok" : "no"); // failed? clear it if (!ok) data_real = tb_null; // ok? return (tb_pointer_t)data_real; } static tb_void_t tb_static_large_allocator_clear(tb_allocator_ref_t self) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return(allocator && allocator->data_head && allocator->data_size > sizeof(tb_static_large_data_head_t)); // clear it allocator->data_head->bfree = 1; allocator->data_head->space = allocator->data_size - sizeof(tb_static_large_data_head_t); // clear the pred cache tb_memset_(allocator->data_pred, 0, sizeof(allocator->data_pred)); // add this free data to the pred cache tb_static_large_allocator_pred_update(allocator, allocator->data_head); // clear info #ifdef __tb_debug__ allocator->peak_size = 0; allocator->total_size = 0; allocator->real_size = 0; allocator->occupied_size = 0; allocator->malloc_count = 0; allocator->ralloc_count = 0; allocator->free_count = 0; #endif } static tb_void_t tb_static_large_allocator_exit(tb_allocator_ref_t self) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return(allocator); // exit lock tb_spinlock_exit(&allocator->base.lock); } #ifdef __tb_debug__ static tb_void_t tb_static_large_allocator_dump(tb_allocator_ref_t self) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return(allocator); // trace tb_trace_i(""); // the data head tb_static_large_data_head_t* data_head = allocator->data_head; tb_assert_and_check_return(data_head); // the data tail tb_static_large_data_head_t* data_tail = allocator->data_tail; tb_assert_and_check_return(data_tail); // done tb_size_t frag_count = 0; while ((data_head + 1) <= data_tail) { // non-free? if (!data_head->bfree) { // check it tb_static_large_allocator_check_data(allocator, data_head); // trace tb_trace_e("leak: %p", &data_head[1]); // dump data tb_pool_data_dump((tb_byte_t const*)&data_head[1], tb_false, "[static_large_allocator]: [error]: "); } // fragment++ frag_count++; // the next head data_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_head->space); } // trace tb_trace_i(""); // trace pred info tb_size_t i = 0; tb_size_t pred_size = tb_arrayn(allocator->data_pred); for (i = 0; i < pred_size; i++) { // the pred info tb_static_large_data_pred_t const* pred = &allocator->data_pred[i]; tb_assert_and_check_break(pred); // trace tb_trace_i("pred[>%04luKB]: data: %p, space: %lu, total_count: %lu, failed_count: %lu", ((allocator->page_size << (i - 1)) >> 10), pred->data_head? &pred->data_head[1] : tb_null, pred->data_head? pred->data_head->space : 0, pred->total_count, pred->failed_count); } // trace tb_trace_i(""); // trace debug info tb_trace_i("peak_size: %lu", allocator->peak_size); tb_trace_i("wast_rate: %llu/10000", allocator->occupied_size? (((tb_hize_t)allocator->occupied_size - allocator->real_size) * 10000) / (tb_hize_t)allocator->occupied_size : 0); tb_trace_i("frag_count: %lu", frag_count); tb_trace_i("free_count: %lu", allocator->free_count); tb_trace_i("malloc_count: %lu", allocator->malloc_count); tb_trace_i("ralloc_count: %lu", allocator->ralloc_count); } static tb_bool_t tb_static_large_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data) { // check tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self; tb_assert_and_check_return_val(allocator, tb_false); // have it? return ((tb_byte_t const*)data > (tb_byte_t const*)allocator->data_head && (tb_byte_t const*)data < (tb_byte_t const*)allocator->data_head + allocator->data_size)? tb_true : tb_false; } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_static_large_allocator_init(tb_byte_t* data, tb_size_t size, tb_size_t pagesize) { // check tb_assert_and_check_return_val(data && size, tb_null); tb_assert_static(!(sizeof(tb_static_large_data_head_t) & (TB_POOL_DATA_ALIGN - 1))); tb_assert_static(!(sizeof(tb_static_large_allocator_t) & (TB_POOL_DATA_ALIGN - 1))); // align data and size tb_size_t diff = tb_align((tb_size_t)data, TB_POOL_DATA_ALIGN) - (tb_size_t)data; tb_assert_and_check_return_val(size > diff + sizeof(tb_static_large_allocator_t), tb_null); size -= diff; data += diff; // init allocator tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)data; tb_memset_(allocator, 0, sizeof(tb_static_large_allocator_t)); // init base allocator->base.type = TB_ALLOCATOR_TYPE_LARGE; allocator->base.flag = TB_ALLOCATOR_FLAG_NONE; allocator->base.large_malloc = tb_static_large_allocator_malloc; allocator->base.large_ralloc = tb_static_large_allocator_ralloc; allocator->base.large_free = tb_static_large_allocator_free; allocator->base.clear = tb_static_large_allocator_clear; allocator->base.exit = tb_static_large_allocator_exit; #ifdef __tb_debug__ allocator->base.dump = tb_static_large_allocator_dump; allocator->base.have = tb_static_large_allocator_have; #endif // init lock if (!tb_spinlock_init(&allocator->base.lock)) return tb_null; // init page_size allocator->page_size = pagesize? pagesize : tb_page_size(); // page_size must be larger than sizeof(tb_static_large_data_head_t) if (allocator->page_size < sizeof(tb_static_large_data_head_t)) allocator->page_size += sizeof(tb_static_large_data_head_t); // page_size must be aligned allocator->page_size = tb_align_pow2(allocator->page_size); tb_assert_and_check_return_val(allocator->page_size, tb_null); // init data size allocator->data_size = size - sizeof(tb_static_large_allocator_t); tb_assert_and_check_return_val(allocator->data_size > allocator->page_size, tb_null); // align data size allocator->data_size = tb_align(allocator->data_size - allocator->page_size, allocator->page_size); tb_assert_and_check_return_val(allocator->data_size > sizeof(tb_static_large_data_head_t), tb_null); // init data head allocator->data_head = (tb_static_large_data_head_t*)&allocator[1]; allocator->data_head->bfree = 1; allocator->data_head->space = allocator->data_size - sizeof(tb_static_large_data_head_t); tb_assert_and_check_return_val(!((tb_size_t)allocator->data_head & (TB_POOL_DATA_ALIGN - 1)), tb_null); // add this free data to the pred cache tb_static_large_allocator_pred_update(allocator, allocator->data_head); // init data tail allocator->data_tail = (tb_static_large_data_head_t*)((tb_byte_t*)&allocator->data_head[1] + allocator->data_head->space); // register lock profiler #ifdef TB_LOCK_PROFILER_ENABLE tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&allocator->base.lock, TB_TRACE_MODULE_NAME); #endif // ok return (tb_allocator_ref_t)allocator; } tbox-1.6.7/src/tbox/memory/impl/static_large_allocator.h 0000664 0000000 0000000 00000003211 14142237372 0023371 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_large_allocator.h */ #ifndef TB_MEMORY_IMPL_STATIC_LARGE_ALLOCATOR_H #define TB_MEMORY_IMPL_STATIC_LARGE_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init the large allocator and the allocated data will be aligned by the page size * * @param data the allocator data * @param size the allocator size * @param pagesize the pagesize * * @return the allocator */ tb_allocator_ref_t tb_static_large_allocator_init(tb_byte_t* data, tb_size_t size, tb_size_t pagesize); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/large_allocator.c 0000664 0000000 0000000 00000002410 14142237372 0021054 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file large_allocator.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "large_allocator.h" #include "impl/impl.h" #include "../utils/utils.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_large_allocator_init(tb_byte_t* data, tb_size_t size) { // init pool return (data && size)? tb_static_large_allocator_init(data, size, tb_page_size()) : tb_native_large_allocator_init(); } tbox-1.6.7/src/tbox/memory/large_allocator.h 0000664 0000000 0000000 00000004267 14142237372 0021075 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file large_allocator.h * @ingroup memory * */ #ifndef TB_MEMORY_LARGE_ALLOCATOR_H #define TB_MEMORY_LARGE_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init the large allocator * *
* * ------------------------- ------------------------ * | native memory | | data | * ------------------------- ------------------------ * | | * ------------------------- ------------------------ * | native large allocator | | static large allocator | * ------------------------- ------------------------ * | | * ------------------------------------------------------ * | large allocator | * ------------------------------------------------------ * ** * @param data the data, uses the native memory if be null * @param size the size * * @return the allocator */ tb_allocator_ref_t tb_large_allocator_init(tb_byte_t* data, tb_size_t size); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/memory.h 0000664 0000000 0000000 00000013776 14142237372 0017260 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file memory.h * @defgroup memory * */ #ifndef TB_MEMORY_H #define TB_MEMORY_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "buffer.h" #include "allocator.h" #include "fixed_pool.h" #include "string_pool.h" #include "queue_buffer.h" #include "static_buffer.h" #include "large_allocator.h" #include "small_allocator.h" #include "native_allocator.h" #include "static_allocator.h" #include "virtual_allocator.h" #include "default_allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * description */ /*!architecture * *
* * ---------------- ------------------------------------------------------- ---------------------- * | native memory | or | data | <- | static allocator | * ---------------- ------------------------------------------------------- ---------------------- * | if data be null | * `---------------------------------------> | * | * ----------------------------------------------------------------------------- ---------------------- ------ ------ * | large allocator | -> | fixed pool:NB | -> | slot | -> | slot | -> ... * ----------------------------------------------------------------------------- ---------------------- ------ ------ * | | * | --------------------------------------- ---------------------- ------ ------ * | | small allocator | -> | fixed pool:16B | -> | slot | -> | slot | -> ... * | --------------------------------------- |----------------------| ------ ------ * | | | fixed pool:32B | -> ... * | | |----------------------| * | | | fixed pool:64B | -> ... * | | |----------------------| * | | | fixed pool:96B* | -> ... * | | |----------------------| * | | | fixed pool:128B | -> ... * | | |----------------------| * | | | fixed pool:192B* | -> ... * | | |----------------------| * | | | fixed pool:256B | -> ... * | | |----------------------| * | | | fixed pool:384B* | -> ... * | | |----------------------| * | | | fixed pool:512B | -> ... * | | |----------------------| * | | | fixed pool:1024B | -> ... * | | |----------------------| * | | | fixed pool:2048B | -> ... * | | |----------------------| * | | | fixed pool:3072B* | -> ... * | | ---------------------- * | | * | | * ------------------------------------------------------------------------------ * | >3KB | <=3KB | * |------------------------------------------------------------------------------| * | default allocator | * ------------------------------------------------------------------------------ * | * ---------------------- * | string pool | * ---------------------- * **/ #endif tbox-1.6.7/src/tbox/memory/native_allocator.c 0000664 0000000 0000000 00000006355 14142237372 0021264 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file native_allocator.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "native_allocator" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "native_allocator.h" #include "../utils/utils.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_pointer_t tb_native_allocator_malloc(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__) { // trace tb_trace_d("malloc(%lu) at %s(): %lu, %s", size, func_, line_, file_); // malloc it return tb_native_memory_malloc(size); } static tb_pointer_t tb_native_allocator_ralloc(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__) { // trace tb_trace_d("ralloc(%p, %lu) at %s(): %lu, %s", data, size, func_, line_, file_); // ralloc it return tb_native_memory_ralloc(data, size); } static tb_bool_t tb_native_allocator_free(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__) { // trace tb_trace_d("free(%p) at %s(): %lu, %s", data, func_, line_, file_); // free it return tb_native_memory_free(data); } static tb_bool_t tb_native_allocator_instance_init(tb_handle_t instance, tb_cpointer_t priv) { // check tb_allocator_ref_t allocator = (tb_allocator_ref_t)instance; tb_check_return_val(allocator, tb_false); /* init the native memory first * * because this allocator may be called before tb_init() */ if (!tb_native_memory_init()) return tb_false; // init allocator allocator->type = TB_ALLOCATOR_TYPE_NATIVE; allocator->flag = TB_ALLOCATOR_FLAG_NOLOCK; allocator->malloc = tb_native_allocator_malloc; allocator->ralloc = tb_native_allocator_ralloc; allocator->free = tb_native_allocator_free; #ifdef __tb_debug__ allocator->dump = tb_null; allocator->have = tb_null; #endif // ok return tb_true; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_native_allocator() { // init static tb_atomic32_t s_inited = 0; static tb_allocator_t s_allocator = {0}; // init the static instance tb_singleton_static_init(&s_inited, &s_allocator, tb_native_allocator_instance_init, tb_null); // ok return &s_allocator; } tbox-1.6.7/src/tbox/memory/native_allocator.h 0000664 0000000 0000000 00000002654 14142237372 0021267 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file native_allocator.h * @ingroup memory * */ #ifndef TB_MEMORY_NATIVE_ALLOCATOR_H #define TB_MEMORY_NATIVE_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the global native allocator * * @return the allocator */ tb_allocator_ref_t tb_native_allocator(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/prefix.h 0000664 0000000 0000000 00000001575 14142237372 0017237 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_MEMORY_PREFIX_H #define TB_MEMORY_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #endif tbox-1.6.7/src/tbox/memory/queue_buffer.c 0000664 0000000 0000000 00000020323 14142237372 0020402 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file queue_buffer.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "memory.h" #include "../libc/libc.h" #include "../utils/utils.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_queue_buffer_init(tb_queue_buffer_ref_t buffer, tb_size_t maxn) { // check tb_assert_and_check_return_val(buffer, tb_false); // init buffer->data = tb_null; buffer->head = tb_null; buffer->size = 0; buffer->maxn = maxn; // ok return tb_true; } tb_void_t tb_queue_buffer_exit(tb_queue_buffer_ref_t buffer) { if (buffer) { if (buffer->data) tb_free(buffer->data); tb_memset(buffer, 0, sizeof(tb_queue_buffer_t)); } } tb_byte_t* tb_queue_buffer_data(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, tb_null); // the data return buffer->data; } tb_byte_t* tb_queue_buffer_head(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, tb_null); // the head return buffer->head; } tb_byte_t* tb_queue_buffer_tail(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, tb_null); // the tail return buffer->head? buffer->head + buffer->size : tb_null; } tb_size_t tb_queue_buffer_size(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, 0); // the size return buffer->size; } tb_size_t tb_queue_buffer_maxn(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, 0); // the maxn return buffer->maxn; } tb_size_t tb_queue_buffer_left(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer && buffer->size <= buffer->maxn, 0); // the left return buffer->maxn - buffer->size; } tb_bool_t tb_queue_buffer_full(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, tb_false); // is full? return buffer->size == buffer->maxn? tb_true : tb_false; } tb_bool_t tb_queue_buffer_null(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, tb_false); // is null? return buffer->size? tb_false : tb_true; } tb_void_t tb_queue_buffer_clear(tb_queue_buffer_ref_t buffer) { // check tb_assert_and_check_return(buffer); // clear it buffer->size = 0; buffer->head = buffer->data; } tb_byte_t* tb_queue_buffer_resize(tb_queue_buffer_ref_t buffer, tb_size_t maxn) { // check tb_assert_and_check_return_val(buffer && maxn && maxn >= buffer->size, tb_null); // has data? if (buffer->data) { // move data to head if (buffer->head != buffer->data) { if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size); buffer->head = buffer->data; } // realloc if (maxn > buffer->maxn) { // init head buffer->head = tb_null; // make data buffer->data = (tb_byte_t*)tb_ralloc(buffer->data, maxn); tb_assert_and_check_return_val(buffer->data, tb_null); // save head buffer->head = buffer->data; } } // update maxn buffer->maxn = maxn; // ok return buffer->data; } tb_long_t tb_queue_buffer_skip(tb_queue_buffer_ref_t buffer, tb_size_t size) { // check tb_assert_and_check_return_val(buffer, -1); // no data? tb_check_return_val(buffer->data && buffer->size && size, 0); tb_assert_and_check_return_val(buffer->head, -1); // read data tb_long_t read = buffer->size > size? size : buffer->size; buffer->head += read; buffer->size -= read; // null? reset head if (!buffer->size) buffer->head = buffer->data; // ok return read; } tb_long_t tb_queue_buffer_read(tb_queue_buffer_ref_t buffer, tb_byte_t* data, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && data, -1); // no data? tb_check_return_val(buffer->data && buffer->size && size, 0); tb_assert_and_check_return_val(buffer->head, -1); // read data tb_long_t read = buffer->size > size? size : buffer->size; tb_memcpy(data, buffer->head, read); buffer->head += read; buffer->size -= read; // null? reset head if (!buffer->size) buffer->head = buffer->data; // ok return read; } tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* data, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && data && buffer->maxn, -1); // no data? if (!buffer->data) { // make data buffer->data = tb_malloc_bytes(buffer->maxn); tb_assert_and_check_return_val(buffer->data, -1); // init it buffer->head = buffer->data; buffer->size = 0; } tb_assert_and_check_return_val(buffer->data && buffer->head, -1); // full? tb_size_t left = buffer->maxn - buffer->size; tb_check_return_val(left, 0); // attempt to write data in tail directly if the tail space is enough tb_byte_t* tail = buffer->head + buffer->size; if (buffer->data + buffer->maxn >= tail + size) { tb_memcpy(tail, data, size); buffer->size += size; return (tb_long_t)size; } // move data to head if (buffer->head != buffer->data) { if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size); buffer->head = buffer->data; } // write data tb_size_t writ = left > size? size : left; tb_memcpy(buffer->data + buffer->size, data, writ); buffer->size += writ; // ok return writ; } tb_byte_t* tb_queue_buffer_pull_init(tb_queue_buffer_ref_t buffer, tb_size_t* size) { // check tb_assert_and_check_return_val(buffer, tb_null); // no data? tb_check_return_val(buffer->data && buffer->size, tb_null); tb_assert_and_check_return_val(buffer->head, tb_null); // save size if (size) *size = buffer->size; // ok return buffer->head; } tb_void_t tb_queue_buffer_pull_exit(tb_queue_buffer_ref_t buffer, tb_size_t size) { // check tb_assert_and_check_return(buffer && buffer->head && size <= buffer->size); // update buffer->size -= size; buffer->head += size; // null? reset head if (!buffer->size) buffer->head = buffer->data; } tb_byte_t* tb_queue_buffer_push_init(tb_queue_buffer_ref_t buffer, tb_size_t* size) { // check tb_assert_and_check_return_val(buffer && buffer->maxn, tb_null); // no data? if (!buffer->data) { // make data buffer->data = tb_malloc_bytes(buffer->maxn); tb_assert_and_check_return_val(buffer->data, tb_null); // init buffer->head = buffer->data; buffer->size = 0; } tb_assert_and_check_return_val(buffer->data && buffer->head, tb_null); // full? tb_size_t left = buffer->maxn - buffer->size; tb_check_return_val(left, tb_null); // move data to head first, make sure there is enough write space if (buffer->head != buffer->data) { if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size); buffer->head = buffer->data; } // save size if (size) *size = left; // ok return buffer->head + buffer->size; } tb_void_t tb_queue_buffer_push_exit(tb_queue_buffer_ref_t buffer, tb_size_t size) { // check tb_assert_and_check_return(buffer && buffer->head && buffer->size + size <= buffer->maxn); // update the size buffer->size += size; } tbox-1.6.7/src/tbox/memory/queue_buffer.h 0000664 0000000 0000000 00000012354 14142237372 0020414 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file queue_buffer.h * @ingroup memory * */ #ifndef TB_MEMORY_QUEUE_BUFFER_H #define TB_MEMORY_QUEUE_BUFFER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the queue buffer type typedef struct __tb_queue_buffer_t { // the buffer data tb_byte_t* data; // the buffer head tb_byte_t* head; // the buffer size tb_size_t size; // the buffer maxn tb_size_t maxn; }tb_queue_buffer_t, *tb_queue_buffer_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init buffer * * @param buffer the buffer * @param maxn the buffer maxn * * @return tb_true or tb_false */ tb_bool_t tb_queue_buffer_init(tb_queue_buffer_ref_t buffer, tb_size_t maxn); /*! exit buffer * * @param buffer the buffer */ tb_void_t tb_queue_buffer_exit(tb_queue_buffer_ref_t buffer); /*! the buffer data * * @param buffer the buffer * * @return the buffer data */ tb_byte_t* tb_queue_buffer_data(tb_queue_buffer_ref_t buffer); /*! the buffer head * * @param buffer the buffer * * @return the buffer head */ tb_byte_t* tb_queue_buffer_head(tb_queue_buffer_ref_t buffer); /*! the buffer tail * * @param buffer the buffer * * @return the buffer tail */ tb_byte_t* tb_queue_buffer_tail(tb_queue_buffer_ref_t buffer); /*! the buffer maxn * * @param buffer the buffer * * @return the buffer maxn */ tb_size_t tb_queue_buffer_maxn(tb_queue_buffer_ref_t buffer); /*! the buffer size * * @param buffer the buffer * * @return the buffer size */ tb_size_t tb_queue_buffer_size(tb_queue_buffer_ref_t buffer); /*! the buffer left * * @param buffer the buffer * * @return the buffer left */ tb_size_t tb_queue_buffer_left(tb_queue_buffer_ref_t buffer); /*! the buffer full? * * @param buffer the buffer * * @return tb_true or tb_false */ tb_bool_t tb_queue_buffer_full(tb_queue_buffer_ref_t buffer); /*! the buffer null? * * @param buffer the buffer * * @return tb_true or tb_false */ tb_bool_t tb_queue_buffer_null(tb_queue_buffer_ref_t buffer); /*! clear buffer * * @param buffer the buffer */ tb_void_t tb_queue_buffer_clear(tb_queue_buffer_ref_t buffer); /*! resize buffer size * * @param buffer the buffer * @param maxn the buffer maxn * * @return the buffer data */ tb_byte_t* tb_queue_buffer_resize(tb_queue_buffer_ref_t buffer, tb_size_t maxn); /*! skip buffer * * @param buffer the buffer * @param size the skiped size * * @return the real size */ tb_long_t tb_queue_buffer_skip(tb_queue_buffer_ref_t buffer, tb_size_t size); /*! read buffer * * @param buffer the buffer * @param data the data * @param size the size * * @return the real size */ tb_long_t tb_queue_buffer_read(tb_queue_buffer_ref_t buffer, tb_byte_t* data, tb_size_t size); /*! writ buffer * * @param buffer the buffer * @param data the data * @param size the size * * @return the real size */ tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* data, tb_size_t size); /*! init pull buffer for reading * * @param buffer the buffer * @param size the size * * @return the data */ tb_byte_t* tb_queue_buffer_pull_init(tb_queue_buffer_ref_t buffer, tb_size_t* size); /*! exit pull buffer for reading * * @param buffer the buffer * @param size the size */ tb_void_t tb_queue_buffer_pull_exit(tb_queue_buffer_ref_t buffer, tb_size_t size); /*! init push buffer for writing * * @param buffer the buffer * @param size the size * * @return the data */ tb_byte_t* tb_queue_buffer_push_init(tb_queue_buffer_ref_t buffer, tb_size_t* size); /*! exit push buffer for writing * * @param buffer the buffer * @param size the size */ tb_void_t tb_queue_buffer_push_exit(tb_queue_buffer_ref_t buffer, tb_size_t size); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/small_allocator.c 0000664 0000000 0000000 00000034172 14142237372 0021104 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file small_allocator.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "small_allocator" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "small_allocator.h" #include "large_allocator.h" #include "fixed_pool.h" #include "impl/prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the small allocator type typedef struct __tb_small_allocator_t { // the base tb_allocator_t base; // the large allocator tb_allocator_ref_t large_allocator; // the fixed pool tb_fixed_pool_ref_t fixed_pool[12]; }tb_small_allocator_t, *tb_small_allocator_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * declaration */ __tb_extern_c__ tb_fixed_pool_ref_t tb_fixed_pool_init_(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_bool_t for_small_allocator, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_fixed_pool_ref_t tb_small_allocator_find_fixed(tb_small_allocator_ref_t allocator, tb_size_t size) { // check tb_assert(allocator && size && size <= TB_SMALL_ALLOCATOR_DATA_MAXN); // done tb_fixed_pool_ref_t fixed_pool = tb_null; do { // the fixed pool index tb_size_t index = 0; tb_size_t space = 0; if (size > 64 && size < 193) { if (size < 97) { index = 3; space = 96; } else if (size > 128) { index = 5; space = 192; } else { index = 4; space = 128; } } else if (size > 192 && size < 513) { if (size < 257) { index = 6; space = 256; } else if (size > 384) { index = 8; space = 512; } else { index = 7; space = 384; } } else if (size < 65) { if (size < 17) { index = 0; space = 16; } else if (size > 32) { index = 2; space = 64; } else { index = 1; space = 32; } } else { if (size < 1025) { index = 9; space = 1024; } else if (size > 2048) { index = 11; space = 3072; } else { index = 10; space = 2048; } } // trace tb_trace_d("find: size: %lu => index: %lu, space: %lu", size, index, space); // make fixed pool if not exists if (!allocator->fixed_pool[index]) allocator->fixed_pool[index] = tb_fixed_pool_init_(allocator->large_allocator, 0, space, tb_true, tb_null, tb_null, tb_null); tb_assert_and_check_break(allocator->fixed_pool[index]); // ok fixed_pool = allocator->fixed_pool[index]; } while (0); // ok? return fixed_pool; } #ifdef __tb_debug__ static tb_bool_t tb_small_allocator_item_check(tb_pointer_t data, tb_cpointer_t priv) { // check tb_fixed_pool_ref_t fixed_pool = (tb_fixed_pool_ref_t)priv; tb_assert(fixed_pool && data); // done tb_bool_t ok = tb_false; do { // the data head tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_assertf(data_head->debug.magic == TB_POOL_DATA_MAGIC, "invalid data: %p", data); // the data space tb_size_t space = tb_fixed_pool_item_size(fixed_pool); tb_assert_and_check_break(space >= data_head->size); // check underflow tb_assertf(space == data_head->size || ((tb_byte_t*)data)[data_head->size] == TB_POOL_DATA_PATCH, "data underflow"); // ok ok = tb_true; } while (0); // continue? return ok; } #endif static tb_void_t tb_small_allocator_exit(tb_allocator_ref_t self) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return(allocator && allocator->large_allocator); // enter tb_spinlock_enter(&allocator->base.lock); // exit fixed pool tb_size_t i = 0; tb_size_t n = tb_arrayn(allocator->fixed_pool); for (i = 0; i < n; i++) { // exit it if (allocator->fixed_pool[i]) tb_fixed_pool_exit(allocator->fixed_pool[i]); allocator->fixed_pool[i] = tb_null; } // leave tb_spinlock_leave(&allocator->base.lock); // exit lock tb_spinlock_exit(&allocator->base.lock); // exit pool tb_allocator_large_free(allocator->large_allocator, allocator); } static tb_void_t tb_small_allocator_clear(tb_allocator_ref_t self) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return(allocator && allocator->large_allocator); // clear fixed pool tb_size_t i = 0; tb_size_t n = tb_arrayn(allocator->fixed_pool); for (i = 0; i < n; i++) { // clear it if (allocator->fixed_pool[i]) tb_fixed_pool_clear(allocator->fixed_pool[i]); } } static tb_pointer_t tb_small_allocator_malloc(tb_allocator_ref_t self, tb_size_t size __tb_debug_decl__) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return_val(allocator && allocator->large_allocator && size, tb_null); tb_assert_and_check_return_val(size <= TB_SMALL_ALLOCATOR_DATA_MAXN, tb_null); // done tb_pointer_t data = tb_null; do { // the fixed pool tb_fixed_pool_ref_t fixed_pool = tb_small_allocator_find_fixed(allocator, size); tb_assert_and_check_break(fixed_pool); // done data = tb_fixed_pool_malloc_(fixed_pool __tb_debug_args__); tb_assert_and_check_break(data); // the data head tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_assert(data_head->debug.magic == TB_POOL_DATA_MAGIC); #ifdef __tb_debug__ // fill the patch bytes if (data_head->size > size) tb_memset_((tb_byte_t*)data + size, TB_POOL_DATA_PATCH, data_head->size - size); #endif // update size data_head->size = size; } while (0); // check tb_assertf(data, "malloc(%lu) failed!", size); // ok? return data; } static tb_pointer_t tb_small_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size __tb_debug_decl__) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return_val(allocator && allocator->large_allocator && data && size, tb_null); tb_assert_and_check_return_val(size <= TB_SMALL_ALLOCATOR_DATA_MAXN, tb_null); // done tb_pointer_t data_new = tb_null; do { // the old data head tb_pool_data_head_t* data_head_old = &(((tb_pool_data_head_t*)data)[-1]); tb_assertf(data_head_old->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data); // the old fixed pool tb_fixed_pool_ref_t fixed_pool_old = tb_small_allocator_find_fixed(allocator, data_head_old->size); tb_assert_and_check_break(fixed_pool_old); // the old data space tb_size_t space_old = tb_fixed_pool_item_size(fixed_pool_old); tb_assert_and_check_break(space_old >= data_head_old->size); // check underflow tb_assertf(space_old == data_head_old->size || ((tb_byte_t*)data)[data_head_old->size] == TB_POOL_DATA_PATCH, "data underflow"); // the new fixed pool tb_fixed_pool_ref_t fixed_pool_new = tb_small_allocator_find_fixed(allocator, size); tb_assert_and_check_break(fixed_pool_new); // same space? if (fixed_pool_old == fixed_pool_new) { #ifdef __tb_debug__ // fill the patch bytes if (data_head_old->size > size) tb_memset_((tb_byte_t*)data + size, TB_POOL_DATA_PATCH, data_head_old->size - size); #endif // only update size data_head_old->size = size; // ok data_new = data; break; } // make the new data data_new = tb_fixed_pool_malloc_(fixed_pool_new __tb_debug_args__); tb_assert_and_check_break(data_new); // the new data head tb_pool_data_head_t* data_head_new = &(((tb_pool_data_head_t*)data_new)[-1]); tb_assert(data_head_new->debug.magic == TB_POOL_DATA_MAGIC); #ifdef __tb_debug__ // fill the patch bytes if (data_head_new->size > size) tb_memset_((tb_byte_t*)data_new + size, TB_POOL_DATA_PATCH, data_head_new->size - size); #endif // update size data_head_new->size = size; // copy the old data tb_memcpy_(data_new, data, tb_min(data_head_old->size, size)); // free the old data tb_fixed_pool_free_(fixed_pool_old, data __tb_debug_args__); } while (0); // ok return data_new; } static tb_bool_t tb_small_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return_val(allocator && allocator->large_allocator && data, tb_false); // done tb_bool_t ok = tb_false; do { // the data head tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_assertf(data_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data); // the fixed pool tb_fixed_pool_ref_t fixed_pool = tb_small_allocator_find_fixed(allocator, data_head->size); tb_assert_and_check_break(fixed_pool); // the data space tb_size_t space = tb_fixed_pool_item_size(fixed_pool); tb_assert_and_check_break(space >= data_head->size); // check underflow tb_assertf(space == data_head->size || ((tb_byte_t*)data)[data_head->size] == TB_POOL_DATA_PATCH, "data underflow"); // done ok = tb_fixed_pool_free_(fixed_pool, data __tb_debug_args__); } while (0); // ok? return ok; } #ifdef __tb_debug__ static tb_void_t tb_small_allocator_dump(tb_allocator_ref_t self) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return(allocator && allocator->large_allocator); // trace tb_trace_i(""); // dump fixed pool tb_size_t i = 0; tb_size_t n = tb_arrayn(allocator->fixed_pool); for (i = 0; i < n; i++) { // exists? if (allocator->fixed_pool[i]) { // check it tb_fixed_pool_walk(allocator->fixed_pool[i], tb_small_allocator_item_check, (tb_cpointer_t)allocator->fixed_pool[i]); // dump it tb_fixed_pool_dump(allocator->fixed_pool[i]); } } }static tb_bool_t tb_small_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data) { // check tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self; tb_assert_and_check_return_val(allocator && allocator->large_allocator, tb_false); // have it? return tb_allocator_have(allocator->large_allocator, data); } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_small_allocator_init(tb_allocator_ref_t large_allocator) { // done tb_bool_t ok = tb_false; tb_small_allocator_ref_t allocator = tb_null; do { // no allocator? uses the global allocator if (!large_allocator) large_allocator = tb_allocator(); tb_assert_and_check_break(large_allocator); // make allocator allocator = (tb_small_allocator_ref_t)tb_allocator_large_malloc0(large_allocator, sizeof(tb_small_allocator_t), tb_null); tb_assert_and_check_break(allocator); // init large allocator allocator->large_allocator = large_allocator; // init base allocator->base.type = TB_ALLOCATOR_TYPE_SMALL; allocator->base.flag = TB_ALLOCATOR_FLAG_NONE; allocator->base.malloc = tb_small_allocator_malloc; allocator->base.ralloc = tb_small_allocator_ralloc; allocator->base.free = tb_small_allocator_free; allocator->base.clear = tb_small_allocator_clear; allocator->base.exit = tb_small_allocator_exit; #ifdef __tb_debug__ allocator->base.dump = tb_small_allocator_dump; allocator->base.have = tb_small_allocator_have; #endif // init lock if (!tb_spinlock_init(&allocator->base.lock)) break; // ok ok = tb_true; } while (0); // failed? if (!ok) { if (allocator) tb_small_allocator_exit((tb_allocator_ref_t)allocator); allocator = tb_null; } // ok? return (tb_allocator_ref_t)allocator; } tbox-1.6.7/src/tbox/memory/small_allocator.h 0000664 0000000 0000000 00000005515 14142237372 0021110 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file small_allocator.h * @ingroup memory * */ #ifndef TB_MEMORY_SMALL_ALLOCATOR_H #define TB_MEMORY_SMALL_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "large_allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the data size maximum #define TB_SMALL_ALLOCATOR_DATA_MAXN (3072) /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init the small allocator only for size <=3KB * *
* * -------------------------------------- * | fixed pool: 16B | 1-16B | * |--------------------------------------| * | fixed pool: 32B | 17-32B | * |--------------------------------------| * | fixed pool: 64B | 33-64B | * |--------------------------------------| * | fixed pool: 96B* | 65-96B* | * |--------------------------------------| * | fixed pool: 128B | 97-128B | * |--------------------------------------| * | fixed pool: 192B* | 129-192B* | * |--------------------------------------| * | fixed pool: 256B | 193-256B | * |--------------------------------------| * | fixed pool: 384B* | 257-384B* | * |--------------------------------------| * | fixed pool: 512B | 385-512B | * |--------------------------------------| * | fixed pool: 1024B | 513-1024B | * |--------------------------------------| * | fixed pool: 2048B | 1025-2048B | * |--------------------------------------| * | fixed pool: 3072B* | 2049-3072B* | * -------------------------------------- * ** * @param large_allocator the large allocator, uses the global allocator if be null * * @return the pool */ tb_allocator_ref_t tb_small_allocator_init(tb_allocator_ref_t large_allocator); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/static_allocator.c 0000664 0000000 0000000 00000005457 14142237372 0021267 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_allocator.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "static_allocator.h" #include "impl/impl.h" #include "../utils/utils.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_handle_t tb_static_allocator_instance_init(tb_cpointer_t* ppriv) { // check tb_check_return_val(ppriv, tb_null); // the data and size tb_value_ref_t tuple = (tb_value_ref_t)*ppriv; tb_byte_t* data = (tb_byte_t*)tuple[0].ptr; tb_size_t size = tuple[1].ul; tb_assert_and_check_return_val(data && size, tb_null); // ok? return (tb_handle_t)tb_static_allocator_init(data, size); } static tb_void_t tb_static_allocator_instance_exit(tb_handle_t self, tb_cpointer_t priv) { // check tb_allocator_ref_t allocator = (tb_allocator_ref_t)self; tb_assert_and_check_return(allocator); // dump allocator #ifdef __tb_debug__ if (allocator) tb_allocator_dump(allocator); #endif // exit allocator if (allocator) tb_allocator_exit(allocator); allocator= tb_null; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_static_allocator(tb_byte_t* data, tb_size_t size) { /* init singleton first * * because this allocator may be called before tb_init() */ if (!tb_singleton_init()) return tb_null; // init tuple tb_value_t tuple[2]; tuple[0].ptr = (tb_pointer_t)data; tuple[1].ul = size; // get it return (tb_allocator_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_STATIC_ALLOCATOR, tb_static_allocator_instance_init, tb_static_allocator_instance_exit, tb_null, tuple); } tb_allocator_ref_t tb_static_allocator_init(tb_byte_t* data, tb_size_t size) { // init it tb_allocator_ref_t allocator = tb_static_large_allocator_init(data, size, 8); tb_assert_and_check_return_val(allocator, tb_null); // init type allocator->type = TB_ALLOCATOR_TYPE_STATIC; // ok return allocator; } tbox-1.6.7/src/tbox/memory/static_allocator.h 0000664 0000000 0000000 00000004567 14142237372 0021275 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_allocator.h * @ingroup memory * */ #ifndef TB_MEMORY_STATIC_ALLOCATOR_H #define TB_MEMORY_STATIC_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the global static allocator * * @note * this allocator may be called before tb_init() * * @param data the allocator data * @param size the allocator size * * @return the allocator */ tb_allocator_ref_t tb_static_allocator(tb_byte_t* data, tb_size_t size); /*! init the static allocator * *
* * ----------------------------------------------------- * | data | * ----------------------------------------------------- * | * ----------------------------------------------------- * | static allocator | * ----------------------------------------------------- * ** * @param data the allocator data * @param size the allocator size * * @return the allocator */ tb_allocator_ref_t tb_static_allocator_init(tb_byte_t* data, tb_size_t size); /*! exit the allocator * * @param allocator the allocator */ tb_void_t tb_static_allocator_exit(tb_allocator_ref_t allocator); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/static_buffer.c 0000664 0000000 0000000 00000015232 14142237372 0020550 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_buffer.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "memory.h" #include "../libc/libc.h" #include "../utils/utils.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the maximum grow size of value buffer #ifdef __tb_small__ # define TB_STATIC_BUFFER_GROW_SIZE (64) #else # define TB_STATIC_BUFFER_GROW_SIZE (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_static_buffer_init(tb_static_buffer_ref_t buffer, tb_byte_t* data, tb_size_t maxn) { // check tb_assert_and_check_return_val(buffer, tb_false); // init buffer->size = 0; buffer->data = data; buffer->maxn = maxn; // ok return tb_true; } tb_void_t tb_static_buffer_exit(tb_static_buffer_ref_t buffer) { // exit it if (buffer) { buffer->data = tb_null; buffer->size = 0; buffer->maxn = 0; } } tb_byte_t* tb_static_buffer_data(tb_static_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, tb_null); // the buffer data return buffer->data; } tb_size_t tb_static_buffer_size(tb_static_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, 0); // the buffer size return buffer->size; } tb_size_t tb_static_buffer_maxn(tb_static_buffer_ref_t buffer) { // check tb_assert_and_check_return_val(buffer, 0); // the buffer maxn return buffer->maxn; } tb_void_t tb_static_buffer_clear(tb_static_buffer_ref_t buffer) { // check tb_assert_and_check_return(buffer); // clear it buffer->size = 0; } tb_byte_t* tb_static_buffer_resize(tb_static_buffer_ref_t buffer, tb_size_t size) { // check tb_assert_and_check_return_val(buffer && buffer->data && size <= buffer->maxn, tb_null); // resize buffer->size = size; // ok return buffer->data; } tb_byte_t* tb_static_buffer_memset(tb_static_buffer_ref_t buffer, tb_byte_t b) { return tb_static_buffer_memnsetp(buffer, 0, b, tb_static_buffer_size(buffer)); } tb_byte_t* tb_static_buffer_memsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b) { return tb_static_buffer_memnsetp(buffer, p, b, tb_static_buffer_size(buffer)); } tb_byte_t* tb_static_buffer_memnset(tb_static_buffer_ref_t buffer, tb_byte_t b, tb_size_t n) { return tb_static_buffer_memnsetp(buffer, 0, b, n); } tb_byte_t* tb_static_buffer_memnsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer, tb_null); // check tb_check_return_val(n, tb_static_buffer_data(buffer)); // resize tb_byte_t* d = tb_static_buffer_resize(buffer, p + n); tb_assert_and_check_return_val(d, tb_null); // memset tb_memset(d + p, b, n); // ok? return d; } tb_byte_t* tb_static_buffer_memcpy(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b) { return tb_static_buffer_memncpyp(buffer, 0, tb_static_buffer_data(b), tb_static_buffer_size(b)); } tb_byte_t* tb_static_buffer_memcpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_static_buffer_ref_t b) { return tb_static_buffer_memncpyp(buffer, p, tb_static_buffer_data(b), tb_static_buffer_size(b)); } tb_byte_t* tb_static_buffer_memncpy(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n) { return tb_static_buffer_memncpyp(buffer, 0, b, n); } tb_byte_t* tb_static_buffer_memncpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer && b, tb_null); // check tb_check_return_val(n, tb_static_buffer_data(buffer)); // resize tb_byte_t* d = tb_static_buffer_resize(buffer, p + n); tb_assert_and_check_return_val(d, tb_null); // memcpy tb_memcpy(d + p, b, n); // ok? return d; } tb_byte_t* tb_static_buffer_memmov(tb_static_buffer_ref_t buffer, tb_size_t b) { // check tb_assert_and_check_return_val(b <= tb_static_buffer_size(buffer), tb_null); return tb_static_buffer_memnmovp(buffer, 0, b, tb_static_buffer_size(buffer) - b); } tb_byte_t* tb_static_buffer_memmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b) { // check tb_assert_and_check_return_val(b <= tb_static_buffer_size(buffer), tb_null); return tb_static_buffer_memnmovp(buffer, p, b, tb_static_buffer_size(buffer) - b); } tb_byte_t* tb_static_buffer_memnmov(tb_static_buffer_ref_t buffer, tb_size_t b, tb_size_t n) { return tb_static_buffer_memnmovp(buffer, 0, b, n); } tb_byte_t* tb_static_buffer_memnmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer && (b + n) <= tb_static_buffer_size(buffer), tb_null); // clear? if (b == tb_static_buffer_size(buffer)) { tb_static_buffer_clear(buffer); return tb_static_buffer_data(buffer); } // check tb_check_return_val(p != b && n, tb_static_buffer_data(buffer)); // resize tb_byte_t* d = tb_static_buffer_resize(buffer, p + n); tb_assert_and_check_return_val(d, tb_null); // memmov tb_memmov(d + p, d + b, n); // ok? return d; } tb_byte_t* tb_static_buffer_memcat(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b) { return tb_static_buffer_memncat(buffer, tb_static_buffer_data(b), tb_static_buffer_size(b)); } tb_byte_t* tb_static_buffer_memncat(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n) { // check tb_assert_and_check_return_val(buffer && b, tb_null); // check tb_check_return_val(n, tb_static_buffer_data(buffer)); // is null? tb_size_t p = tb_static_buffer_size(buffer); if (!p) return tb_static_buffer_memncpy(buffer, b, n); // resize tb_byte_t* d = tb_static_buffer_resize(buffer, p + n); tb_assert_and_check_return_val(d, tb_null); // memcat tb_memcpy(d + p, b, n); // ok? return d; } tbox-1.6.7/src/tbox/memory/static_buffer.h 0000664 0000000 0000000 00000016174 14142237372 0020563 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file static_buffer.h * @ingroup memory * */ #ifndef TB_MEMORY_STATIC_BUFFER_H #define TB_MEMORY_STATIC_BUFFER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the static buffer type typedef struct __tb_static_buffer_t { // the buffer data tb_byte_t* data; // the buffer size tb_size_t size; // the buffer maxn tb_size_t maxn; }tb_static_buffer_t, *tb_static_buffer_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init the static buffer * * @param buffer the static buffer * @param data the data * @param maxn the data maxn * * @return tb_true or tb_false */ tb_bool_t tb_static_buffer_init(tb_static_buffer_ref_t buffer, tb_byte_t* data, tb_size_t maxn); /*! exit the static buffer * * @param buffer the static buffer */ tb_void_t tb_static_buffer_exit(tb_static_buffer_ref_t buffer); /*! the buffer data * * @param buffer the static buffer * * @return the buffer data address */ tb_byte_t* tb_static_buffer_data(tb_static_buffer_ref_t buffer); /*! the buffer data size * * @param buffer the static buffer * * @return the buffer data size */ tb_size_t tb_static_buffer_size(tb_static_buffer_ref_t buffer); /*! the buffer data maxn * * @param buffer the static buffer * * @return the buffer data maxn */ tb_size_t tb_static_buffer_maxn(tb_static_buffer_ref_t buffer); /*! clear the buffer * * @param buffer the static buffer */ tb_void_t tb_static_buffer_clear(tb_static_buffer_ref_t buffer); /*! resize the buffer size * * @param buffer the static buffer * @param size the new buffer size * * @return the buffer data address */ tb_byte_t* tb_static_buffer_resize(tb_static_buffer_ref_t buffer, tb_size_t size); /*! memset: b => 0 ... e * * @param buffer the static buffer * @param b the filled byte * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memset(tb_static_buffer_ref_t buffer, tb_byte_t b); /*! memset: b => p ... e * * @param buffer the static buffer * @param p the start position * @param b the filled byte * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b); /*! memset: b => 0 ... n * * @param buffer the static buffer * @param b the filled byte * @param n the filled count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memnset(tb_static_buffer_ref_t buffer, tb_byte_t b, tb_size_t n); /*! memset: b => p ... n * * @param buffer the static buffer * @param p the start position * @param b the filled byte * @param n the filled count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memnsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b, tb_size_t n); /*! memcpy: b => 0 ... * * @param buffer the static buffer * @param b the copied buffer * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memcpy(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b); /*! memcpy: b => p ... * * @param buffer the static buffer * @param p the start position * @param b the copied buffer * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memcpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_static_buffer_ref_t b); /*! memcpy: b ... n => 0 ... * * @param buffer the static buffer * @param b the copied buffer * @param n the copied count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memncpy(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n); /*! memcpy: b ... n => p ... * * @param buffer the static buffer * @param p the start position * @param b the copied buffer * @param n the copied count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memncpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n); /*! memmov: b ... e => 0 ... * * @param buffer the static buffer * @param b the moved start position * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memmov(tb_static_buffer_ref_t buffer, tb_size_t b); /*! memmov: b ... e => p ... * * @param buffer the static buffer * @param p the moved destination position * @param b the moved start position * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b); /*! memmov: b ... n => 0 ... * * @param buffer the static buffer * @param b the moved start position * @param n the moved count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memnmov(tb_static_buffer_ref_t buffer, tb_size_t b, tb_size_t n); /*! memmov: b ... n => p ... * * @param buffer the static buffer * @param p the moved destination position * @param b the moved start position * @param n the moved count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memnmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b, tb_size_t n); /*! memcat: b +=> e ... * * @param buffer the static buffer * @param b the concated buffer * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memcat(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b); /*! memcat: b ... n +=> e ... * * @param buffer the static buffer * @param b the concated buffer * @param n the concated count * * @return the buffer data address */ tb_byte_t* tb_static_buffer_memncat(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/string_pool.c 0000664 0000000 0000000 00000012544 14142237372 0020272 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file string_pool.c * @ingroup memory * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "string_pool" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "allocator.h" #include "memory.h" #include "../libc/libc.h" #include "../utils/utils.h" #include "../platform/platform.h" #include "../container/container.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the string pool type typedef struct __tb_string_pool_t { // the cache tb_hash_map_ref_t cache; }tb_string_pool_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_string_pool_ref_t tb_string_pool_init(tb_bool_t bcase) { // done tb_bool_t ok = tb_false; tb_string_pool_t* pool = tb_null; do { // make pool pool = tb_malloc0_type(tb_string_pool_t); tb_assert_and_check_break(pool); // init hash pool->cache = tb_hash_map_init(0, tb_element_str(bcase), tb_element_size()); tb_assert_and_check_break(pool->cache); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (pool) tb_string_pool_exit((tb_string_pool_ref_t)pool); pool = tb_null; } // ok? return (tb_string_pool_ref_t)pool; } tb_void_t tb_string_pool_exit(tb_string_pool_ref_t self) { // check tb_string_pool_t* pool = (tb_string_pool_t*)self; tb_assert_and_check_return(pool); // exit cache if (pool->cache) tb_hash_map_exit(pool->cache); pool->cache = tb_null; // exit it tb_free(pool); } tb_void_t tb_string_pool_clear(tb_string_pool_ref_t self) { // check tb_string_pool_t* pool = (tb_string_pool_t*)self; tb_assert_and_check_return(pool); // clear cache if (pool->cache) tb_hash_map_clear(pool->cache); } tb_char_t const* tb_string_pool_insert(tb_string_pool_ref_t self, tb_char_t const* data) { // check tb_string_pool_t* pool = (tb_string_pool_t*)self; tb_assert_and_check_return_val(pool && data, tb_null); // done tb_char_t const* cstr = tb_null; if (pool->cache) { // exists? tb_size_t itor; tb_hash_map_item_ref_t item = tb_null; if ( ((itor = tb_hash_map_find(pool->cache, data)) != tb_iterator_tail(pool->cache)) && (item = (tb_hash_map_item_ref_t)tb_iterator_item(pool->cache, itor))) { // refn tb_size_t refn = (tb_size_t)item->data; // refn++ if (refn) tb_iterator_copy(pool->cache, itor, (tb_pointer_t)(refn + 1)); // no refn? remove it else { // assert tb_assert(0); // del it tb_iterator_remove(pool->cache, itor); item = tb_null; } } // no item? insert it if (!item) { // insert it if ((itor = tb_hash_map_insert(pool->cache, data, (tb_pointer_t)1)) != tb_iterator_tail(pool->cache)) item = (tb_hash_map_item_ref_t)tb_iterator_item(pool->cache, itor); } // save the cstr if (item) cstr = (tb_char_t const*)item->name; } // ok? return cstr; } tb_void_t tb_string_pool_remove(tb_string_pool_ref_t self, tb_char_t const* data) { // check tb_string_pool_t* pool = (tb_string_pool_t*)self; tb_assert_and_check_return(pool && data); // done tb_hash_map_item_ref_t item = tb_null; if (pool->cache) { // exists? tb_size_t itor; if ( ((itor = tb_hash_map_find(pool->cache, data)) != tb_iterator_tail(pool->cache)) && (item = (tb_hash_map_item_ref_t)tb_iterator_item(pool->cache, itor))) { // refn tb_size_t refn = (tb_size_t)item->data; // refn-- if (refn > 1) tb_iterator_copy(pool->cache, itor, (tb_pointer_t)(refn - 1)); // del it else tb_iterator_remove(pool->cache, itor); } } } #ifdef __tb_debug__ tb_void_t tb_string_pool_dump(tb_string_pool_ref_t self) { // check tb_string_pool_t* pool = (tb_string_pool_t*)self; tb_assert_and_check_return(pool && pool->cache); // dump cache tb_for_all_if (tb_hash_map_item_ref_t, item, pool->cache, item) { // trace tb_trace_i("item: refn: %lu, cstr: %s", (tb_size_t)item->data, item->name); } } #endif tbox-1.6.7/src/tbox/memory/string_pool.h 0000664 0000000 0000000 00000005361 14142237372 0020276 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file string_pool.h * @ingroup memory * */ #ifndef TB_MEMORY_STRING_POOL_H #define TB_MEMORY_STRING_POOL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the string pool ref type typedef __tb_typeref__(string_pool); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init string pool for small, readonly and repeat strings * * readonly, strip repeat strings and decrease memory fragmens * * @param bcase is case? * * @return the string pool */ tb_string_pool_ref_t tb_string_pool_init(tb_bool_t bcase); /*! exit the string pool * * @param pool the string pool */ tb_void_t tb_string_pool_exit(tb_string_pool_ref_t pool); /*! clear the string pool * * @param pool the string pool */ tb_void_t tb_string_pool_clear(tb_string_pool_ref_t pool); /*! insert string to the pool and increase the reference count * * @param pool the string pool * @param data the string data * * @return the string data */ tb_char_t const* tb_string_pool_insert(tb_string_pool_ref_t pool, tb_char_t const* data); /*! remove string from the pool if the reference count be zero * * @param pool the string pool * @param data the string data */ tb_void_t tb_string_pool_remove(tb_string_pool_ref_t pool, tb_char_t const* data); #ifdef __tb_debug__ /*! dump the string pool * * @param pool the string pool */ tb_void_t tb_string_pool_dump(tb_string_pool_ref_t pool); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/memory/virtual_allocator.c 0000664 0000000 0000000 00000006134 14142237372 0021457 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file virtual_allocator.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "virtual_allocator" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "virtual_allocator.h" #include "../utils/utils.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_pointer_t tb_virtual_allocator_malloc(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__) { // trace tb_trace_d("vmalloc(%lu) at %s(): %lu, %s", size, func_, line_, file_); // malloc it return tb_virtual_memory_malloc(size); } static tb_pointer_t tb_virtual_allocator_ralloc(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__) { // trace tb_trace_d("vralloc(%p, %lu) at %s(): %lu, %s", data, size, func_, line_, file_); // ralloc it return tb_virtual_memory_ralloc(data, size); } static tb_bool_t tb_virtual_allocator_free(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__) { // trace tb_trace_d("vfree(%p) at %s(): %lu, %s", data, func_, line_, file_); // free it return tb_virtual_memory_free(data); } static tb_bool_t tb_virtual_allocator_instance_init(tb_handle_t instance, tb_cpointer_t priv) { // check tb_allocator_ref_t allocator = (tb_allocator_ref_t)instance; tb_check_return_val(allocator, tb_false); // init allocator allocator->type = TB_ALLOCATOR_TYPE_VIRTUAL; allocator->flag = TB_ALLOCATOR_FLAG_NOLOCK; allocator->malloc = tb_virtual_allocator_malloc; allocator->ralloc = tb_virtual_allocator_ralloc; allocator->free = tb_virtual_allocator_free; #ifdef __tb_debug__ allocator->dump = tb_null; allocator->have = tb_null; #endif // ok return tb_true; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_allocator_ref_t tb_virtual_allocator() { // init static tb_atomic32_t s_inited = 0; static tb_allocator_t s_allocator = {0}; // init the static instance tb_singleton_static_init(&s_inited, &s_allocator, tb_virtual_allocator_instance_init, tb_null); // ok return &s_allocator; } tbox-1.6.7/src/tbox/memory/virtual_allocator.h 0000664 0000000 0000000 00000002661 14142237372 0021465 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file virtual_allocator.h * @ingroup memory * */ #ifndef TB_MEMORY_VIRTUAL_ALLOCATOR_H #define TB_MEMORY_VIRTUAL_ALLOCATOR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "allocator.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the global virtual allocator * * @return the allocator */ tb_allocator_ref_t tb_virtual_allocator(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/micro.lua 0000664 0000000 0000000 00000010336 14142237372 0016070 0 ustar 00root root 0000000 0000000 -- add target target("tbox") -- make as a static library set_kind("static") -- add defines add_defines("__tb_prefix__=\"tbox\"") -- set the auto-generated config.h set_configdir("$(buildir)/$(plat)/$(arch)/$(mode)") add_configfiles("tbox.config.h.in") -- add include directories add_includedirs("..", {public = true}) add_includedirs("$(buildir)/$(plat)/$(arch)/$(mode)", {public = true}) -- add the header files for installing add_headerfiles("../(tbox/**.h)|**/impl/**.h") add_headerfiles("../(tbox/prefix/**/prefix.S)") add_headerfiles("../(tbox/math/impl/*.h)") add_headerfiles("../(tbox/utils/impl/*.h)") add_headerfiles("$(buildir)/$(plat)/$(arch)/$(mode)/tbox.config.h", {prefixdir = "tbox"}) -- add options add_options("info", "float", "wchar", "micro", "coroutine") -- add the source files add_files("tbox.c") add_files("libc/string/memset.c") add_files("libc/string/memmov.c") add_files("libc/string/memcpy.c") add_files("libc/string/memcmp.c") add_files("libc/string/strstr.c") add_files("libc/string/strdup.c") add_files("libc/string/strlen.c") add_files("libc/string/strnlen.c") add_files("libc/string/strcmp.c") add_files("libc/string/strncmp.c") add_files("libc/string/stricmp.c") add_files("libc/string/strnicmp.c") add_files("libc/string/strlcpy.c") add_files("libc/string/strncpy.c") add_files("libc/stdio/vsnprintf.c") add_files("libc/stdio/snprintf.c") add_files("libc/stdio/printf.c") add_files("libc/stdlib/stdlib.c") add_files("libc/impl/libc.c") add_files("libm/impl/libm.c") add_files("math/impl/math.c") add_files("utils/used.c") add_files("utils/bits.c") add_files("utils/trace.c") add_files("utils/singleton.c") add_files("memory/allocator.c") add_files("memory/native_allocator.c") add_files("memory/static_allocator.c") add_files("memory/fixed_pool.c") add_files("memory/impl/static_fixed_pool.c") add_files("memory/impl/static_large_allocator.c") add_files("memory/impl/memory.c") add_files("network/ipv4.c") add_files("network/ipv6.c") add_files("network/unixaddr.c") add_files("network/ipaddr.c") add_files("network/impl/network.c") add_files("platform/page.c") add_files("platform/time.c") add_files("platform/file.c") add_files("platform/path.c") add_files("platform/sched.c") add_files("platform/print.c") add_files("platform/thread.c") add_files("platform/socket.c") add_files("platform/addrinfo.c") add_files("platform/poller.c") add_files("platform/mutex.c") add_files("platform/semaphore.c") add_files("platform/native_memory.c") add_files("platform/impl/platform.c") add_files("platform/impl/pollerdata.c") add_files("container/iterator.c") add_files("container/list_entry.c") add_files("container/single_list_entry.c") add_files("container/array_iterator.c") add_files("algorithm/binary_find.c") add_files("algorithm/binary_find_if.c") -- add the source files for debug mode if is_mode("debug") then add_files("utils/dump.c") add_files("memory/impl/prefix.c") add_files("platform/backtrace.c") end -- add the source files for float if has_config("float") then add_files("libm/isinf.c") add_files("libm/isinff.c") add_files("libm/isnan.c") add_files("libm/isnanf.c") end -- add the source for the windows if is_os("windows") then add_files("libc/stdlib/mbstowcs.c") add_files("platform/dynamic.c") add_files("platform/atomic64.c") add_files("platform/windows/pipe.c") add_files("platform/windows/windows.c") add_files("platform/windows/interface/ws2_32.c") add_files("platform/windows/interface/mswsock.c") add_files("platform/windows/interface/kernel32.c") if is_mode("debug") then add_files("platform/windows/interface/dbghelp.c") end end -- add the source files for coroutine if has_config("coroutine") then add_files("coroutine/stackless/*.c") add_files("coroutine/impl/stackless/*.c") end -- check interfaces check_interfaces() tbox-1.6.7/src/tbox/network/ 0000775 0000000 0000000 00000000000 14142237372 0015742 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/network/cookies.c 0000664 0000000 0000000 00000055043 14142237372 0017551 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file cookies.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "cookies" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "cookies.h" #include "impl/http/date.h" #include "url.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../string/string.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" #include "../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the cookies entry type typedef struct __tb_cookies_entry_t { // the domain tb_char_t const* domain; // the path tb_char_t const* path; // the name tb_char_t const* name; // the value tb_char_t const* value; // the expires tb_time_t expires; // the max-age, default: 1 and storage: 0 tb_uint32_t maxage : 30; // storage cookies to file? remove it immediately if maxage == 0 and storage: 0 tb_uint32_t storage : 1; // is secure? tb_uint32_t secure : 1; }tb_cookies_entry_t, *tb_cookies_entry_ref_t; // the cookies type typedef struct __tb_cookies_t { // the lock tb_spinlock_t lock; // the string element tb_element_t string_element; // the string pool tb_string_pool_ref_t string_pool; // the cookie pool, key: "domain+path+name" tb_hash_set_ref_t cookie_pool; }tb_cookies_t; /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t tb_cookies_get_domain_and_path_from_url(tb_char_t const* url, tb_char_t* pdomain, tb_size_t ndomain, tb_char_t* ppath, tb_size_t npath, tb_bool_t* psecure) { // check tb_assert_and_check_return_val(url && pdomain && ndomain && ppath && npath && psecure, tb_false); // get url pointer tb_char_t const* p = url; tb_char_t const* e = url + tb_strlen(url); tb_assert_and_check_return_val(p < e, tb_false); // skip "http://" if (p + 7 < e && !tb_strnicmp(p, "http://", 7)) { p += 7; } // skip "https://" else if (p + 8 < e && !tb_strnicmp(p, "https://", 8)) { p += 8; *psecure = tb_true; } // skip www if (p + 3 < e && !tb_strnicmp(p, "www", 3)) p += 3; // skip . if (p + 1 < e && *p == '.') p++; // get domain tb_char_t* pb = (tb_char_t*)pdomain; tb_char_t* pe = (tb_char_t*)pdomain + ndomain - 1; while (p < e && pb < pe && *p && *p != '/' && *p != ':') *pb++ = *p++; *pb = '\0'; // trace tb_trace_d("domain: %s", pdomain); // skip port if (*p && *p == ':') for (p++; p < e && *p && *p != '/'; p++) ; // get path pb = ppath; pe = ppath + npath - 1; while (p < e && pb < pe && *p && *p != '?') *pb++ = *p++; *pb = '\0'; // no path? if (!*ppath) { *ppath++ = '/'; *ppath = '\0'; } // trace tb_trace_d("path: %s", ppath); // ok? return *pdomain? tb_true : tb_false; } static tb_bool_t tb_cookies_is_child_domain(tb_char_t const* parent, tb_char_t const* child) { // check tb_assert_and_check_return_val(parent && child, tb_false); // init tb_char_t const* pb = parent; tb_char_t const* cb = child; tb_size_t pn = tb_strlen(pb); tb_size_t cn = tb_strlen(cb); tb_assert_and_check_return_val(pn && cn, tb_false); // is child? tb_size_t n = 0; tb_char_t const* pe = pb + pn - 1; tb_char_t const* ce = cb + cn - 1; for (; pe >= pb && ce >= cb && *pe == *ce; pe--, ce--) { if (*ce == '.') n++; } // ok? return (pe < pb && n >= 1 && (ce < cb || *ce == '.'))? tb_true : tb_false; } static tb_bool_t tb_cookies_is_child_path(tb_char_t const* parent, tb_char_t const* child) { // check tb_assert_and_check_return_val(parent && child, tb_false); // parent is root? if (parent[0] == '/' && !parent[1]) return tb_true; // is child? tb_char_t const* p = parent; tb_char_t const* c = child; tb_size_t n = tb_strlen(parent); while (n-- && *p && *c && *p++ == *c++) ; // ok? return (!*p && (!*c || *c == '/'))? tb_true : tb_false; } static tb_void_t tb_cookies_entry_exit(tb_cookies_t* cookies, tb_cookies_entry_ref_t entry) { // check tb_assert_and_check_return(cookies && entry); // exit domain if (entry->domain) tb_string_pool_remove(cookies->string_pool, entry->domain); entry->domain = tb_null; // exit path if (entry->path) tb_string_pool_remove(cookies->string_pool, entry->path); entry->path = tb_null; // exit name if (entry->name) tb_string_pool_remove(cookies->string_pool, entry->name); entry->name = tb_null; // exit value if (entry->value) tb_string_pool_remove(cookies->string_pool, entry->value); entry->value = tb_null; } static tb_void_t tb_cookies_entry_free(tb_element_ref_t element, tb_pointer_t buff) { // check tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)buff; tb_assert_and_check_return(element && entry); // the cookies tb_cookies_t* cookies = (tb_cookies_t*)element->priv; tb_assert_and_check_return(cookies && cookies->string_pool); // exit it tb_cookies_entry_exit(cookies, entry); } static tb_size_t tb_cookies_entry_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index) { // check tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)data; tb_assert_and_check_return_val(element && entry && entry->domain, 0); // the cookies tb_cookies_t* cookies = (tb_cookies_t*)element->priv; tb_assert_and_check_return_val(cookies && cookies->string_element.hash, 0); // compute the three hash values tb_size_t v0 = cookies->string_element.hash(&cookies->string_element, entry->domain, mask, index); tb_size_t v1 = entry->path? cookies->string_element.hash(&cookies->string_element, entry->path, mask, index) : 0; tb_size_t v2 = entry->name? cookies->string_element.hash(&cookies->string_element, entry->name, mask, index) : 0; // the hash value return (v0 ^ v1 ^ v2) & mask; } static tb_long_t tb_cookies_entry_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata) { // check tb_cookies_entry_ref_t lentry = (tb_cookies_entry_ref_t)ldata; tb_cookies_entry_ref_t rentry = (tb_cookies_entry_ref_t)rdata; tb_assert_and_check_return_val(lentry && lentry->domain, 0); tb_assert_and_check_return_val(rentry && rentry->domain, 0); // compare domain tb_long_t ok = tb_strcmp(lentry->domain, rentry->domain); tb_check_return_val(!ok, ok); // compare domain ok = tb_strcmp(lentry->path? lentry->path : "", rentry->path? rentry->path : ""); tb_check_return_val(!ok, ok); // compare name return tb_strcmp(lentry->name? lentry->name : "", rentry->name? rentry->name : ""); } static tb_bool_t tb_cookies_entry_init(tb_cookies_t* cookies, tb_cookies_entry_ref_t entry, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_char_t const* value) { // check tb_assert_and_check_return_val(cookies && cookies->string_pool && entry && value, tb_false); // init maxage: -1 entry->maxage = 1; entry->storage = 0; // done tb_char_t const* p = value; tb_char_t const* b = tb_null; tb_char_t const* v = tb_null; tb_char_t data[4096] = {0}; while (1) { // key=value; or value; if (!*p || *p == ';') { // end? tb_check_break(b); // trace tb_trace_d("entry: %s => %s", b? b : "", v? v : ""); // done value if (!tb_strnicmp(b, "expires", 7)) { // must have value tb_assert_and_check_return_val(v, tb_false); // make expires time entry->expires = tb_http_date_from_cstr(v, p - v); } else if (!tb_strnicmp(b, "max-age", 7)) { // must have value tb_assert_and_check_return_val(v, tb_false); // the maxage tb_long_t maxage = tb_stoi32(v); // storage to file? entry->storage = maxage > 0? 1 : 0; // save maxage entry->maxage = tb_abs(maxage); } else if (!tb_strnicmp(b, "domain", 6)) { // must have value tb_assert_and_check_return_val(v, tb_false); // save value tb_assert_and_check_return_val(p - v < sizeof(data), tb_false); if (v < p) { tb_strncpy(data, v, p - v); data[p - v] = '\0'; entry->domain = tb_string_pool_insert(cookies->string_pool, data[0] == '.'? data + 1 : data); } } else if (!tb_strnicmp(b, "path", 4)) { // must have value tb_assert_and_check_return_val(v, tb_false); // save value tb_assert_and_check_return_val(p - v < sizeof(data), tb_false); if (v < p) { tb_strncpy(data, v, p - v); data[p - v] = '\0'; entry->path = tb_string_pool_insert(cookies->string_pool, data); } } else if (!tb_strnicmp(b, "version", 7)) { // must have value tb_assert_and_check_return_val(v, tb_false); } else if (!tb_strnicmp(b, "secure", 6)) entry->secure = 1; // ignore it else if (!tb_strnicmp(b, "HttpOnly", 8)) ; // key=value else if (v) { // must have value tb_assert_and_check_return_val(v > b, tb_false); // save name tb_assert_and_check_return_val(v - b - 1 < sizeof(data), tb_false); tb_strncpy(data, b, v - b - 1); data[v - b - 1] = '\0'; entry->name = tb_string_pool_insert(cookies->string_pool, data); tb_assert_and_check_return_val(entry->name, tb_false); // save value tb_assert_and_check_return_val(p - v < sizeof(data), tb_false); if (v < p) { tb_strncpy(data, v, p - v); data[p - v] = '\0'; entry->value = tb_string_pool_insert(cookies->string_pool, data); tb_assert_and_check_return_val(entry->value, tb_false); } // trace tb_trace_d("set %s=%s", entry->name, entry->value? entry->value : ""); } // next key-value pair if (*p) { b = tb_null; v = tb_null; p++; } // end else break; } // skip space for name else if (!b && !v && *p == ' ') p++; // point to name else if (!b && *p) b = p++; // point to value else if (!v && *p == '=') v = ++p; // next else p++; } // domain not exists? using the given domain if (!entry->domain && domain) { // the domain size tb_size_t n = tb_strlen(domain); // skip www if (n > 3 && !tb_strnicmp(domain, "www", 3)) { domain += 3; n -= 3; } // skip . if (n && *domain == '.') domain++; // save domain entry->domain = tb_string_pool_insert(cookies->string_pool, domain); } if (!entry->domain) { // trace tb_trace_e("no domain for value: %s", value); return tb_false; } // path not exists? using the given path if (!entry->path) entry->path = tb_string_pool_insert(cookies->string_pool, path? path : "/"); tb_assert_and_check_return_val(entry->path, tb_false); // no secure? using the given secure value if (!entry->secure && secure) entry->secure = 1; // ok return tb_true; } static tb_bool_t tb_cookies_entry_walk(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_value_t* tuple = (tb_value_t*)value; tb_assert(item && tuple); // the entry tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)item; tb_assert(entry && entry->domain); // the domain tb_char_t const* domain = tuple[0].cstr; // the path tb_char_t const* path = tuple[1].cstr; // the secure tb_size_t secure = tuple[2].ul; // the value of key tb_string_ref_t kvalue = (tb_string_ref_t)tuple[3].ptr; tb_assert(kvalue); // expired? if (entry->expires && tb_cache_time() >= entry->expires) { // trace tb_trace_d("expired: %s%s%s: %s = %s", entry->secure? "https://" : "http://", entry->domain, entry->path? entry->path : "", entry->name? entry->name : "", entry->value? entry->value : ""); // remove it return tb_true; } // this cookies is at domain/path? if ( tb_cookies_is_child_domain(entry->domain, domain) && entry->path && entry->name && tb_cookies_is_child_path(entry->path, path) && entry->secure == secure) { // append "key=value; " tb_string_cstrfcat(kvalue, "%s=%s; ", entry->name, entry->value? entry->value : ""); } // continue return tb_false; } /* ////////////////////////////////////////////////////////////////////////////////////// * instance implementation */ static tb_handle_t tb_cookies_instance_init(tb_cpointer_t* ppriv) { return (tb_handle_t)tb_cookies_init(); } static tb_void_t tb_cookies_instance_exit(tb_handle_t cookies, tb_cpointer_t priv) { // dump it #ifdef __tb_debug__ tb_cookies_dump((tb_cookies_ref_t)cookies); #endif // exit it tb_cookies_exit((tb_cookies_ref_t)cookies); } /* ////////////////////////////////////////////////////////////////////////////////////// * interface implementation */ tb_cookies_ref_t tb_cookies() { return (tb_cookies_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_COOKIES, tb_cookies_instance_init, tb_cookies_instance_exit, tb_null, tb_null); } tb_cookies_ref_t tb_cookies_init() { // done tb_bool_t ok = tb_false; tb_cookies_t* cookies = tb_null; do { // make cookies cookies = tb_malloc0_type(tb_cookies_t); tb_assert_and_check_break(cookies); // init lock if (!tb_spinlock_init(&cookies->lock)) break; // init string pool cookies->string_pool = tb_string_pool_init(tb_true); tb_assert_and_check_break(cookies->string_pool); // init cookie pool tb_element_t element = tb_element_mem(sizeof(tb_cookies_entry_t), tb_cookies_entry_free, cookies); element.hash = tb_cookies_entry_hash; element.comp = tb_cookies_entry_comp; cookies->cookie_pool = tb_hash_set_init(TB_HASH_SET_BUCKET_SIZE_MICRO, element); tb_assert_and_check_break(cookies->cookie_pool); // init string element cookies->string_element = tb_element_str(tb_true); // register lock profiler #ifdef TB_LOCK_PROFILER_ENABLE tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&cookies->lock, TB_TRACE_MODULE_NAME); #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit cookies if (cookies) tb_cookies_exit((tb_cookies_ref_t)cookies); cookies = tb_null; } // ok? return (tb_cookies_ref_t)cookies; } tb_void_t tb_cookies_exit(tb_cookies_ref_t self) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return(cookies); // enter tb_spinlock_enter(&cookies->lock); // exit cookie pool if (cookies->cookie_pool) tb_hash_set_exit(cookies->cookie_pool); cookies->cookie_pool = tb_null; // exit string pool if (cookies->string_pool) tb_string_pool_exit(cookies->string_pool); cookies->string_pool = tb_null; // leave tb_spinlock_leave(&cookies->lock); // exit lock tb_spinlock_exit(&cookies->lock); // exit it tb_free(cookies); } tb_void_t tb_cookies_clear(tb_cookies_ref_t self) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return(cookies); // enter tb_spinlock_enter(&cookies->lock); // clear cookie pool if (cookies->cookie_pool) tb_hash_set_clear(cookies->cookie_pool); // clear string pool if (cookies->string_pool) tb_string_pool_clear(cookies->string_pool); // leave tb_spinlock_leave(&cookies->lock); } tb_bool_t tb_cookies_set(tb_cookies_ref_t self, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_char_t const* value) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return_val(cookies, tb_false); // enter tb_spinlock_enter(&cookies->lock); // done tb_bool_t ok = tb_false; tb_cookies_entry_t entry = {0}; do { // check tb_assert_and_check_break(cookies->string_pool && cookies->cookie_pool); // init entry if (!tb_cookies_entry_init(cookies, &entry, domain, path, secure, value)) break; // maxage is zero? remove it if (!entry.maxage && !entry.storage) { // remove it tb_hash_set_remove(cookies->cookie_pool, &entry); // exit it tb_cookies_entry_exit(cookies, &entry); } // set entry else tb_hash_set_insert(cookies->cookie_pool, &entry); // storage to file? if (entry.storage) { // TODO tb_trace1_w("not supports storaging cookies to file now!"); } // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it tb_cookies_entry_exit(cookies, &entry); } // leave tb_spinlock_leave(&cookies->lock); // ok? return ok; } tb_bool_t tb_cookies_set_from_url(tb_cookies_ref_t self, tb_char_t const* url, tb_char_t const* value) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return_val(cookies, tb_false); // get domain and path from the given url tb_bool_t secure = tb_false; tb_char_t domain[256] = {0}; tb_char_t path[TB_PATH_MAXN] = {0}; if (tb_cookies_get_domain_and_path_from_url(url, domain, sizeof(domain) - 1, path, sizeof(path) - 1, &secure)) { // trace tb_trace_d("domain: %s, path: %s, secure: %s", domain, path, secure? "ok" : "no"); // set it with domain and path return tb_cookies_set(self, domain, path, secure, value); } // try to set it without domain and path return tb_cookies_set(self, tb_null, tb_null, tb_false, value); } tb_char_t const* tb_cookies_get(tb_cookies_ref_t self, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_string_ref_t value) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return_val(cookies && domain && value, tb_null); // clear value first tb_string_clear(value); // enter tb_spinlock_enter(&cookies->lock); // done tb_bool_t ok = tb_false; do { // check tb_assert_and_check_break(cookies->string_pool && cookies->cookie_pool); // no path? using the root path if (!path || !path[0]) path = "/"; // skip '.' if (*domain == '.') domain++; // spak the cached time tb_cache_time_spak(); // get the matched values tb_value_t tuple[4]; tuple[0].cstr = domain; tuple[1].cstr = path; tuple[2].ul = secure? 1 : 0; tuple[3].ptr = value; tb_remove_if(cookies->cookie_pool, tb_cookies_entry_walk, tuple); // ok ok = tb_true; } while (0); // failed? if (!ok) tb_string_clear(value); // leave tb_spinlock_leave(&cookies->lock); // ok? return tb_string_size(value)? tb_string_cstr(value) : tb_null; } tb_char_t const* tb_cookies_get_from_url(tb_cookies_ref_t self, tb_char_t const* url, tb_string_ref_t value) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return_val(cookies && value, tb_null); // get domain and path from the given url tb_bool_t secure = tb_false; tb_char_t domain[256] = {0}; tb_char_t path[TB_PATH_MAXN] = {0}; if (!tb_cookies_get_domain_and_path_from_url(url, domain, sizeof(domain) - 1, path, sizeof(path) - 1, &secure)) return tb_null; // trace tb_trace_d("domain: %s, path: %s, secure: %s", domain, path, secure? "ok" : "no"); // get it from domain and path return tb_cookies_get(self, domain, path, secure, value); } #ifdef __tb_debug__ tb_void_t tb_cookies_dump(tb_cookies_ref_t self) { // check tb_cookies_t* cookies = (tb_cookies_t*)self; tb_assert_and_check_return(cookies && cookies->cookie_pool); // enter tb_spinlock_enter(&cookies->lock); // dump tb_trace_i(""); tb_trace_i("cookie: size: %lu", tb_hash_set_size(cookies->cookie_pool)); tb_for_all_if (tb_cookies_entry_ref_t, entry, cookies->cookie_pool, entry) { // the entry tb_assert_and_check_continue(entry->domain); // the date tb_tm_t date = {0}; tb_gmtime(entry->expires, &date); // trace tb_trace_i("%s%s%s: %s = %s, expires: %04ld-%02ld-%02ld %02ld:%02ld:%02ld GMT, week: %d", entry->secure? "https://" : "http://", entry->domain, entry->path? entry->path : "", entry->name? entry->name : "", entry->value? entry->value : "", date.year, date.month, date.mday, date.hour, date.minute, date.second, date.week); } // leave tb_spinlock_leave(&cookies->lock); } #endif tbox-1.6.7/src/tbox/network/cookies.h 0000664 0000000 0000000 00000033212 14142237372 0017550 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file cookies.h * @ingroup network * */ #ifndef TB_NETWORK_HTTP_COOKIES_H #define TB_NETWORK_HTTP_COOKIES_H /* ////////////////////////////////////////////////////////////////////////////////////// * INTRODUCTION * Cookies are a general mechanism which server side connections (such as CGI scripts) * can use to both store and retrieve information on the client side of the connection. * The addition of a simple, persistent, client-side state significantly extends the capabilities * of Web-based client/server applications. * * OVERVIEW * A server, when returning an HTTP object to a client, may also send a piece of state information * which the client will store. Included in that state object is a description of the range of * URLs for which that state is valid. Any future HTTP requests made by the client which fall * in that range will include a transmittal of the current value of the state object from the client back to the server. * The state object is called a cookie, for no compelling reason. * This simple mechanism provides a powerful new tool which enables a host of new types of applications to * be written for web-based environments. Shopping applications can now store information about the currently * selected items, for fee services can send back registration information and free the client from * retyping a user-id on next connection, sites can store per-user preferences on the client, * and have the client supply those preferences every time that site is connected to. * * SPECIFICATION * A cookie is introduced to the client by including a Set-Cookie header as part of an HTTP response, * typically this will be generated by a CGI script. * Syntax of the Set-Cookie HTTP Response Header * This is the format a CGI script would use to add to the HTTP headers a new piece of data which is to be stored * by the client for later retrieval. * Set-Cookie: NAME=VALUE; expires=DATE; * path=PATH; domain=DOMAIN_NAME; secure * * NAME=VALUE * This string is a sequence of characters excluding semi-colon, comma and white space. * If there is a need to place such data in the name or value, some encoding method such as URL style %XX encoding * is recommended, though no encoding is defined or required. * This is the only required attribute on the Set-Cookie header. * * expires=DATE * The expires attribute specifies a date string that defines the valid life time of that cookie. * Once the expiration date has been reached, the cookie will no longer be stored or given out. * The date string is formatted as: * * Wdy, DD-Mon-YYYY HH:MM:SS GMT * This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123, with the variations that the only legal time zone * is GMT and the separators between the elements of the date must be dashes. * expires is an optional attribute. If not specified, the cookie will expire when the user's session ends. * * Note: There is a bug in Netscape Navigator version 1.1 and earlier. Only cookies whose path attribute * is set explicitly to "/" will be properly saved between sessions if they have an expires attribute. * * * domain=DOMAIN_NAME * When searching the cookie list for valid cookies, a comparison of the domain attributes of the cookie * is made with the Internet domain name of the host from which the URL will be fetched. If there is a tail match, * then the cookie will go through path matching to see if it should be sent. * "Tail matching" means that domain attribute is matched against the tail of the fully qualified domain name * of the host. A domain attribute of "acme.com" would match host names "anvil.acme.com" as well as * "shipping.crate.acme.com". * Only hosts within the specified domain can set a cookie for a domain and domains must have at least two (2) * or three (3) periods in them to prevent domains of the form: ".com", ".edu", and "va.us". * Any domain that fails within one of the seven special top level domains listed below only require two periods. * Any other domain requires at least three. The seven special top level domains are: * "COM", "EDU", "NET", "ORG", "GOV", "MIL", and "INT". * * The default value of domain is the host name of the server which generated the cookie response. * * * path=PATH * The path attribute is used to specify the subset of URLs in a domain for which the cookie is valid. * If a cookie has already passed domain matching, then the pathname component of the URL is compared with * the path attribute, and if there is a match, the cookie is considered valid and is sent along with the URL request. * The path "/foo" would match "/foobar" and "/foo/bar.html". The path "/" is the most general path. * If the path is not specified, it as assumed to be the same path as the document being described * by the header which contains the cookie. * * * secure * If a cookie is marked secure, it will only be transmitted if the communications channel with the host * is a secure one. Currently this means that secure cookies will only be sent to HTTPS (HTTP over SSL) servers. * If secure is not specified, a cookie is considered safe to be sent in the clear over unsecured channels. * * max-age * A positive valueindicates that the cookie will expire after that many seconds have passed. * Note that the value is the maximum age when the cookie will expire, not the cookie's current age. * A negative value means that the cookie is not stored persistently and will be deleted when the Web browser exits. * A zero value causes the cookie to be deleted. * The default value is -1 * * Syntax of the Cookie HTTP Request Header * When requesting a URL from an HTTP server, the browser will match the URL against all cookies * and if any of them match, a line containing the name/value pairs of all matching cookies will be included * in the HTTP request. Here is the format of that line: * Cookie: NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ... * * Additional Notes * Multiple Set-Cookie headers can be issued in a single server response. * * Instances of the same path and name will overwrit each other, with the latest instance taking precedence. * Instances of the same path but different names will add additional mappings. * * Setting the path to a higher-level value does not override other more specific path mappings. * If there are multiple matches for a given cookie name, but with separate paths, * all the matching cookies will be sent. (See examples below.) * * The expires header lets the client know when it is safe to purge the mapping but the client is not required to do so. * A client may also delete a cookie before it's expiration date arrives if the number of cookies exceeds * its internal limits. * * When sending cookies to a server, all cookies with a more specific path mapping should be sent before cookies * with less specific path mappings. For example, a cookie "name1=foo" with a path mapping of "/" should be * sent after a cookie "name1=foo2" with a path mapping of "/bar" if they are both to be sent. * * There are limitations on the number of cookies that a client can store at any one time. * This is a specification of the minimum number of cookies that a client should be prepared to receive and store. * 300 total cookies * 4 kilobytes per cookie, where the name and the OPAQUE_STRING combine to form the 4 kilobyte limit. * 20 cookies per server or domain. (note that completely specified hosts and domains are treated as * separate entities and have a 20 cookie limitation for each, not combined) * Servers should not expect clients to be able to exceed these limits. When the 300 cookie limit * or the 20 cookie per server limit is exceeded, clients should delete the least recently used cookie. * When a cookie larger than 4 kilobytes is encountered the cookie should be trimmed to fit, * but the name should remain intact as long as it is less than 4 kilobytes. * * If a CGI script wishes to delete a cookie, it can do so by returning a cookie with the same name, * and an expires time which is in the past. The path and name must match exactly in order for the expiring cookie * to replace the valid cookie. This requirement makes it difficult for anyone but the originator of a cookie * to delete a cookie. * * When caching HTTP, as a proxy server might do, the Set-cookie response header should never be cached. * * If a proxy server receives a response which contains a Set-cookie header, * it should propagate the Set-cookie header to the client, regardless of whether the response was 304 (Not Modified) * or 200 (OK). * Similarly, if a client request contains a Cookie: header, it should be forwarded through a proxy, * even if the conditional If-modified-since request is being made. * * EXAMPLES * Here are some sample exchanges which are designed to illustrate the use of cookies. * First Example transaction sequence: * Client requests a document, and receives in the response: * Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT * When client requests a URL in path "/" on this server, it sends: * Cookie: CUSTOMER=WILE_E_COYOTE * Client requests a document, and receives in the response: * Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/ * When client requests a URL in path "/" on this server, it sends: * Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 * Client receives: * Set-Cookie: SHIPPING=FEDEX; path=/foo * When client requests a URL in path "/" on this server, it sends: * Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 * When client requests a URL in path "/foo" on this server, it sends: * Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX * Second Example transaction sequence: * Assume all mappings from above have been cleared. * * Client receives: * Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/ * When client requests a URL in path "/" on this server, it sends: * Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001 * Client receives: * Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo * When client requests a URL in path "/ammo" on this server, it sends: * Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001 * NOTE: There are two name/value pairs named "PART_NUMBER" due to the inheritance of the "/" mapping * in addition to the "/ammo" mapping. * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../string/string.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the cookies ref type typedef __tb_typeref__(cookies); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the cookies instances * * @return the cookies */ tb_cookies_ref_t tb_cookies(tb_noarg_t); /*! init cookies * * @return the cookies */ tb_cookies_ref_t tb_cookies_init(tb_noarg_t); /*! exit cookies * * @param cookies the cookies */ tb_void_t tb_cookies_exit(tb_cookies_ref_t cookies); /*! set cookies from the given domain and path * * @param cookies the cookies * @param domain the domain, .e.g .xxx.com or xxx.com and compatible www.xxx.com * @param path the path, .e.g /root/path * @param secure is secure? * @param value the value * * @return tb_true or tb_false */ tb_bool_t tb_cookies_set(tb_cookies_ref_t cookies, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_char_t const* value); /*! set cookies from the given url * * @param cookies the cookies * @param url the url * @param value the value * * @return tb_true or tb_false */ tb_bool_t tb_cookies_set_from_url(tb_cookies_ref_t cookies, tb_char_t const* url, tb_char_t const* value); /*! get cookies from the given domain and path * * @param cookies the cookies * @param domain the domain, .e.g .xxx.com or xxx.com and compatible www.xxx.com * @param path the path, .e.g /root/path * @param secure is secure? * @param value the cookies value * * @return the cookies data */ tb_char_t const* tb_cookies_get(tb_cookies_ref_t cookies, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_string_ref_t value); /*! get cookies from the given url * * @param cookies the cookies * @param url the url * @param value the cookies value * * @return the cookies data */ tb_char_t const* tb_cookies_get_from_url(tb_cookies_ref_t cookies, tb_char_t const* url, tb_string_ref_t value); /*! clear cookies * * @param cookies the cookies */ tb_void_t tb_cookies_clear(tb_cookies_ref_t cookies); #ifdef __tb_debug__ /*! dump cookies * * @param cookies the cookies */ tb_void_t tb_cookies_dump(tb_cookies_ref_t cookies); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/dns/ 0000775 0000000 0000000 00000000000 14142237372 0016526 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/network/dns/cache.c 0000664 0000000 0000000 00000015711 14142237372 0017742 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file cache.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "dns_cache" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "cache.h" #include "../../platform/platform.h" #include "../../container/container.h" #include "../../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the cache maxn #ifdef __tb_small__ # define TB_DNS_CACHE_MAXN (64) #else # define TB_DNS_CACHE_MAXN (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the dns cache type typedef struct __tb_dns_cache_t { // the hash tb_hash_map_ref_t hash; // the times tb_hize_t times; // the expired tb_size_t expired; }tb_dns_cache_t; // the dns cache addr type typedef struct __tb_dns_cache_addr_t { // the addr tb_ipaddr_t addr; // the time tb_size_t time; }tb_dns_cache_addr_t; /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // the lock static tb_spinlock_t g_lock = TB_SPINLOCK_INIT; // the cache static tb_dns_cache_t g_cache = {0}; /* ////////////////////////////////////////////////////////////////////////////////////// * helper */ static __tb_inline__ tb_size_t tb_dns_cache_now() { return (tb_size_t)(tb_cache_time_spak() / 1000); } static tb_bool_t tb_dns_cache_clear(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert(item); // the dns cache address tb_dns_cache_addr_t const* caddr = (tb_dns_cache_addr_t const*)((tb_hash_map_item_ref_t)item)->data; tb_assert(caddr); // is expired? tb_bool_t ok = tb_false; if (caddr->time < g_cache.expired) { // remove it ok = tb_true; // trace tb_trace_d("del: %s => %{ipaddr}, time: %u, size: %u", (tb_char_t const*)item->name, &caddr->addr, caddr->time, tb_hash_map_size(g_cache.hash)); // update times tb_assert(g_cache.times >= caddr->time); g_cache.times -= caddr->time; } // ok? return ok; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_dns_cache_init() { // enter tb_spinlock_enter(&g_lock); // done tb_bool_t ok = tb_false; do { // init hash if (!g_cache.hash) g_cache.hash = tb_hash_map_init(tb_align8(tb_isqrti(TB_DNS_CACHE_MAXN) + 1), tb_element_str(tb_false), tb_element_mem(sizeof(tb_dns_cache_addr_t), tb_null, tb_null)); tb_assert_and_check_break(g_cache.hash); // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&g_lock); // failed? exit it if (!ok) tb_dns_cache_exit(); // ok? return ok; } tb_void_t tb_dns_cache_exit() { // enter tb_spinlock_enter(&g_lock); // exit hash if (g_cache.hash) tb_hash_map_exit(g_cache.hash); g_cache.hash = tb_null; // exit times g_cache.times = 0; // exit expired g_cache.expired = 0; // leave tb_spinlock_leave(&g_lock); } tb_bool_t tb_dns_cache_get(tb_char_t const* name, tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return_val(name && addr, tb_false); // trace tb_trace_d("get: %s", name); // is addr? tb_check_return_val(!tb_ipaddr_ip_cstr_set(addr, name, TB_IPADDR_FAMILY_NONE), tb_true); // is localhost? if (!tb_stricmp(name, "localhost")) { // save address tb_ipaddr_ip_cstr_set(addr, "127.0.0.1", TB_IPADDR_FAMILY_IPV4); // ok return tb_true; } // clear address tb_ipaddr_clear(addr); // enter tb_spinlock_enter(&g_lock); // done tb_bool_t ok = tb_false; do { // check tb_assert_and_check_break(g_cache.hash); // get the host address tb_dns_cache_addr_t* caddr = (tb_dns_cache_addr_t*)tb_hash_map_get(g_cache.hash, name); tb_check_break(caddr); // trace tb_trace_d("get: %s => %{ipaddr}, time: %u => %u, size: %u", name, &caddr->addr, caddr->time, tb_dns_cache_now(), tb_hash_map_size(g_cache.hash)); // update time tb_assert_and_check_break(g_cache.times >= caddr->time); g_cache.times -= caddr->time; caddr->time = tb_dns_cache_now(); g_cache.times += caddr->time; // save address tb_ipaddr_copy(addr, &caddr->addr); // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&g_lock); // ok? return ok; } tb_void_t tb_dns_cache_set(tb_char_t const* name, tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return(name && addr); // check address tb_assert(!tb_ipaddr_ip_is_empty(addr)); // trace tb_trace_d("set: %s => %{ipaddr}", name, addr); // init addr tb_dns_cache_addr_t caddr; caddr.time = tb_dns_cache_now(); tb_ipaddr_copy(&caddr.addr, addr); // enter tb_spinlock_enter(&g_lock); // done do { // check tb_assert_and_check_break(g_cache.hash); // remove the expired items if full if (tb_hash_map_size(g_cache.hash) >= TB_DNS_CACHE_MAXN) { // the expired time g_cache.expired = ((tb_size_t)(g_cache.times / tb_hash_map_size(g_cache.hash)) + 1); // check tb_assert_and_check_break(g_cache.expired); // trace tb_trace_d("expired: %lu", g_cache.expired); // remove the expired times tb_remove_if(g_cache.hash, tb_dns_cache_clear, tb_null); } // check tb_assert_and_check_break(tb_hash_map_size(g_cache.hash) < TB_DNS_CACHE_MAXN); // save addr tb_hash_map_insert(g_cache.hash, name, &caddr); // update times g_cache.times += caddr.time; // trace tb_trace_d("set: %s => %{ipaddr}, time: %u, size: %u", name, &caddr.addr, caddr.time, tb_hash_map_size(g_cache.hash)); } while (0); // leave tb_spinlock_leave(&g_lock); } tbox-1.6.7/src/tbox/network/dns/cache.h 0000664 0000000 0000000 00000003600 14142237372 0017741 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file cache.h * @ingroup network * */ #ifndef TB_NETWORK_DNS_CACHE_H #define TB_NETWORK_DNS_CACHE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init the cache list * * not using ctime default * * @return tb_true or tb_false */ tb_bool_t tb_dns_cache_init(tb_noarg_t); /// exit the cache list tb_void_t tb_dns_cache_exit(tb_noarg_t); /*! get addr from cache * * @param name the host name * @param addr the host addr * * @return tb_true or tb_false */ tb_bool_t tb_dns_cache_get(tb_char_t const* name, tb_ipaddr_ref_t addr); /*! set addr to cache * * @param name the host name * @param addr the host addr */ tb_void_t tb_dns_cache_set(tb_char_t const* name, tb_ipaddr_ref_t addr); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/dns/dns.h 0000664 0000000 0000000 00000001706 14142237372 0017467 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file dns.h * @ingroup network * */ #ifndef TB_NETWORK_DNS_H #define TB_NETWORK_DNS_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "cache.h" #include "server.h" #include "looker.h" #endif tbox-1.6.7/src/tbox/network/dns/looker.c 0000664 0000000 0000000 00000052227 14142237372 0020175 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file looker.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "dns_looker" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "looker.h" #include "cache.h" #include "server.h" #include "../../string/string.h" #include "../../memory/memory.h" #include "../../network/network.h" #include "../../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the dns looker timeout #define TB_DNS_LOOKER_TIMEOUT (5000) /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ // the dns looker step enum typedef enum __tb_dns_looker_step_e { TB_DNS_LOOKER_STEP_NONE = 0 , TB_DNS_LOOKER_STEP_REQT = 1 , TB_DNS_LOOKER_STEP_RESP = 2 , TB_DNS_LOOKER_STEP_NEVT = 4 }tb_dns_looker_step_e; // the dns looker type typedef struct __tb_dns_looker_t { // the name tb_static_string_t name; // the request and response packet tb_static_buffer_t rpkt; // the size for recv and send packet tb_size_t size; // the iterator tb_size_t itor; // the step tb_size_t step; // the tryn tb_size_t tryn; // the socket tb_socket_ref_t sock; // the socket family tb_uint8_t family; // the server list tb_ipaddr_t list[2]; // the server maxn tb_size_t maxn; // the data tb_byte_t data[TB_DNS_NAME_MAXN + TB_DNS_RPKT_MAXN]; }tb_dns_looker_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_long_t tb_dns_looker_reqt(tb_dns_looker_t* looker) { // check tb_check_return_val(!(looker->step & TB_DNS_LOOKER_STEP_REQT), 1); // format it first if the request is null if (!tb_static_buffer_size(&looker->rpkt)) { // check size tb_assert_and_check_return_val(!looker->size, -1); // format query tb_static_stream_t stream; tb_byte_t rpkt[TB_DNS_RPKT_MAXN]; tb_size_t size = 0; tb_byte_t* p = tb_null; tb_static_stream_init(&stream, rpkt, TB_DNS_RPKT_MAXN); // identification number tb_static_stream_writ_u16_be(&stream, TB_DNS_HEADER_MAGIC); /* 0x2104: 0 0000 001 0000 0000 * * tb_uint16_t qr :1; // query/response flag * tb_uint16_t opcode :4; // purpose of message * tb_uint16_t aa :1; // authoritive answer * tb_uint16_t tc :1; // truncated message * tb_uint16_t rd :1; // recursion desired * tb_uint16_t ra :1; // recursion available * tb_uint16_t z :1; // its z! reserved * tb_uint16_t ad :1; // authenticated data * tb_uint16_t cd :1; // checking disabled * tb_uint16_t rcode :4; // response code * * this is a query * this is a standard query * not authoritive answer * not truncated * recursion desired * * recursion not available! hey we dont have it (lol) * */ #if 1 tb_static_stream_writ_u16_be(&stream, 0x0100); #else tb_static_stream_writ_u1(&stream, 0); // this is a query tb_static_stream_writ_ubits32(&stream, 0, 4); // this is a standard query tb_static_stream_writ_u1(&stream, 0); // not authoritive answer tb_static_stream_writ_u1(&stream, 0); // not truncated tb_static_stream_writ_u1(&stream, 1); // recursion desired tb_static_stream_writ_u1(&stream, 0); // recursion not available! hey we dont have it (lol) tb_static_stream_writ_u1(&stream, 0); tb_static_stream_writ_u1(&stream, 0); tb_static_stream_writ_u1(&stream, 0); tb_static_stream_writ_ubits32(&stream, 0, 4); #endif /* we have only one question * * tb_uint16_t question; // number of question entries * tb_uint16_t answer; // number of answer entries * tb_uint16_t authority; // number of authority entries * tb_uint16_t resource; // number of resource entries * */ tb_static_stream_writ_u16_be(&stream, 1); tb_static_stream_writ_u16_be(&stream, 0); tb_static_stream_writ_u16_be(&stream, 0); tb_static_stream_writ_u16_be(&stream, 0); // set questions, see as tb_dns_question_t // name + question1 + question2 + ... tb_static_stream_writ_u8(&stream, '.'); p = (tb_byte_t*)tb_static_stream_writ_cstr(&stream, tb_static_string_cstr(&looker->name)); // only one question now. tb_static_stream_writ_u16_be(&stream, 1); // we are requesting the ipv4 address tb_static_stream_writ_u16_be(&stream, 1); // it's internet (lol) // encode dns name if (!p || !tb_dns_encode_name((tb_char_t*)p - 1)) return -1; // size size = tb_static_stream_offset(&stream); tb_assert_and_check_return_val(size, -1); // copy tb_static_buffer_memncpy(&looker->rpkt, rpkt, size); } // data && size tb_byte_t const* data = tb_static_buffer_data(&looker->rpkt); tb_size_t size = tb_static_buffer_size(&looker->rpkt); // check tb_assert_and_check_return_val(data && size && looker->size < size, -1); // try get addr from the dns list tb_ipaddr_ref_t addr = tb_null; if (looker->maxn && looker->itor && looker->itor <= looker->maxn) addr = &looker->list[looker->itor - 1]; // check tb_assert_and_check_return_val(addr && !tb_ipaddr_is_empty(addr), -1); // family have been changed? reinit socket if (tb_ipaddr_family(addr) != looker->family) { // exit the previous socket if (looker->sock) tb_socket_exit(looker->sock); // init a new socket for the family looker->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, tb_ipaddr_family(addr)); tb_assert_and_check_return_val(looker->sock, -1); // update the new family looker->family = (tb_uint8_t)tb_ipaddr_family(addr); } // need wait if no data looker->step &= ~TB_DNS_LOOKER_STEP_NEVT; // trace tb_trace_d("request: try %{ipaddr}", addr); // send request while (looker->size < size) { // writ data tb_long_t writ = tb_socket_usend(looker->sock, addr, data + looker->size, size - looker->size); tb_assert_and_check_return_val(writ >= 0, -1); // no data? if (!writ) { // abort? tb_check_return_val(!looker->size && !looker->tryn, -1); // tryn++ looker->tryn++; // continue return 0; } else looker->tryn = 0; // update size looker->size += writ; } // finish it looker->step |= TB_DNS_LOOKER_STEP_REQT; looker->tryn = 0; // reset rpkt looker->size = 0; tb_static_buffer_clear(&looker->rpkt); // ok tb_trace_d("request: ok"); return 1; } static tb_bool_t tb_dns_looker_resp_done(tb_dns_looker_t* looker, tb_ipaddr_ref_t addr) { // the rpkt and size tb_byte_t const* rpkt = tb_static_buffer_data(&looker->rpkt); tb_size_t size = tb_static_buffer_size(&looker->rpkt); tb_assert_and_check_return_val(rpkt && size >= TB_DNS_HEADER_SIZE, tb_false); // init stream tb_static_stream_t stream; tb_static_stream_init(&stream, (tb_byte_t*)rpkt, size); // init header tb_dns_header_t header; header.id = tb_static_stream_read_u16_be(&stream); tb_static_stream_skip(&stream, 2); header.question = tb_static_stream_read_u16_be(&stream); header.answer = tb_static_stream_read_u16_be(&stream); header.authority = tb_static_stream_read_u16_be(&stream); header.resource = tb_static_stream_read_u16_be(&stream); // trace tb_trace_d("response: size: %u", size); tb_trace_d("response: id: 0x%04x", header.id); tb_trace_d("response: question: %d", header.question); tb_trace_d("response: answer: %d", header.answer); tb_trace_d("response: authority: %d", header.authority); tb_trace_d("response: resource: %d", header.resource); tb_trace_d(""); // check header tb_assert_and_check_return_val(header.id == TB_DNS_HEADER_MAGIC, tb_false); // skip questions, only one question now. // name + question1 + question2 + ... tb_assert_and_check_return_val(header.question == 1, tb_false); #if 1 tb_static_stream_skip_cstr(&stream); tb_static_stream_skip(&stream, 4); #else tb_char_t* name = tb_static_stream_read_cstr(&stream); //name = tb_dns_decode_name(name); tb_assert_and_check_return_val(name, tb_false); tb_static_stream_skip(&stream, 4); tb_trace_d("response: name: %s", name); #endif // decode answers tb_size_t i = 0; tb_size_t found = 0; for (i = 0; i < header.answer; i++) { // decode answer tb_dns_answer_t answer; tb_trace_d("response: answer: %d", i); // decode dns name tb_char_t const* name = tb_dns_decode_name(&stream, answer.name); tb_used(name); tb_trace_d("response: name: %s", name); // decode resource answer.res.type = tb_static_stream_read_u16_be(&stream); answer.res.class_ = tb_static_stream_read_u16_be(&stream); answer.res.ttl = tb_static_stream_read_u32_be(&stream); answer.res.size = tb_static_stream_read_u16_be(&stream); tb_trace_d("response: type: %d", answer.res.type); tb_trace_d("response: class: %d", answer.res.class_); tb_trace_d("response: ttl: %d", answer.res.ttl); tb_trace_d("response: size: %d", answer.res.size); // is ipv4? if (answer.res.type == 1) { // get ipv4 tb_byte_t b1 = tb_static_stream_read_u8(&stream); tb_byte_t b2 = tb_static_stream_read_u8(&stream); tb_byte_t b3 = tb_static_stream_read_u8(&stream); tb_byte_t b4 = tb_static_stream_read_u8(&stream); // trace tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4); // save the first ip if (!found) { // save it if (addr) { // init ipv4 tb_ipv4_t ipv4; ipv4.u8[0] = b1; ipv4.u8[1] = b2; ipv4.u8[2] = b3; ipv4.u8[3] = b4; // save ipv4 tb_ipaddr_ipv4_set(addr, &ipv4); } // found it found = 1; // trace tb_trace_d("response: "); break; } } else { // decode rdata answer.rdata = (tb_byte_t*)tb_dns_decode_name(&stream, answer.name); // trace tb_trace_d("response: alias: %s", answer.rdata? (tb_char_t const*)answer.rdata : ""); } // trace tb_trace_d("response: "); } // found it? tb_check_return_val(found, tb_false); #if 0 // decode authorities for (i = 0; i < header.authority; i++) { // decode answer tb_dns_answer_t answer; tb_trace_d("response: authority: %d", i); // decode dns name tb_char_t* name = tb_dns_decode_name(&stream, answer.name); tb_trace_d("response: name: %s", name? name : ""); // decode resource answer.res.type = tb_static_stream_read_u16_be(&stream); answer.res.class_ = tb_static_stream_read_u16_be(&stream); answer.res.ttl = tb_static_stream_read_u32_be(&stream); answer.res.size = tb_static_stream_read_u16_be(&stream); tb_trace_d("response: type: %d", answer.res.type); tb_trace_d("response: class: %d", answer.res.class_); tb_trace_d("response: ttl: %d", answer.res.ttl); tb_trace_d("response: size: %d", answer.res.size); // is ipv4? if (answer.res.type == 1) { tb_byte_t b1 = tb_static_stream_read_u8(&stream); tb_byte_t b2 = tb_static_stream_read_u8(&stream); tb_byte_t b3 = tb_static_stream_read_u8(&stream); tb_byte_t b4 = tb_static_stream_read_u8(&stream); tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4); } else { // decode data answer.rdata = tb_dns_decode_name(&stream, answer.name); tb_trace_d("response: server: %s", answer.rdata? answer.rdata : ""); } tb_trace_d("response: "); } for (i = 0; i < header.resource; i++) { // decode answer tb_dns_answer_t answer; tb_trace_d("response: resource: %d", i); // decode dns name tb_char_t* name = tb_dns_decode_name(&stream, answer.name); tb_trace_d("response: name: %s", name? name : ""); // decode resource answer.res.type = tb_static_stream_read_u16_be(&stream); answer.res.class_ = tb_static_stream_read_u16_be(&stream); answer.res.ttl = tb_static_stream_read_u32_be(&stream); answer.res.size = tb_static_stream_read_u16_be(&stream); tb_trace_d("response: type: %d", answer.res.type); tb_trace_d("response: class: %d", answer.res.class_); tb_trace_d("response: ttl: %d", answer.res.ttl); tb_trace_d("response: size: %d", answer.res.size); // is ipv4? if (answer.res.type == 1) { tb_byte_t b1 = tb_static_stream_read_u8(&stream); tb_byte_t b2 = tb_static_stream_read_u8(&stream); tb_byte_t b3 = tb_static_stream_read_u8(&stream); tb_byte_t b4 = tb_static_stream_read_u8(&stream); tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4); } else { // decode data answer.rdata = tb_dns_decode_name(&stream, answer.name); tb_trace_d("response: alias: %s", answer.rdata? answer.rdata : ""); } tb_trace_d("response: "); } #endif // ok return tb_true; } static tb_long_t tb_dns_looker_resp(tb_dns_looker_t* looker, tb_ipaddr_ref_t addr) { // check tb_check_return_val(!(looker->step & TB_DNS_LOOKER_STEP_RESP), 1); // need wait if no data looker->step &= ~TB_DNS_LOOKER_STEP_NEVT; // recv response data tb_size_t size = tb_static_buffer_size(&looker->rpkt); tb_size_t maxn = tb_static_buffer_maxn(&looker->rpkt); tb_byte_t* data = tb_static_buffer_data(&looker->rpkt); while (size < maxn) { // read data tb_long_t read = tb_socket_urecv(looker->sock, tb_null, data + size, maxn - size); tb_assert_and_check_return_val(read >= 0, -1); // no data? if (!read) { // end? read x, read 0 tb_check_break(!tb_static_buffer_size(&looker->rpkt)); // abort? read 0, read 0 tb_check_return_val(!looker->tryn, -1); // tryn++ looker->tryn++; // continue return 0; } else looker->tryn = 0; // update buffer size tb_static_buffer_resize(&looker->rpkt, size + read); size = tb_static_buffer_size(&looker->rpkt); } // done if (!tb_dns_looker_resp_done(looker, addr)) return -1; // check tb_assert_and_check_return_val(tb_static_string_size(&looker->name) && !tb_ipaddr_ip_is_empty(addr), -1); // save address to cache tb_dns_cache_set(tb_static_string_cstr(&looker->name), addr); // finish it looker->step |= TB_DNS_LOOKER_STEP_RESP; looker->tryn = 0; // reset rpkt looker->size = 0; tb_static_buffer_clear(&looker->rpkt); // ok tb_trace_d("response: ok"); return 1; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_dns_looker_ref_t tb_dns_looker_init(tb_char_t const* name) { // check tb_assert_and_check_return_val(name, tb_null); // must be not address tb_assert(!tb_ipaddr_ip_cstr_set(tb_null, name, TB_IPADDR_FAMILY_NONE)); // done tb_bool_t ok = tb_false; tb_dns_looker_t* looker = tb_null; do { // make looker looker = tb_malloc0_type(tb_dns_looker_t); tb_assert_and_check_return_val(looker, tb_null); // dump server // tb_dns_server_dump(); // get the dns server list looker->maxn = tb_dns_server_get(looker->list); tb_check_break(looker->maxn && looker->maxn <= tb_arrayn(looker->list)); // init name if (!tb_static_string_init(&looker->name, (tb_char_t*)looker->data, TB_DNS_NAME_MAXN)) break; tb_static_string_cstrcpy(&looker->name, name); // init rpkt if (!tb_static_buffer_init(&looker->rpkt, looker->data + TB_DNS_NAME_MAXN, TB_DNS_RPKT_MAXN)) break; // init family looker->family = TB_IPADDR_FAMILY_IPV4; // init sock looker->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, looker->family); tb_assert_and_check_break(looker->sock); // init itor looker->itor = 1; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (looker) tb_dns_looker_exit((tb_dns_looker_ref_t)looker); looker = tb_null; } // ok? return (tb_dns_looker_ref_t)looker; } tb_long_t tb_dns_looker_spak(tb_dns_looker_ref_t self, tb_ipaddr_ref_t addr) { // check tb_dns_looker_t* looker = (tb_dns_looker_t*)self; tb_assert_and_check_return_val(looker && addr, -1); // init tb_long_t r = -1; do { // request r = tb_dns_looker_reqt(looker); tb_check_break(r > 0); // response r = tb_dns_looker_resp(looker, addr); tb_check_break(r > 0); } while (0); // failed? if (r < 0) { // next if (looker->itor + 1 <= looker->maxn) looker->itor++; else looker->itor = 0; // has next? if (looker->itor) { // reset step, no event now, need not wait looker->step = TB_DNS_LOOKER_STEP_NONE | TB_DNS_LOOKER_STEP_NEVT; // reset rpkt looker->size = 0; tb_static_buffer_clear(&looker->rpkt); // continue r = 0; } } // ok? return r; } tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t self, tb_long_t timeout) { // check tb_dns_looker_t* looker = (tb_dns_looker_t*)self; tb_assert_and_check_return_val(looker && looker->sock, -1); // has io event? tb_size_t e = TB_SOCKET_EVENT_NONE; if (!(looker->step & TB_DNS_LOOKER_STEP_NEVT)) { if (!(looker->step & TB_DNS_LOOKER_STEP_REQT)) e = TB_SOCKET_EVENT_SEND; else if (!(looker->step & TB_DNS_LOOKER_STEP_RESP)) e = TB_SOCKET_EVENT_RECV; } // need wait? tb_long_t r = 0; if (e) { // trace tb_trace_d("waiting %p ..", looker->sock); // wait r = tb_socket_wait(looker->sock, e, timeout); // fail or timeout? tb_check_return_val(r > 0, r); } // ok? return r; } tb_void_t tb_dns_looker_exit(tb_dns_looker_ref_t self) { // the looker tb_dns_looker_t* looker = (tb_dns_looker_t*)self; if (looker) { // exit sock if (looker->sock) tb_socket_exit(looker->sock); looker->sock = tb_null; // exit it tb_free(looker); } } tb_bool_t tb_dns_looker_done(tb_char_t const* name, tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return_val(name && addr, tb_false); // try to lookup it from cache first if (tb_dns_cache_get(name, addr)) return tb_true; // init looker tb_dns_looker_ref_t looker = tb_dns_looker_init(name); tb_check_return_val(looker, tb_false); // spak tb_long_t r = -1; while (!(r = tb_dns_looker_spak(looker, addr))) { // wait r = tb_dns_looker_wait(looker, TB_DNS_LOOKER_TIMEOUT); tb_assert_and_check_break(r >= 0); } // exit tb_dns_looker_exit(looker); // ok return r > 0? tb_true : tb_false; } tbox-1.6.7/src/tbox/network/dns/looker.h 0000664 0000000 0000000 00000004745 14142237372 0020204 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file looker.h * @ingroup network * */ #ifndef TB_NETWORK_DNS_LOOKER_H #define TB_NETWORK_DNS_LOOKER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the dns looker type typedef __tb_typeref__(dns_looker); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init for looking ipv4 from the host name, non-block * * @param name the host name * * @return the looker handle */ tb_dns_looker_ref_t tb_dns_looker_init(tb_char_t const* name); /*! spak the looker * * @param looker the looker * @param addr the address * * @return 1: ok, 0: continue: -1: failed */ tb_long_t tb_dns_looker_spak(tb_dns_looker_ref_t looker, tb_ipaddr_ref_t addr); /*! wait the looker * * @param looker the looker * @param timeout the timeout * * @return 1: ok, 0: continue: -1: failed */ tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t looker, tb_long_t timeout); /*! exit the looker * * @param looker the looker */ tb_void_t tb_dns_looker_exit(tb_dns_looker_ref_t looker); /*! lookup address from the host name, block * * try to look it from cache first * * @param name the host name * @param addr the address * * @return tb_true or tb_false */ tb_bool_t tb_dns_looker_done(tb_char_t const* name, tb_ipaddr_ref_t addr); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/dns/prefix.h 0000664 0000000 0000000 00000011723 14142237372 0020200 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_NETWORK_DNS_PREFIX_H #define TB_NETWORK_DNS_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../ipaddr.h" #include "../../utils/utils.h" #include "../../stream/static_stream.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the protocol header #define TB_DNS_HEADER_SIZE (12) #define TB_DNS_HEADER_MAGIC (0xbeef) // the protocol port #define TB_DNS_HOST_PORT (53) // the name maximum size #define TB_DNS_NAME_MAXN (256) // the rpkt maximum size #define TB_DNS_RPKT_MAXN (TB_DNS_HEADER_SIZE + TB_DNS_NAME_MAXN + 256) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the dns header type typedef struct __tb_dns_header_t { tb_uint16_t id; // identification number tb_uint16_t qr :1; // query/response flag tb_uint16_t opcode :4; // purpose of message tb_uint16_t aa :1; // authoritive answer tb_uint16_t tc :1; // truncated message tb_uint16_t rd :1; // recursion desired tb_uint16_t ra :1; // recursion available tb_uint16_t z :1; // its z! reserved tb_uint16_t ad :1; // authenticated data tb_uint16_t cd :1; // checking disabled tb_uint16_t rcode :4; // response code tb_uint16_t question; // number of question entries tb_uint16_t answer; // number of answer entries tb_uint16_t authority; // number of authority entries tb_uint16_t resource; // number of resource entries }tb_dns_header_t; // the dns question type typedef struct __tb_dns_question_t { tb_uint16_t type; tb_uint16_t class_; }tb_dns_question_t; // the dns resource type typedef struct __tb_dns_resource_t { tb_uint16_t type; tb_uint16_t class_; tb_uint32_t ttl; tb_uint16_t size; }tb_dns_resource_t; // the dns answer type typedef struct __tb_dns_answer_t { tb_char_t name[TB_DNS_NAME_MAXN]; tb_dns_resource_t res; tb_byte_t const* rdata; }tb_dns_answer_t; /* ////////////////////////////////////////////////////////////////////////////////////// * inlines */ // size + data, e.g. .www.google.com => 3www6google3com static __tb_inline__ tb_char_t const* tb_dns_encode_name(tb_char_t* name) { tb_assert_and_check_return_val(name && name[0] == '.', tb_null); // encode tb_byte_t n = 0; tb_char_t* b = name; tb_char_t* p = name + 1; while (*p) { if (*p == '.') { //*b = '0' + n; *b = (tb_char_t)n; n = 0; b = p; } else n++; p++; } //*b = '0' + n; *b = n; // ok return name; } static __tb_inline__ tb_char_t const* tb_dns_decode_name_impl(tb_char_t const* sb, tb_char_t const* se, tb_char_t const* ps, tb_char_t** pd) { tb_char_t const* p = ps; tb_char_t* q = *pd; while (p < se) { tb_byte_t c = *p++; if (!c) break; // is pointer? 11xxxxxx xxxxxxxx else if (c >= 0xc0) { tb_uint16_t pos = c; pos &= ~0xc0; pos <<= 8; pos |= *p++; tb_dns_decode_name_impl(sb, se, sb + pos, &q); break; } // is ascii? 00xxxxxx else { while (c--) *q++ = *p++; *q++ = '.'; } } *pd = q; return p; } static __tb_inline__ tb_char_t const* tb_dns_decode_name(tb_static_stream_ref_t sstream, tb_char_t* name) { tb_char_t* q = name; tb_char_t* p = (tb_char_t*)tb_dns_decode_name_impl((tb_char_t const*)tb_static_stream_beg(sstream), (tb_char_t const*)tb_static_stream_end(sstream), (tb_char_t const*)tb_static_stream_pos(sstream), &q); if (p) { tb_assert(q - name < TB_DNS_NAME_MAXN); if (q > name && *(q - 1) == '.') *--q = '\0'; tb_static_stream_goto(sstream, (tb_byte_t*)p); return name; } else return tb_null; } #endif tbox-1.6.7/src/tbox/network/dns/server.c 0000664 0000000 0000000 00000034152 14142237372 0020205 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file server.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "dns_server" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "server.h" #include "../../utils/utils.h" #include "../../stream/stream.h" #include "../../network/network.h" #include "../../platform/platform.h" #include "../../container/container.h" #include "../../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the dns server test timeout #define TB_DNS_SERVER_TEST_TIMEOUT (500) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the dns server type typedef struct __tb_dns_server_t { // the rate tb_size_t rate; // the addr tb_ipaddr_t addr; }tb_dns_server_t, *tb_dns_server_ref_t; // the dns server list type typedef struct __tb_dns_server_list_t { // is sorted? tb_bool_t sort; // the server list tb_vector_ref_t list; }tb_dns_server_list_t; /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // the lock static tb_spinlock_t g_lock = TB_SPINLOCK_INIT; // the server list static tb_dns_server_list_t g_list = {0}; /* ////////////////////////////////////////////////////////////////////////////////////// * server */ static tb_long_t tb_dns_server_comp(tb_element_ref_t element, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert(litem && ritem); // the rate tb_size_t lrate = ((tb_dns_server_t const*)litem)->rate; tb_size_t rrate = ((tb_dns_server_t const*)ritem)->rate; // comp return (lrate > rrate? 1 : (lrate < rrate? -1 : 0)); } static tb_long_t tb_dns_server_test(tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return_val(addr && !tb_ipaddr_is_empty(addr), -1); // done tb_static_stream_t sstream; tb_byte_t rpkt[TB_DNS_RPKT_MAXN]; tb_size_t size = 0; tb_long_t rate = -1; tb_socket_ref_t sock = tb_null; do { // trace tb_trace_d("test: %{ipaddr}: ..", addr); // init sock sock = tb_socket_init(TB_SOCKET_TYPE_UDP, tb_ipaddr_family(addr)); tb_assert_and_check_break(sock); // init stream tb_static_stream_init(&sstream, rpkt, TB_DNS_RPKT_MAXN); // identification number tb_static_stream_writ_u16_be(&sstream, TB_DNS_HEADER_MAGIC); /* 0x2104: 0 0000 001 0000 0000 * * tb_uint16_t qr :1; // query/response flag * tb_uint16_t opcode :4; // purpose of message * tb_uint16_t aa :1; // authoritive answer * tb_uint16_t tc :1; // truncated message * tb_uint16_t rd :1; // recursion desired * tb_uint16_t ra :1; // recursion available * tb_uint16_t z :1; // its z! reserved * tb_uint16_t ad :1; // authenticated data * tb_uint16_t cd :1; // checking disabled * tb_uint16_t rcode :4; // response code * * this is a query * this is a standard query * not authoritive answer * not truncated * recursion desired * * recursion not available! hey we dont have it (lol) * */ #if 1 tb_static_stream_writ_u16_be(&sstream, 0x0100); #else tb_static_stream_writ_u1(&sstream, 0); // this is a query tb_static_stream_writ_ubits32(&sstream, 0, 4); // this is a standard query tb_static_stream_writ_u1(&sstream, 0); // not authoritive answer tb_static_stream_writ_u1(&sstream, 0); // not truncated tb_static_stream_writ_u1(&sstream, 1); // recursion desired tb_static_stream_writ_u1(&sstream, 0); // recursion not available! hey we dont have it (lol) tb_static_stream_writ_u1(&sstream, 0); tb_static_stream_writ_u1(&sstream, 0); tb_static_stream_writ_u1(&sstream, 0); tb_static_stream_writ_ubits32(&sstream, 0, 4); #endif /* we have only one question * * tb_uint16_t question; // number of question entries * tb_uint16_t answer; // number of answer entries * tb_uint16_t authority; // number of authority entries * tb_uint16_t resource; // number of resource entries * */ tb_static_stream_writ_u16_be(&sstream, 1); tb_static_stream_writ_u16_be(&sstream, 0); tb_static_stream_writ_u16_be(&sstream, 0); tb_static_stream_writ_u16_be(&sstream, 0); // set questions, see as tb_dns_question_t // name + question1 + question2 + ... tb_static_stream_writ_u8(&sstream, 3); tb_static_stream_writ_u8(&sstream, 'w'); tb_static_stream_writ_u8(&sstream, 'w'); tb_static_stream_writ_u8(&sstream, 'w'); tb_static_stream_writ_u8(&sstream, 5); tb_static_stream_writ_u8(&sstream, 't'); tb_static_stream_writ_u8(&sstream, 'b'); tb_static_stream_writ_u8(&sstream, 'o'); tb_static_stream_writ_u8(&sstream, 'o'); tb_static_stream_writ_u8(&sstream, 'x'); tb_static_stream_writ_u8(&sstream, 3); tb_static_stream_writ_u8(&sstream, 'o'); tb_static_stream_writ_u8(&sstream, 'r'); tb_static_stream_writ_u8(&sstream, 'g'); tb_static_stream_writ_u8(&sstream, '\0'); // only one question now. tb_static_stream_writ_u16_be(&sstream, 1); // we are requesting the ipv4 address tb_static_stream_writ_u16_be(&sstream, 1); // it's internet (lol) // size size = tb_static_stream_offset(&sstream); tb_assert_and_check_break(size); // init time tb_hong_t time = tb_cache_time_spak(); // se/nd request tb_size_t writ = 0; tb_bool_t fail = tb_false; while (writ < size) { // writ data tb_long_t real = tb_socket_usend(sock, addr, rpkt + writ, size - writ); // trace tb_trace_d("writ %ld", real); // check tb_check_break_state(real >= 0, fail, tb_true); // no data? if (!real) { // abort? tb_check_break_state(!writ, fail, tb_true); // wait real = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, TB_DNS_SERVER_TEST_TIMEOUT); // fail or timeout? tb_check_break_state(real > 0, fail, tb_true); } else writ += real; } // failed? tb_check_break(!fail); // only recv id & answer, 8 bytes tb_long_t read = 0; while (read < 8) { // read data tb_long_t r = tb_socket_urecv(sock, tb_null, rpkt + read, TB_DNS_RPKT_MAXN - read); // trace tb_trace_d("read %ld", r); // check tb_check_break(r >= 0); // no data? if (!r) { // end? tb_check_break(!read); // wait r = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, TB_DNS_SERVER_TEST_TIMEOUT); // trace tb_trace_d("wait %ld", r); // fail or timeout? tb_check_break(r > 0); } else read += r; } // check tb_check_break(read >= 8); // check protocol tb_size_t id = tb_bits_get_u16_be(rpkt); tb_check_break(id == TB_DNS_HEADER_MAGIC); // check answer tb_size_t answer = tb_bits_get_u16_be(rpkt + 6); tb_check_break(answer > 0); // rate rate = (tb_long_t)(tb_cache_time_spak() - time); // ok tb_trace_d("test: %{ipaddr} ok, rate: %u", addr, rate); } while (0); // exit sock tb_socket_exit(sock); // ok return rate; } static tb_bool_t tb_dns_server_rate(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // the server tb_bool_t ok = tb_false; tb_dns_server_ref_t server = (tb_dns_server_ref_t)item; if (server && !server->rate) { // done tb_bool_t done = tb_false; do { // the server rate tb_long_t rate = tb_dns_server_test(&server->addr); tb_check_break(rate >= 0); // save the server rate server->rate = rate; // ok done = tb_true; } while (0); // failed? remove it if (!done) ok = tb_true; } // ok? return ok; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_dns_server_init() { // enter tb_spinlock_enter(&g_lock); // done tb_bool_t ok = tb_false; do { // init list if (!g_list.list) { g_list.list = tb_vector_init(8, tb_element_mem(sizeof(tb_dns_server_t), tb_null, tb_null)); g_list.sort = tb_false; } tb_assert_and_check_break(g_list.list); // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&g_lock); // failed? exit it if (!ok) tb_dns_server_exit(); // ok? return ok; } tb_void_t tb_dns_server_exit() { // enter tb_spinlock_enter(&g_lock); // exit list if (g_list.list) tb_vector_exit(g_list.list); g_list.list = tb_null; // exit sort g_list.sort = tb_false; // leave tb_spinlock_leave(&g_lock); } tb_void_t tb_dns_server_dump() { // enter tb_spinlock_enter(&g_lock); // dump list if (g_list.list) { // trace tb_trace_i("============================================================"); tb_trace_i("list: %u servers", tb_vector_size(g_list.list)); // walk tb_size_t i = 0; tb_size_t n = tb_vector_size(g_list.list); for (; i < n; i++) { tb_dns_server_t const* server = (tb_dns_server_t const*)tb_iterator_item(g_list.list, i); if (server) { // trace tb_trace_i("server: %{ipaddr}, rate: %u", &server->addr, server->rate); } } } // leave tb_spinlock_leave(&g_lock); } tb_void_t tb_dns_server_sort() { // enter tb_spinlock_enter(&g_lock); // done tb_vector_ref_t list = tb_null; do { // check tb_assert_and_check_break(g_list.list); // need sort? tb_check_break(!g_list.sort); // init element tb_element_t element = tb_element_mem(sizeof(tb_dns_server_t), tb_null, tb_null); element.comp = tb_dns_server_comp; // init list list = tb_vector_init(8, element); tb_assert_and_check_break(list); // copy list tb_vector_copy(list, g_list.list); } while (0); /* sort ok, only done once sort * using the unsorted server list at the other thread if the sort have been not finished */ g_list.sort = tb_true; // leave tb_spinlock_leave(&g_lock); // need sort? tb_check_return(list); // rate list and remove no-rate servers tb_remove_if(list, tb_dns_server_rate, tb_null); // sort list tb_sort_all(list, tb_null); // enter tb_spinlock_enter(&g_lock); // save the sorted server list if (tb_vector_size(list)) tb_vector_copy(g_list.list, list); else { // no faster server? using the previous server list tb_trace_w("no faster server"); } // leave tb_spinlock_leave(&g_lock); // exit list tb_vector_exit(list); } tb_size_t tb_dns_server_get(tb_ipaddr_t addr[2]) { // check tb_assert_and_check_return_val(addr, 0); // sort first tb_dns_server_sort(); // enter tb_spinlock_enter(&g_lock); // done tb_size_t ok = 0; do { // check tb_assert_and_check_break(g_list.list && g_list.sort); // init tb_size_t i = 0; tb_size_t n = tb_min(tb_vector_size(g_list.list), 2); tb_assert_and_check_break(n <= 2); // done for (; i < n; i++) { // the dns server tb_dns_server_t const* server = (tb_dns_server_t const*)tb_iterator_item(g_list.list, i); if (server) { // save addr addr[ok++] = server->addr; } } } while (0); // leave tb_spinlock_leave(&g_lock); // trace tb_assertf(ok, "no server!"); // ok? return ok; } tb_void_t tb_dns_server_add(tb_char_t const* addr) { // check tb_assert_and_check_return(addr); // init first tb_dns_server_init(); // enter tb_spinlock_enter(&g_lock); // done do { // check tb_assert_and_check_break(g_list.list); // init server tb_dns_server_t server = {0}; if (!tb_ipaddr_set(&server.addr, addr, TB_DNS_HOST_PORT, TB_IPADDR_FAMILY_NONE)) break; // add server tb_vector_insert_tail(g_list.list, &server); // need sort it again g_list.sort = tb_false; } while (0); // leave tb_spinlock_leave(&g_lock); } tbox-1.6.7/src/tbox/network/dns/server.h 0000664 0000000 0000000 00000003706 14142237372 0020213 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file server.h * @ingroup network * */ #ifndef TB_NETWORK_DNS_SERVER_H #define TB_NETWORK_DNS_SERVER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init the server list * * @return tb_true or tb_false */ tb_bool_t tb_dns_server_init(tb_noarg_t); /// exit the server list tb_void_t tb_dns_server_exit(tb_noarg_t); /// dump the server list tb_void_t tb_dns_server_dump(tb_noarg_t); /// sort the server list by the response speed tb_void_t tb_dns_server_sort(tb_noarg_t); /*! get the server * * @param addr the server address list, addr[0] is the fastest * * @return the server size */ tb_size_t tb_dns_server_get(tb_ipaddr_t addr[2]); /*! add the server * * @param addr the server address */ tb_void_t tb_dns_server_add(tb_char_t const* addr); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/http.c 0000664 0000000 0000000 00000075225 14142237372 0017100 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file http.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "http" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "http.h" #include "impl/http/date.h" #include "impl/http/option.h" #include "impl/http/status.h" #include "impl/http/method.h" #include "../zip/zip.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../string/string.h" #include "../stream/stream.h" #include "../platform/platform.h" #include "../algorithm/algorithm.h" #include "../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the http type typedef struct __tb_http_t { // the option tb_http_option_t option; // the status tb_http_status_t status; // the stream tb_stream_ref_t stream; // the sstream for sock tb_stream_ref_t sstream; // the cstream for chunked tb_stream_ref_t cstream; // the zstream for gzip/deflate tb_stream_ref_t zstream; // the head tb_hash_map_ref_t head; // is opened? tb_bool_t bopened; // the request data tb_string_t request; // the cookies tb_string_t cookies; // the request/response data for decreasing stack size tb_char_t data[8192]; }tb_http_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_bool_t tb_http_connect(tb_http_t* http) { // check tb_assert_and_check_return_val(http && http->stream, tb_false); // done tb_bool_t ok = tb_false; do { // the host is changed? tb_bool_t host_changed = tb_true; tb_char_t const* host_old = tb_null; tb_char_t const* host_new = tb_url_host(&http->option.url); tb_stream_ctrl(http->stream, TB_STREAM_CTRL_GET_HOST, &host_old); if (host_old && host_new && !tb_stricmp(host_old, host_new)) host_changed = tb_false; // trace tb_trace_d("connect: host: %s", host_changed? "changed" : "keep"); // set url and timeout if (!tb_stream_ctrl(http->stream, TB_STREAM_CTRL_SET_URL, tb_url_cstr(&http->option.url))) break; if (!tb_stream_ctrl(http->stream, TB_STREAM_CTRL_SET_TIMEOUT, http->option.timeout)) break; // reset keep-alive and close socket first before connecting anthor host if (host_changed && !tb_stream_ctrl(http->stream, TB_STREAM_CTRL_SOCK_KEEP_ALIVE, tb_false)) break; // dump option #if defined(__tb_debug__) && TB_TRACE_MODULE_DEBUG tb_http_option_dump(&http->option); #endif // trace tb_trace_d("connect: .."); // clear status tb_http_status_cler(&http->status, host_changed); // open stream if (!tb_stream_open(http->stream)) break; // ok ok = tb_true; } while (0); // failed? save state if (!ok) http->status.state = tb_stream_state(http->stream); // trace tb_trace_d("connect: %s, state: %s", ok? "ok" : "failed", tb_state_cstr(http->status.state)); // ok? return ok; } static tb_bool_t tb_http_request_post(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv) { // check tb_http_t* http = (tb_http_t*)priv; tb_assert_and_check_return_val(http && http->stream, tb_false); // trace tb_trace_d("post: percent: %llu%%, size: %lu, state: %s", size > 0? (offset * 100 / size) : 0, save, tb_state_cstr(state)); // done func if (http->option.post_func && !http->option.post_func(state, offset, size, save, rate, http->option.post_priv)) return tb_false; // ok? return tb_true; } static tb_bool_t tb_http_request(tb_http_t* http) { // check tb_assert_and_check_return_val(http && http->stream, tb_false); // done tb_bool_t ok = tb_false; tb_stream_ref_t pstream = tb_null; tb_hong_t post_size = 0; do { // clear line data tb_string_clear(&http->request); // init the head value tb_static_string_t value; if (!tb_static_string_init(&value, http->data, sizeof(http->data))) break; // init method tb_char_t const* method = tb_http_method_cstr(http->option.method); tb_assert_and_check_break(method); // init path tb_char_t const* path = tb_url_path(&http->option.url); tb_assert_and_check_break(path); // init args tb_char_t const* args = tb_url_args(&http->option.url); // init host tb_char_t const* host = tb_url_host(&http->option.url); tb_assert_and_check_break(host); tb_hash_map_insert(http->head, "Host", host); // init accept tb_hash_map_insert(http->head, "Accept", "*/*"); // init connection tb_hash_map_insert(http->head, "Connection", http->status.balived? "keep-alive" : "close"); // init cookies tb_bool_t cookie = tb_false; if (http->option.cookies) { // set cookie if (tb_cookies_get(http->option.cookies, host, path, tb_url_ssl(&http->option.url), &http->cookies)) { tb_hash_map_insert(http->head, "Cookie", tb_string_cstr(&http->cookies)); cookie = tb_true; } } // no cookie? remove it if (!cookie) tb_hash_map_remove(http->head, "Cookie"); // init range if (http->option.range.bof && http->option.range.eof >= http->option.range.bof) tb_static_string_cstrfcpy(&value, "bytes=%llu-%llu", http->option.range.bof, http->option.range.eof); else if (http->option.range.bof && !http->option.range.eof) tb_static_string_cstrfcpy(&value, "bytes=%llu-", http->option.range.bof); else if (!http->option.range.bof && http->option.range.eof) tb_static_string_cstrfcpy(&value, "bytes=0-%llu", http->option.range.eof); else if (http->option.range.bof > http->option.range.eof) { http->status.state = TB_STATE_HTTP_RANGE_INVALID; break; } // update range if (tb_static_string_size(&value)) tb_hash_map_insert(http->head, "Range", tb_static_string_cstr(&value)); // remove range else tb_hash_map_remove(http->head, "Range"); // init post if (http->option.method == TB_HTTP_METHOD_POST) { // done tb_bool_t post_ok = tb_false; do { // init pstream tb_char_t const* url = tb_url_cstr(&http->option.post_url); if (http->option.post_data && http->option.post_size) pstream = tb_stream_init_from_data(http->option.post_data, http->option.post_size); else if (url) pstream = tb_stream_init_from_url(url); tb_assert_and_check_break(pstream); // open pstream if (!tb_stream_open(pstream)) break; // the post size post_size = tb_stream_size(pstream); tb_assert_and_check_break(post_size >= 0); // append post size tb_static_string_cstrfcpy(&value, "%lld", post_size); tb_hash_map_insert(http->head, "Content-Length", tb_static_string_cstr(&value)); // ok post_ok = tb_true; } while (0); // init post failed? if (!post_ok) { http->status.state = TB_STATE_HTTP_POST_FAILED; break; } } // remove post else tb_hash_map_remove(http->head, "Content-Length"); // replace the custom head tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&http->option.head_data); tb_char_t const* head_tail = head_data + tb_buffer_size(&http->option.head_data); while (head_data < head_tail) { // the name and data tb_char_t const* name = head_data; tb_char_t const* data = head_data + tb_strlen(name) + 1; tb_check_break(data < head_tail); // replace it tb_hash_map_insert(http->head, name, data); // next head_data = data + tb_strlen(data) + 1; } // exit the head value tb_static_string_exit(&value); // check head tb_assert_and_check_break(tb_hash_map_size(http->head)); // append method tb_string_cstrcat(&http->request, method); // append ' ' tb_string_chrcat(&http->request, ' '); // encode path tb_url_encode2(path, tb_strlen(path), http->data, sizeof(http->data) - 1); path = http->data; // append path tb_string_cstrcat(&http->request, path); // append args if exists if (args) { // append '?' tb_string_chrcat(&http->request, '?'); // encode args tb_url_encode2(args, tb_strlen(args), http->data, sizeof(http->data) - 1); args = http->data; // append args tb_string_cstrcat(&http->request, args); } // append ' ' tb_string_chrcat(&http->request, ' '); // append version, HTTP/1.1 tb_string_cstrfcat(&http->request, "HTTP/1.%1u\r\n", http->status.balived? http->status.version : http->option.version); // append key: value tb_for_all (tb_hash_map_item_ref_t, item, http->head) { if (item && item->name && item->data) tb_string_cstrfcat(&http->request, "%s: %s\r\n", (tb_char_t const*)item->name, (tb_char_t const*)item->data); } // append end tb_string_cstrcat(&http->request, "\r\n"); // the request data and size tb_char_t const* request_data = tb_string_cstr(&http->request); tb_size_t request_size = tb_string_size(&http->request); tb_assert_and_check_break(request_data && request_size); // trace tb_trace_d("request[%lu]:\n%s", request_size, request_data); // writ request if (!tb_stream_bwrit(http->stream, (tb_byte_t const*)request_data, request_size)) break; // writ post if (http->option.method == TB_HTTP_METHOD_POST) { // post stream if (tb_transfer(pstream, http->stream, http->option.post_lrate, tb_http_request_post, http) != post_size) { http->status.state = TB_STATE_HTTP_POST_FAILED; break; } } // sync request if (!tb_stream_sync(http->stream, tb_false)) break; // ok ok = tb_true; } while (0); // failed? if (!ok && !http->status.state) http->status.state = TB_STATE_HTTP_REQUEST_FAILED; // exit pstream if (pstream) tb_stream_exit(pstream); pstream = tb_null; // ok? return ok; } /* * HTTP/1.1 206 Partial Content * Date: Fri, 23 Apr 2010 05:25:45 GMT * Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4.5 with Suhosin-Patch * Last-Modified: Mon, 08 Mar 2010 09:58:09 GMT * ETag: "6cc014-8f47f-481471a322e40" * Accept-Ranges: bytes * Content-Length: 586879 * Content-Range: bytes 0-586878/586879 * Connection: close * Content-Type: application/x-shockwave-flash */ static tb_bool_t tb_http_response_done(tb_http_t* http, tb_char_t const* line, tb_size_t indx) { // check tb_assert_and_check_return_val(http && http->sstream && line, tb_false); // the first line? tb_char_t const* p = line; if (!indx) { // check http response if (tb_strnicmp(p, "HTTP/1.", 7)) { // failed tb_assert(0); return tb_false; } // seek to the http version p += 7; tb_assert_and_check_return_val(*p, tb_false); // parse version tb_assert_and_check_return_val((*p - '0') < 2, tb_false); http->status.version = *p - '0'; // seek to the http code p++; while (tb_isspace(*p)) p++; // parse code tb_assert_and_check_return_val(*p && tb_isdigit(*p), tb_false); http->status.code = tb_stou32(p); // save state if (http->status.code == 200 || http->status.code == 206) http->status.state = TB_STATE_OK; else if (http->status.code == 204) http->status.state = TB_STATE_HTTP_RESPONSE_204; else if (http->status.code >= 300 && http->status.code <= 307) http->status.state = TB_STATE_HTTP_RESPONSE_300 + (http->status.code - 300); else if (http->status.code >= 400 && http->status.code <= 416) http->status.state = TB_STATE_HTTP_RESPONSE_400 + (http->status.code - 400); else if (http->status.code >= 500 && http->status.code <= 507) http->status.state = TB_STATE_HTTP_RESPONSE_500 + (http->status.code - 500); else http->status.state = TB_STATE_HTTP_RESPONSE_UNK; // check state code: 4xx & 5xx if (http->status.code >= 400 && http->status.code < 600) return tb_false; } // key: value? else { // seek to value while (*p && *p != ':') p++; tb_assert_and_check_return_val(*p, tb_false); p++; while (*p && tb_isspace(*p)) p++; // no value tb_check_return_val(*p, tb_true); // parse content size if (!tb_strnicmp(line, "Content-Length", 14)) { http->status.content_size = tb_stou64(p); if (http->status.document_size < 0) http->status.document_size = http->status.content_size; } // parse content range: "bytes $from-$to/$document_size" else if (!tb_strnicmp(line, "Content-Range", 13)) { tb_hize_t from = 0; tb_hize_t to = 0; tb_hize_t document_size = 0; if (!tb_strncmp(p, "bytes ", 6)) { p += 6; from = tb_stou64(p); while (*p && *p != '-') p++; if (*p && *p++ == '-') to = tb_stou64(p); while (*p && *p != '/') p++; if (*p && *p++ == '/') document_size = tb_stou64(p); } // no stream, be able to seek http->status.bseeked = 1; http->status.document_size = document_size; if (http->status.content_size < 0) { if (from && to > from) http->status.content_size = to - from; else if (!from && to) http->status.content_size = to; else if (from && !to && document_size > from) http->status.content_size = document_size - from; else http->status.content_size = document_size; } } // parse accept-ranges: "bytes " else if (!tb_strnicmp(line, "Accept-Ranges", 13)) { // no stream, be able to seek http->status.bseeked = 1; } // parse content type else if (!tb_strnicmp(line, "Content-Type", 12)) { tb_string_cstrcpy(&http->status.content_type, p); tb_assert_and_check_return_val(tb_string_size(&http->status.content_type), tb_false); } // parse transfer encoding else if (!tb_strnicmp(line, "Transfer-Encoding", 17)) { if (!tb_stricmp(p, "chunked")) http->status.bchunked = 1; } // parse content encoding else if (!tb_strnicmp(line, "Content-Encoding", 16)) { if (!tb_stricmp(p, "gzip")) http->status.bgzip = 1; else if (!tb_stricmp(p, "deflate")) http->status.bdeflate = 1; } // parse location else if (!tb_strnicmp(line, "Location", 8)) { // redirect? check code: 301 - 307 tb_assert_and_check_return_val(http->status.code > 300 && http->status.code < 308, tb_false); // save location tb_string_cstrcpy(&http->status.location, p); } // parse connection else if (!tb_strnicmp(line, "Connection", 10)) { // keep alive? http->status.balived = !tb_stricmp(p, "close")? 0 : 1; // ctrl stream for sock if (!tb_stream_ctrl(http->sstream, TB_STREAM_CTRL_SOCK_KEEP_ALIVE, http->status.balived? tb_true : tb_false)) return tb_false; } // parse cookies else if (http->option.cookies && !tb_strnicmp(line, "Set-Cookie", 10)) { // the host tb_char_t const* host = tb_null; tb_http_ctrl((tb_http_ref_t)http, TB_HTTP_OPTION_GET_HOST, &host); // the path tb_char_t const* path = tb_null; tb_http_ctrl((tb_http_ref_t)http, TB_HTTP_OPTION_GET_PATH, &path); // is ssl? tb_bool_t bssl = tb_false; tb_http_ctrl((tb_http_ref_t)http, TB_HTTP_OPTION_GET_SSL, &bssl); // set cookies tb_cookies_set(http->option.cookies, host, path, bssl, p); } } // ok return tb_true; } static tb_bool_t tb_http_response(tb_http_t* http) { // check tb_assert_and_check_return_val(http && http->stream, tb_false); // done tb_bool_t ok = tb_false; do { // read line tb_long_t real = 0; tb_size_t indx = 0; while ((real = tb_stream_bread_line(http->stream, http->data, sizeof(http->data) - 1)) >= 0) { // trace tb_trace_d("response: %s", http->data); // do callback if (http->option.head_func && !http->option.head_func(http->data, http->option.head_priv)) break; // end? if (!real) { // switch to cstream if chunked if (http->status.bchunked) { // init cstream if (http->cstream) { if (!tb_stream_ctrl(http->cstream, TB_STREAM_CTRL_FLTR_SET_STREAM, http->stream)) break; } else http->cstream = tb_stream_init_filter_from_chunked(http->stream, tb_true); tb_assert_and_check_break(http->cstream); // open cstream, need not async if (!tb_stream_open(http->cstream)) break; // using cstream http->stream = http->cstream; // disable seek http->status.bseeked = 0; } // switch to zstream if gzip or deflate if (http->option.bunzip && (http->status.bgzip || http->status.bdeflate)) { #if defined(TB_CONFIG_PACKAGE_HAVE_ZLIB) && defined(TB_CONFIG_MODULE_HAVE_ZIP) // init zstream if (http->zstream) { if (!tb_stream_ctrl(http->zstream, TB_STREAM_CTRL_FLTR_SET_STREAM, http->stream)) break; } else http->zstream = tb_stream_init_filter_from_zip(http->stream, http->status.bgzip? TB_ZIP_ALGO_GZIP : TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE); tb_assert_and_check_break(http->zstream); // the filter tb_filter_ref_t filter = tb_null; if (!tb_stream_ctrl(http->zstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break; tb_assert_and_check_break(filter); // ctrl filter if (!tb_filter_ctrl(filter, TB_FILTER_CTRL_ZIP_SET_ALGO, http->status.bgzip? TB_ZIP_ALGO_GZIP : TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE)) break; // limit the filter input size if (http->status.content_size > 0) tb_filter_limit(filter, http->status.content_size); // open zstream, need not async if (!tb_stream_open(http->zstream)) break; // using zstream http->stream = http->zstream; // disable seek http->status.bseeked = 0; #else // trace tb_trace_w("gzip is not supported now! please enable it from config if you need it."); // not supported http->status.state = TB_STATE_HTTP_GZIP_NOT_SUPPORTED; break; #endif } // trace tb_trace_d("response: ok"); // dump status #if defined(__tb_debug__) && TB_TRACE_MODULE_DEBUG tb_http_status_dump(&http->status); #endif // ok ok = tb_true; break; } // done it if (!tb_http_response_done(http, http->data, indx++)) break; } } while (0); // ok? return ok; } static tb_bool_t tb_http_redirect(tb_http_t* http) { // check tb_assert_and_check_return_val(http && http->stream, tb_false); // done tb_size_t i = 0; tb_bool_t ok = tb_true; for (i = 0; i < http->option.redirect && tb_string_size(&http->status.location); i++) { // read the redirect content if (http->status.content_size > 0) { tb_byte_t data[TB_STREAM_BLOCK_MAXN]; tb_hize_t read = 0; tb_hize_t size = http->status.content_size; while (read < size) { // the need tb_size_t need = (tb_size_t)tb_min(size - read, (tb_hize_t)TB_STREAM_BLOCK_MAXN); // read it if (!tb_stream_bread(http->stream, data, need)) break; // save size read += need; } // check tb_assert_pass_and_check_break(read == size); } // close stream if (http->stream && !tb_stream_clos(http->stream)) break; // switch to sstream http->stream = http->sstream; // get location url tb_char_t const* location = tb_string_cstr(&http->status.location); tb_assert_and_check_break(location); // trace tb_trace_d("redirect: %s", location); // only path? tb_size_t protocol = tb_url_protocol_probe(location); if (protocol == TB_URL_PROTOCOL_FILE) tb_url_path_set(&http->option.url, location); // full http url? else if (protocol == TB_URL_PROTOCOL_HTTP) { // set url if (!tb_url_cstr_set(&http->option.url, location)) break; } else { // trace tb_trace_e("unsupported protocol for location %s", location); break; } // connect it if (!(ok = tb_http_connect(http))) break; // request it if (!(ok = tb_http_request(http))) break; // response it if (!(ok = tb_http_response(http))) break; } // ok? return ok && !tb_string_size(&http->status.location); } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_http_ref_t tb_http_init() { // done tb_bool_t ok = tb_false; tb_http_t* http = tb_null; do { // make http http = tb_malloc0_type(tb_http_t); tb_assert_and_check_break(http); // init stream http->stream = http->sstream = tb_stream_init_sock(); tb_assert_and_check_break(http->stream); // init head http->head = tb_hash_map_init(8, tb_element_str(tb_false), tb_element_str(tb_false)); tb_assert_and_check_break(http->head); // init request data if (!tb_string_init(&http->request)) break; // init cookies data if (!tb_string_init(&http->cookies)) break; // init option if (!tb_http_option_init(&http->option)) break; // init status if (!tb_http_status_init(&http->status)) break; // ok ok = tb_true; } while (0); // failed? if (!ok) { if (http) tb_http_exit((tb_http_ref_t)http); http = tb_null; } // ok? return (tb_http_ref_t)http; } tb_void_t tb_http_kill(tb_http_ref_t self) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return(http); // kill stream if (http->stream) tb_stream_kill(http->stream); } tb_void_t tb_http_exit(tb_http_ref_t self) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return(http); // close it tb_http_close(self); // exit zstream if (http->zstream) tb_stream_exit(http->zstream); http->zstream = tb_null; // exit cstream if (http->cstream) tb_stream_exit(http->cstream); http->cstream = tb_null; // exit sstream if (http->sstream) tb_stream_exit(http->sstream); http->sstream = tb_null; // exit stream http->stream = tb_null; // exit status tb_http_status_exit(&http->status); // exit option tb_http_option_exit(&http->option); // exit cookies data tb_string_exit(&http->cookies); // exit request data tb_string_exit(&http->request); // exit head if (http->head) tb_hash_map_exit(http->head); http->head = tb_null; // free it tb_free(http); } tb_long_t tb_http_wait(tb_http_ref_t self, tb_size_t events, tb_long_t timeout) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http && http->stream, -1); // opened? tb_assert_and_check_return_val(http->bopened, -1); // wait it tb_long_t wait = tb_stream_wait(http->stream, events, timeout); // failed? save state if (wait < 0 && !http->status.state) http->status.state = tb_stream_state(http->stream); // ok? return wait; } tb_bool_t tb_http_open(tb_http_ref_t self) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http, tb_false); // opened? tb_assert_and_check_return_val(!http->bopened, tb_false); // done tb_bool_t ok = tb_false; do { // connect it if (!tb_http_connect(http)) break; // request it if (!tb_http_request(http)) break; // response it if (!tb_http_response(http)) break; // redirect it if (!tb_http_redirect(http)) break; // ok ok = tb_true; } while (0); // failed? close it if (!ok) { // close stream if (http->stream) tb_stream_clos(http->stream); // switch to sstream http->stream = http->sstream; } // is opened? http->bopened = ok; // ok? return ok; } tb_bool_t tb_http_close(tb_http_ref_t self) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http, tb_false); // opened? tb_check_return_val(http->bopened, tb_true); // close stream if (http->stream && !tb_stream_clos(http->stream)) return tb_false; // switch to sstream http->stream = http->sstream; // clear opened http->bopened = tb_false; // ok return tb_true; } tb_bool_t tb_http_seek(tb_http_ref_t self, tb_hize_t offset) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http, tb_false); // opened? tb_assert_and_check_return_val(http->bopened, tb_false); // seeked? tb_check_return_val(http->status.bseeked, tb_false); // done tb_bool_t ok = tb_false; do { // close stream if (http->stream && !tb_stream_clos(http->stream)) break; // switch to sstream http->stream = http->sstream; // trace tb_trace_d("seek: %llu", offset); // set range http->option.range.bof = offset; http->option.range.eof = http->status.document_size > 0? http->status.document_size - 1 : 0; // connect it if (!tb_http_connect(http)) break; // request it if (!tb_http_request(http)) break; // response it if (!tb_http_response(http)) break; // ok ok = tb_true; } while (0); // ok? return ok; } tb_long_t tb_http_read(tb_http_ref_t self, tb_byte_t* data, tb_size_t size) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http && http->stream, -1); // opened? tb_assert_and_check_return_val(http->bopened, -1); // read return tb_stream_read(http->stream, data, size); } tb_bool_t tb_http_bread(tb_http_ref_t self, tb_byte_t* data, tb_size_t size) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http && http->stream, tb_false); // opened? tb_assert_and_check_return_val(http->bopened, tb_false); // read tb_size_t read = 0; while (read < size) { // read data tb_long_t real = tb_stream_read(http->stream, data + read, size - read); // update size if (real > 0) read += real; // no data? else if (!real) { // wait tb_long_t e = tb_http_wait(self, TB_SOCKET_EVENT_RECV, http->option.timeout); tb_assert_and_check_break(e >= 0); // timeout? tb_check_break(e); // has read? tb_assert_and_check_break(e & TB_SOCKET_EVENT_RECV); } else break; } // ok? return read == size? tb_true : tb_false; } tb_bool_t tb_http_ctrl(tb_http_ref_t self, tb_size_t option, ...) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http && option, tb_false); // check if (TB_HTTP_OPTION_CODE_IS_SET(option) && http->bopened) { // abort tb_assert(0); return tb_false; } // init args tb_va_list_t args; tb_va_start(args, option); // done tb_bool_t ok = tb_http_option_ctrl(&http->option, option, args); // exit args tb_va_end(args); // ok? return ok; } tb_http_status_t const* tb_http_status(tb_http_ref_t self) { // check tb_http_t* http = (tb_http_t*)self; tb_assert_and_check_return_val(http, tb_null); // the status return &http->status; } tbox-1.6.7/src/tbox/network/http.h 0000664 0000000 0000000 00000031743 14142237372 0017102 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file http.h * @ingroup network * */ #ifndef TB_NETWORK_HTTP_H #define TB_NETWORK_HTTP_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "cookies.h" #include "url.h" #include "../string/string.h" #include "../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the http option code: get #define TB_HTTP_OPTION_CODE_GET(x) ((x) + 1) /// the http option code: set #define TB_HTTP_OPTION_CODE_SET(x) (0xff00 | ((x) + 1)) /// the http option code is setter? #define TB_HTTP_OPTION_CODE_IS_SET(x) ((x) & 0xff00) /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the http method enum typedef enum __tb_http_method_e { TB_HTTP_METHOD_GET = 0 , TB_HTTP_METHOD_POST = 1 , TB_HTTP_METHOD_HEAD = 2 , TB_HTTP_METHOD_PUT = 3 , TB_HTTP_METHOD_OPTIONS = 4 , TB_HTTP_METHOD_DELETE = 5 , TB_HTTP_METHOD_TRACE = 6 , TB_HTTP_METHOD_CONNECT = 7 }tb_http_method_e; /// the http code enum typedef enum __tb_http_code_e { TB_HTTP_CODE_CONTINUE = 100 , TB_HTTP_CODE_SWITCHING_PROTOCOLS = 101 , TB_HTTP_CODE_PROCESSING = 102 , TB_HTTP_CODE_OK = 200 , TB_HTTP_CODE_CREATED = 201 , TB_HTTP_CODE_ACCEPTED = 202 , TB_HTTP_CODE_NON_AUTHORITATIVE_INFORMATION = 203 , TB_HTTP_CODE_NO_CONTENT = 204 , TB_HTTP_CODE_RESET_CONTENT = 205 , TB_HTTP_CODE_PARTIAL_CONTENT = 206 , TB_HTTP_CODE_MULTI_STATUS = 207 , TB_HTTP_CODE_MULTIPLE_CHOICES = 300 , TB_HTTP_CODE_MOVED_PERMANENTLY = 301 , TB_HTTP_CODE_MOVED_TEMPORARILY = 302 , TB_HTTP_CODE_SEE_OTHER = 303 , TB_HTTP_CODE_NOT_MODIFIED = 304 , TB_HTTP_CODE_USE_PROXY = 305 , TB_HTTP_CODE_SWITCH_PROXY = 306 , TB_HTTP_CODE_TEMPORARY_REDIRECT = 307 , TB_HTTP_CODE_BAD_REQUEST = 400 , TB_HTTP_CODE_UNAUTHORIZED = 401 , TB_HTTP_CODE_FORBIDDEN = 403 , TB_HTTP_CODE_NOT_FOUND = 404 , TB_HTTP_CODE_METHOD_NOT_ALLOWED = 405 , TB_HTTP_CODE_NOT_ACCEPTABLE = 406 , TB_HTTP_CODE_REQUEST_TIMEOUT = 408 , TB_HTTP_CODE_CONFLICT = 409 , TB_HTTP_CODE_GONE = 410 , TB_HTTP_CODE_LENGTH_REQUIRED = 411 , TB_HTTP_CODE_PRECONDITION_FAILED = 412 , TB_HTTP_CODE_REQUEST_ENTITY_TOO_LONG = 413 , TB_HTTP_CODE_REQUEST_URI_TOO_LONG = 414 , TB_HTTP_CODE_UNSUPPORTED_MEDIA_TYPE = 415 , TB_HTTP_CODE_RANGE_NOT_SATISFIABLE = 416 , TB_HTTP_CODE_EXPECTATION_FAILED = 417 , TB_HTTP_CODE_UNPROCESSABLE_ENTITY = 422 , TB_HTTP_CODE_LOCKED = 423 , TB_HTTP_CODE_FAILED_DEPENDENCY = 424 , TB_HTTP_CODE_UNORDERED_COLLECTION = 425 , TB_HTTP_CODE_UPGRADE_REQUIRED = 426 , TB_HTTP_CODE_RETRY_WITH = 449 , TB_HTTP_CODE_INTERNAL_SERVER_ERROR = 500 , TB_HTTP_CODE_NOT_IMPLEMENTED = 501 , TB_HTTP_CODE_BAD_GATEWAY = 502 , TB_HTTP_CODE_SERVICE_UNAVAILABLE = 503 , TB_HTTP_CODE_GATEWAY_TIMEOUT = 504 , TB_HTTP_CODE_INSUFFICIENT_STORAGE = 507 , TB_HTTP_CODE_LOOP_DETECTED = 508 , TB_HTTP_CODE_NOT_EXTENDED = 510 }tb_http_code_e; /// the http option enum typedef enum __tb_http_option_e { TB_HTTP_OPTION_NONE = 0 , TB_HTTP_OPTION_GET_SSL = TB_HTTP_OPTION_CODE_GET(1) , TB_HTTP_OPTION_GET_URL = TB_HTTP_OPTION_CODE_GET(2) , TB_HTTP_OPTION_GET_HOST = TB_HTTP_OPTION_CODE_GET(3) , TB_HTTP_OPTION_GET_PORT = TB_HTTP_OPTION_CODE_GET(4) , TB_HTTP_OPTION_GET_PATH = TB_HTTP_OPTION_CODE_GET(5) , TB_HTTP_OPTION_GET_HEAD = TB_HTTP_OPTION_CODE_GET(6) , TB_HTTP_OPTION_GET_RANGE = TB_HTTP_OPTION_CODE_GET(7) , TB_HTTP_OPTION_GET_METHOD = TB_HTTP_OPTION_CODE_GET(8) , TB_HTTP_OPTION_GET_VERSION = TB_HTTP_OPTION_CODE_GET(9) , TB_HTTP_OPTION_GET_TIMEOUT = TB_HTTP_OPTION_CODE_GET(10) , TB_HTTP_OPTION_GET_COOKIES = TB_HTTP_OPTION_CODE_GET(11) , TB_HTTP_OPTION_GET_REDIRECT = TB_HTTP_OPTION_CODE_GET(12) , TB_HTTP_OPTION_GET_HEAD_FUNC = TB_HTTP_OPTION_CODE_GET(13) , TB_HTTP_OPTION_GET_HEAD_PRIV = TB_HTTP_OPTION_CODE_GET(14) , TB_HTTP_OPTION_GET_AUTO_UNZIP = TB_HTTP_OPTION_CODE_GET(15) , TB_HTTP_OPTION_GET_POST_URL = TB_HTTP_OPTION_CODE_GET(16) , TB_HTTP_OPTION_GET_POST_DATA = TB_HTTP_OPTION_CODE_GET(17) , TB_HTTP_OPTION_GET_POST_FUNC = TB_HTTP_OPTION_CODE_GET(18) , TB_HTTP_OPTION_GET_POST_PRIV = TB_HTTP_OPTION_CODE_GET(19) , TB_HTTP_OPTION_GET_POST_LRATE = TB_HTTP_OPTION_CODE_GET(20) , TB_HTTP_OPTION_SET_SSL = TB_HTTP_OPTION_CODE_SET(1) , TB_HTTP_OPTION_SET_URL = TB_HTTP_OPTION_CODE_SET(2) , TB_HTTP_OPTION_SET_HOST = TB_HTTP_OPTION_CODE_SET(3) , TB_HTTP_OPTION_SET_PORT = TB_HTTP_OPTION_CODE_SET(4) , TB_HTTP_OPTION_SET_PATH = TB_HTTP_OPTION_CODE_SET(5) , TB_HTTP_OPTION_SET_HEAD = TB_HTTP_OPTION_CODE_SET(6) , TB_HTTP_OPTION_SET_RANGE = TB_HTTP_OPTION_CODE_SET(7) , TB_HTTP_OPTION_SET_METHOD = TB_HTTP_OPTION_CODE_SET(8) , TB_HTTP_OPTION_SET_VERSION = TB_HTTP_OPTION_CODE_SET(9) , TB_HTTP_OPTION_SET_TIMEOUT = TB_HTTP_OPTION_CODE_SET(10) , TB_HTTP_OPTION_SET_COOKIES = TB_HTTP_OPTION_CODE_SET(11) , TB_HTTP_OPTION_SET_REDIRECT = TB_HTTP_OPTION_CODE_SET(12) , TB_HTTP_OPTION_SET_HEAD_FUNC = TB_HTTP_OPTION_CODE_SET(13) , TB_HTTP_OPTION_SET_HEAD_PRIV = TB_HTTP_OPTION_CODE_SET(14) , TB_HTTP_OPTION_SET_AUTO_UNZIP = TB_HTTP_OPTION_CODE_SET(15) , TB_HTTP_OPTION_SET_POST_URL = TB_HTTP_OPTION_CODE_SET(16) , TB_HTTP_OPTION_SET_POST_DATA = TB_HTTP_OPTION_CODE_SET(17) , TB_HTTP_OPTION_SET_POST_FUNC = TB_HTTP_OPTION_CODE_SET(18) , TB_HTTP_OPTION_SET_POST_PRIV = TB_HTTP_OPTION_CODE_SET(19) , TB_HTTP_OPTION_SET_POST_LRATE = TB_HTTP_OPTION_CODE_SET(20) }tb_http_option_e; /// the http range type typedef struct __tb_http_range_t { /// the begin offset tb_hize_t bof; /// the end offset tb_hize_t eof; }tb_http_range_t; /// the http ref type typedef __tb_typeref__(http); /*! the http head func type * * @param line the http head line * @param priv the func private data * * @return tb_true: ok and continue it if need, tb_false: break it */ typedef tb_bool_t (*tb_http_head_func_t)(tb_char_t const* line, tb_cpointer_t priv); /*! the http post func type * * @param offset the istream offset * @param size the istream size, no size: -1 * @param save the saved size * @param rate the current rate, bytes/s * @param priv the func private data * * @return tb_true: ok and continue it if need, tb_false: break it */ typedef tb_bool_t (*tb_http_post_func_t)(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv); /// the http option type typedef struct __tb_http_option_t { /// the method tb_uint16_t method : 4; /// auto unzip for gzip encoding? tb_uint16_t bunzip : 1; /// the http version, 0: HTTP/1.0, 1: HTTP/1.1 tb_uint16_t version : 1; /// the redirect maxn tb_uint16_t redirect : 10; /// the url tb_url_t url; /// timeout: ms tb_long_t timeout; /// range tb_http_range_t range; /// the cookies tb_cookies_ref_t cookies; /// the priv data tb_pointer_t head_priv; /// the head func tb_http_head_func_t head_func; /// the head data tb_buffer_t head_data; /// the post url tb_url_t post_url; /// the post data tb_byte_t const* post_data; /// the post size tb_size_t post_size; /// the post func tb_http_post_func_t post_func; /// the post data tb_cpointer_t post_priv; /// the post limit rate tb_size_t post_lrate; }tb_http_option_t; /// the http status type typedef struct __tb_http_status_t { /// the http code tb_uint16_t code : 10; /// the http version tb_uint16_t version : 1; /// keep alive? tb_uint16_t balived : 1; /// be able to seek? tb_uint16_t bseeked : 1; /// is chunked? tb_uint16_t bchunked : 1; /// is gzip? tb_uint16_t bgzip : 1; /// is deflate? tb_uint16_t bdeflate : 1; /// the state tb_size_t state; /// the document size tb_hong_t document_size; /// the current content size, maybe in range tb_hong_t content_size; /// the content type tb_string_t content_type; /// the location tb_string_t location; }tb_http_status_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init http * * return the http */ tb_http_ref_t tb_http_init(tb_noarg_t); /*! exit http * * @param http the http */ tb_void_t tb_http_exit(tb_http_ref_t http); /*! kill http * * @param http the http */ tb_void_t tb_http_kill(tb_http_ref_t http); /*! wait the http * * blocking wait the single event object, so need not aiop * return the event type if ok, otherwise return 0 for timeout * * @param http the http * @param events the events * @param timeout the timeout value, return immediately if 0, infinity if -1 * * @return the event type, return 0 if timeout, return -1 if error */ tb_long_t tb_http_wait(tb_http_ref_t http, tb_size_t events, tb_long_t timeout); /*! open the http * * @param http the http * * @return tb_true or tb_false */ tb_bool_t tb_http_open(tb_http_ref_t http); /*! close http * * @param http the http * * @return tb_true or tb_false */ tb_bool_t tb_http_close(tb_http_ref_t http); /*! seek http * * @param http the http * @param offset the offset * * @return tb_true or tb_false */ tb_bool_t tb_http_seek(tb_http_ref_t http, tb_hize_t offset); /*! read data, non-blocking * * @param http the http * @param data the data * @param size the size * * @return ok: real size, continue: 0, fail: -1 */ tb_long_t tb_http_read(tb_http_ref_t http, tb_byte_t* data, tb_size_t size); /*! read data, blocking * * @param http the http * @param data the data * @param size the size * * @return tb_true or tb_false */ tb_bool_t tb_http_bread(tb_http_ref_t http, tb_byte_t* data, tb_size_t size); /*! ctrl the http option * * @param http the http * @param option the ctrl option * * @return tb_true or tb_false */ tb_bool_t tb_http_ctrl(tb_http_ref_t http, tb_size_t option, ...); /*! the http status * * @param http the http * * @return the http status */ tb_http_status_t const* tb_http_status(tb_http_ref_t http); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/hwaddr.c 0000664 0000000 0000000 00000007721 14142237372 0017366 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file hwaddr.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "hwaddr" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "hwaddr.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../string/string.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_void_t tb_hwaddr_clear(tb_hwaddr_ref_t hwaddr) { // check tb_assert_and_check_return(hwaddr); // clear it tb_memset(hwaddr->u8, 0, sizeof(hwaddr->u8)); } tb_void_t tb_hwaddr_copy(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t copied) { // check tb_assert_and_check_return(hwaddr && copied); // copy it hwaddr->u8[0] = copied->u8[0]; hwaddr->u8[1] = copied->u8[1]; hwaddr->u8[2] = copied->u8[2]; hwaddr->u8[3] = copied->u8[3]; hwaddr->u8[4] = copied->u8[4]; hwaddr->u8[5] = copied->u8[5]; } tb_bool_t tb_hwaddr_is_equal(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t other) { // check tb_assert_and_check_return_val(hwaddr && other, tb_false); // is equal? return !tb_memcmp(hwaddr->u8, other->u8, sizeof(hwaddr->u8)); } tb_char_t const* tb_hwaddr_cstr(tb_hwaddr_ref_t hwaddr, tb_char_t* data, tb_size_t maxn) { // check tb_assert_and_check_return_val(hwaddr && data && maxn >= TB_HWADDR_CSTR_MAXN, tb_null); // make it tb_long_t size = tb_snprintf(data, maxn - 1, "%02x:%02x:%02x:%02x:%02x:%02x", hwaddr->u8[0], hwaddr->u8[1], hwaddr->u8[2], hwaddr->u8[3], hwaddr->u8[4], hwaddr->u8[5]); if (size >= 0) data[size] = '\0'; // ok return data; } tb_bool_t tb_hwaddr_cstr_set(tb_hwaddr_ref_t hwaddr, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(cstr, tb_false); // done tb_uint32_t v = 0; tb_char_t c = '\0'; tb_size_t i = 0; tb_char_t const* p = cstr; tb_bool_t ok = tb_true; tb_hwaddr_t temp; do { // the character c = *p++; // digit? if (tb_isdigit16(c) && v <= 0xff) { // update value if (tb_isdigit10(c)) v = (v << 4) + (c - '0'); else if (c > ('a' - 1) && c < ('f' + 1)) v = (v << 4) + (c - 'a') + 10; else if (c > ('A' - 1) && c < ('F' + 1)) v = (v << 4) + (c - 'A') + 10; else { // abort tb_assert(0); // failed ok = tb_false; break; } } // ':' or "-" or '\0'? else if (i < 6 && (c == ':' || c == '-' || !c) && v <= 0xff) { // save value temp.u8[i++] = v; // clear value v = 0; } // failed? else { ok = tb_false; break; } } while (c); // failed if (i != 6) ok = tb_false; // save it if ok if (ok && hwaddr) *hwaddr = temp; // trace // tb_assertf(ok, "invalid hwaddr: %s", cstr); // ok? return ok; } tbox-1.6.7/src/tbox/network/hwaddr.h 0000664 0000000 0000000 00000005345 14142237372 0017373 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file hwaddr.h * @ingroup network * */ #ifndef TB_NETWORK_HWADDR_H #define TB_NETWORK_HWADDR_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the hwaddr string data maxn #define TB_HWADDR_CSTR_MAXN (18) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the hardware address type * * mac: xx:xx:xx:xx:xx:xx */ typedef struct __tb_hwaddr_t { /// u8 tb_byte_t u8[6]; }tb_hwaddr_t, *tb_hwaddr_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! clear the hwaddr * * @param hwaddr the hwaddr */ tb_void_t tb_hwaddr_clear(tb_hwaddr_ref_t hwaddr); /*! copy address, faster than *hwaddr = *other * * @param hwaddr the address * @param copied the copied address */ tb_void_t tb_hwaddr_copy(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t copied); /*! is equal? * * @param hwaddr the hwaddr * @param other the other hwaddr * * @return tb_true or tb_false */ tb_bool_t tb_hwaddr_is_equal(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t other); /*! get the hwaddr string * * @param hwaddr the hwaddr * @param data the hwaddr data * @param maxn the data maxn * * @return the hwaddr address */ tb_char_t const* tb_hwaddr_cstr(tb_hwaddr_ref_t hwaddr, tb_char_t* data, tb_size_t maxn); /*! set the hwaddr from string * * @param hwaddr the hwaddr * @param cstr the hwaddr string * * @return tb_true or tb_false */ tb_bool_t tb_hwaddr_cstr_set(tb_hwaddr_ref_t hwaddr, tb_char_t const* cstr); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/impl/ 0000775 0000000 0000000 00000000000 14142237372 0016703 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/network/impl/http/ 0000775 0000000 0000000 00000000000 14142237372 0017662 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/network/impl/http/date.c 0000664 0000000 0000000 00000013010 14142237372 0020736 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file date.c */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "http_date" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "date.h" #include "../../../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_time_t tb_http_date_from_cstr(tb_char_t const* cstr, tb_size_t size) { // check tb_assert_and_check_return_val(cstr && size, 0); // done tb_tm_t tm = {0}; tb_time_t date = 0; tb_char_t const* p = cstr; tb_char_t const* e = cstr + size; do { // skip space while (p < e && tb_isspace(*p)) p++; // ignore #if 0 // parse week if ((p + 6 < e && !tb_strnicmp(p, "Monday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Mon", 3))) tm.week = 1; else if ((p + 7 < e && !tb_strnicmp(p, "Tuesday", 7)) || (p + 3 < e && !tb_strnicmp(p, "Tue", 3))) tm.week = 2; else if ((p + 9 < e && !tb_strnicmp(p, "Wednesday", 9)) || (p + 3 < e && !tb_strnicmp(p, "Wed", 3))) tm.week = 3; else if ((p + 8 < e && !tb_strnicmp(p, "Thursday", 8)) || (p + 3 < e && !tb_strnicmp(p, "Thu", 3))) tm.week = 4; else if ((p + 6 < e && !tb_strnicmp(p, "Friday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Fri", 3))) tm.week = 5; else if ((p + 8 < e && !tb_strnicmp(p, "Saturday", 8)) || (p + 3 < e && !tb_strnicmp(p, "Sat", 3))) tm.week = 6; else if ((p + 6 < e && !tb_strnicmp(p, "Sunday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Sun", 3))) tm.week = 7; #endif // skip week while (p < e && *p != ',' && !tb_isspace(*p)) p++; if (p < e && (*p == ',' || tb_isspace(*p))) p++; // skip space while (p < e && tb_isspace(*p)) p++; // is day? tb_bool_t year_suffix = tb_true; if (p < e && tb_isdigit(*p)) { /* prefix year * * .e.g * year_suffix == false: Sun, 06-Nov-1994 08:49:37 * year_suffix == true: Sun Nov 6 08:49:37 1994 */ year_suffix = tb_false; // parse day tm.mday = tb_s10tou32(p); // skip day while (p < e && *p != '-' && !tb_isspace(*p)) p++; if (p < e && (*p == '-' || tb_isspace(*p))) p++; } // parse month if (p + 3 < e && !tb_strnicmp(p, "Jan", 3)) tm.month = 1; else if (p + 3 < e && !tb_strnicmp(p, "Feb", 3)) tm.month = 2; else if (p + 3 < e && !tb_strnicmp(p, "Mar", 3)) tm.month = 3; else if (p + 3 < e && !tb_strnicmp(p, "Apr", 3)) tm.month = 4; else if (p + 3 < e && !tb_strnicmp(p, "May", 3)) tm.month = 5; else if (p + 3 < e && !tb_strnicmp(p, "Jun", 3)) tm.month = 6; else if (p + 3 < e && !tb_strnicmp(p, "Jul", 3)) tm.month = 7; else if (p + 3 < e && !tb_strnicmp(p, "Aug", 3)) tm.month = 8; else if (p + 3 < e && !tb_strnicmp(p, "Sep", 3)) tm.month = 9; else if (p + 3 < e && !tb_strnicmp(p, "Oct", 3)) tm.month = 10; else if (p + 3 < e && !tb_strnicmp(p, "Nov", 3)) tm.month = 11; else if (p + 3 < e && !tb_strnicmp(p, "Dec", 3)) tm.month = 12; // skip month while (p < e && *p != '-' && !tb_isspace(*p)) p++; if (p < e && (*p == '-' || tb_isspace(*p))) p++; // year suffix? if (year_suffix) { // parse day tm.mday = tb_s10tou32(p); } else { // parse year tm.year = tb_s10tou32(p); if (tm.year < 100) tm.year += 2000; } // skip year or day while (p < e && !tb_isspace(*p)) p++; while (p < e && tb_isspace(*p)) p++; // parse hour tm.hour = tb_s10tou32(p); // skip hour while (p < e && *p != ':') p++; if (p < e && *p == ':') p++; // parse minute tm.minute = tb_s10tou32(p); // skip minute while (p < e && *p != ':') p++; if (p < e && *p == ':') p++; // parse second tm.second = tb_s10tou32(p); // year suffix? if (year_suffix) { // skip time while (p < e && !tb_isspace(*p)) p++; while (p < e && tb_isspace(*p)) p++; // parse year tm.year = tb_s10tou32(p); if (tm.year < 100) tm.year += 1900; } // make date date = tb_gmmktime(&tm); } while (0); // ok? return date; } tbox-1.6.7/src/tbox/network/impl/http/date.h 0000664 0000000 0000000 00000003512 14142237372 0020751 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file date.h */ #ifndef TB_NETWORK_IMPL_HTTP_DATE_H #define TB_NETWORK_IMPL_HTTP_DATE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* get the http date from the given cstring * *
* supports format: * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format * * for cookies(RFC 822, RFC 850, RFC 1036, and RFC 1123): * Sun, 06-Nov-1994 08:49:37 GMT * ** * @param cstr the cstring * @param size the cstring length * * @return the date */ tb_time_t tb_http_date_from_cstr(tb_char_t const* cstr, tb_size_t size); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/impl/http/method.c 0000664 0000000 0000000 00000003064 14142237372 0021311 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file method.c */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "http_method" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "method.h" /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ static tb_char_t const* g_http_methods[] = { "GET" , "POST" , "HEAD" , "PUT" , "OPTIONS" , "DELETE" , "TRACE" , "CONNECT" }; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_char_t const* tb_http_method_cstr(tb_size_t method) { // check tb_assert_and_check_return_val(method < tb_arrayn(g_http_methods), tb_null); // ok return g_http_methods[method]; } tbox-1.6.7/src/tbox/network/impl/http/method.h 0000664 0000000 0000000 00000002661 14142237372 0021320 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file method.h * */ #ifndef TB_NETWORK_IMPL_HTTP_METHOD_H #define TB_NETWORK_IMPL_HTTP_METHOD_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* get the http method string * * @param method the method * * @return the method string */ tb_char_t const* tb_http_method_cstr(tb_size_t method); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/impl/http/option.c 0000664 0000000 0000000 00000046757 14142237372 0021361 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file option.c */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "http_option" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "option.h" #include "method.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_http_option_init(tb_http_option_t* option) { // check tb_assert_and_check_return_val(option, tb_false); // init option using the default value option->method = TB_HTTP_METHOD_GET; option->redirect = TB_HTTP_DEFAULT_REDIRECT; option->timeout = TB_HTTP_DEFAULT_TIMEOUT; option->version = 1; // HTTP/1.1 option->bunzip = 0; option->cookies = tb_null; // init url if (!tb_url_init(&option->url)) return tb_false; // init post url if (!tb_url_init(&option->post_url)) return tb_false; // init head data if (!tb_buffer_init(&option->head_data)) return tb_false; // ok return tb_true; } tb_void_t tb_http_option_exit(tb_http_option_t* option) { // check tb_assert_and_check_return(option); // exit url tb_url_exit(&option->url); // exit post url tb_url_exit(&option->post_url); // exit head data tb_buffer_exit(&option->head_data); // clear cookies option->cookies = tb_null; } tb_bool_t tb_http_option_ctrl(tb_http_option_t* option, tb_size_t code, tb_va_list_t args) { // check tb_assert_and_check_return_val(option, tb_false); // done switch (code) { case TB_HTTP_OPTION_SET_URL: { // url tb_char_t const* url = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(url, tb_false); // set url if (tb_url_cstr_set(&option->url, url)) return tb_true; } break; case TB_HTTP_OPTION_GET_URL: { // purl tb_char_t const** purl = (tb_char_t const**)tb_va_arg(args, tb_char_t const**); tb_assert_and_check_return_val(purl, tb_false); // get url tb_char_t const* url = tb_url_cstr(&option->url); tb_assert_and_check_return_val(url, tb_false); // ok *purl = url; return tb_true; } break; case TB_HTTP_OPTION_SET_HOST: { // host tb_char_t const* host = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(host, tb_false); // set host tb_url_host_set(&option->url, host); return tb_true; } break; case TB_HTTP_OPTION_GET_HOST: { // phost tb_char_t const** phost = (tb_char_t const**)tb_va_arg(args, tb_char_t const**); tb_assert_and_check_return_val(phost, tb_false); // get host tb_char_t const* host = tb_url_host(&option->url); tb_assert_and_check_return_val(host, tb_false); // ok *phost = host; return tb_true; } break; case TB_HTTP_OPTION_SET_PORT: { // port tb_size_t port = (tb_size_t)tb_va_arg(args, tb_size_t); tb_assert_and_check_return_val(port, tb_false); // set port tb_url_port_set(&option->url, (tb_uint16_t)port); return tb_true; } break; case TB_HTTP_OPTION_GET_PORT: { // pport tb_size_t* pport = (tb_size_t*)tb_va_arg(args, tb_size_t*); tb_assert_and_check_return_val(pport, tb_false); // get port *pport = tb_url_port(&option->url); return tb_true; } break; case TB_HTTP_OPTION_SET_PATH: { // path tb_char_t const* path = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(path, tb_false); // set path tb_url_path_set(&option->url, path); return tb_true; } break; case TB_HTTP_OPTION_GET_PATH: { // ppath tb_char_t const** ppath = (tb_char_t const**)tb_va_arg(args, tb_char_t const**); tb_assert_and_check_return_val(ppath, tb_false); // get path tb_char_t const* path = tb_url_path(&option->url); tb_assert_and_check_return_val(path, tb_false); // ok *ppath = path; return tb_true; } break; case TB_HTTP_OPTION_SET_METHOD: { // method tb_size_t method = (tb_size_t)tb_va_arg(args, tb_size_t); // set method option->method = method; return tb_true; } break; case TB_HTTP_OPTION_GET_METHOD: { // pmethod tb_size_t* pmethod = (tb_size_t*)tb_va_arg(args, tb_size_t*); tb_assert_and_check_return_val(pmethod, tb_false); // get method *pmethod = option->method; return tb_true; } break; case TB_HTTP_OPTION_SET_HEAD: { // key tb_char_t const* key = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(key, tb_false); // val tb_char_t const* val = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(val, tb_false); // remove the previous key and value tb_bool_t head_same = tb_false; tb_char_t const* head_head = (tb_char_t const*)tb_buffer_data(&option->head_data); tb_char_t const* head_data = head_head; tb_char_t const* head_tail = head_data + tb_buffer_size(&option->head_data); while (head_data < head_tail) { // the name and data tb_char_t const* name = head_data; tb_char_t const* data = head_data + tb_strlen(name) + 1; tb_char_t const* next = data + tb_strlen(data) + 1; tb_check_break(data < head_tail); // is this? if (!tb_stricmp(name, key)) { // value is different? remove it if (tb_stricmp(val, data)) tb_buffer_memmovp(&option->head_data, name - head_head, next - head_head); else head_same = tb_true; break; } // next head_data = next; } // set head if (!head_same) { tb_buffer_memncat(&option->head_data, (tb_byte_t const*)key, tb_strlen(key) + 1); tb_buffer_memncat(&option->head_data, (tb_byte_t const*)val, tb_strlen(val) + 1); } // ok return tb_true; } break; case TB_HTTP_OPTION_GET_HEAD: { // key tb_char_t const* key = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(key, tb_false); // pval tb_char_t const** pval = (tb_char_t const**)tb_va_arg(args, tb_char_t const**); tb_assert_and_check_return_val(pval, tb_false); // find head tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&option->head_data); tb_char_t const* head_tail = head_data + tb_buffer_size(&option->head_data); while (head_data < head_tail) { // the name and data tb_char_t const* name = head_data; tb_char_t const* data = head_data + tb_strlen(name) + 1; tb_check_break(data < head_tail); // is this? if (!tb_stricmp(name, key)) { // ok *pval = data; return tb_true; } // next head_data = data + tb_strlen(data) + 1; } // failed return tb_false; } break; case TB_HTTP_OPTION_SET_HEAD_FUNC: { // head_func tb_http_head_func_t head_func = (tb_http_head_func_t)tb_va_arg(args, tb_http_head_func_t); // set head_func option->head_func = head_func; return tb_true; } break; case TB_HTTP_OPTION_GET_HEAD_FUNC: { // phead_func tb_http_head_func_t* phead_func = (tb_http_head_func_t*)tb_va_arg(args, tb_http_head_func_t*); tb_assert_and_check_return_val(phead_func, tb_false); // get head_func *phead_func = option->head_func; return tb_true; } break; case TB_HTTP_OPTION_SET_HEAD_PRIV: { // head_priv tb_pointer_t head_priv = (tb_pointer_t)tb_va_arg(args, tb_pointer_t); // set head_priv option->head_priv = head_priv; return tb_true; } break; case TB_HTTP_OPTION_GET_HEAD_PRIV: { // phead_priv tb_pointer_t* phead_priv = (tb_pointer_t*)tb_va_arg(args, tb_pointer_t*); tb_assert_and_check_return_val(phead_priv, tb_false); // get head_priv *phead_priv = option->head_priv; return tb_true; } break; case TB_HTTP_OPTION_SET_RANGE: { // set range option->range.bof = (tb_hize_t)tb_va_arg(args, tb_hize_t); option->range.eof = (tb_hize_t)tb_va_arg(args, tb_hize_t); return tb_true; } break; case TB_HTTP_OPTION_GET_RANGE: { // pbof tb_hize_t* pbof = (tb_hize_t*)tb_va_arg(args, tb_hize_t*); tb_assert_and_check_return_val(pbof, tb_false); // peof tb_hize_t* peof = (tb_hize_t*)tb_va_arg(args, tb_hize_t*); tb_assert_and_check_return_val(peof, tb_false); // ok *pbof = option->range.bof; *peof = option->range.eof; return tb_true; } break; case TB_HTTP_OPTION_SET_SSL: { // bssl tb_bool_t bssl = (tb_bool_t)tb_va_arg(args, tb_bool_t); // set ssl tb_url_ssl_set(&option->url, bssl); return tb_true; } break; case TB_HTTP_OPTION_GET_SSL: { // pssl tb_bool_t* pssl = (tb_bool_t*)tb_va_arg(args, tb_bool_t*); tb_assert_and_check_return_val(pssl, tb_false); // get ssl *pssl = tb_url_ssl(&option->url); return tb_true; } break; case TB_HTTP_OPTION_SET_TIMEOUT: { // the timeout tb_long_t timeout = (tb_long_t)tb_va_arg(args, tb_long_t); // set timeout option->timeout = timeout? timeout : TB_HTTP_DEFAULT_TIMEOUT; return tb_true; } break; case TB_HTTP_OPTION_GET_TIMEOUT: { // ptimeout tb_long_t* ptimeout = (tb_long_t*)tb_va_arg(args, tb_long_t*); tb_assert_and_check_return_val(ptimeout, tb_false); // get timeout *ptimeout = option->timeout; return tb_true; } break; case TB_HTTP_OPTION_SET_COOKIES: { // set cookies option->cookies = (tb_cookies_ref_t)tb_va_arg(args, tb_cookies_ref_t); return tb_true; } break; case TB_HTTP_OPTION_GET_COOKIES: { // ptimeout tb_cookies_ref_t* pcookies = (tb_cookies_ref_t*)tb_va_arg(args, tb_cookies_ref_t*); tb_assert_and_check_return_val(pcookies, tb_false); // get cookies *pcookies = option->cookies; return tb_true; } break; case TB_HTTP_OPTION_SET_POST_URL: { // url tb_char_t const* url = (tb_char_t const*)tb_va_arg(args, tb_char_t const*); tb_assert_and_check_return_val(url, tb_false); // clear post data and size option->post_data = tb_null; option->post_size = 0; // set url if (tb_url_cstr_set(&option->post_url, url)) return tb_true; } break; case TB_HTTP_OPTION_GET_POST_URL: { // purl tb_char_t const** purl = (tb_char_t const**)tb_va_arg(args, tb_char_t const**); tb_assert_and_check_return_val(purl, tb_false); // get url tb_char_t const* url = tb_url_cstr(&option->post_url); tb_assert_and_check_return_val(url, tb_false); // ok *purl = url; return tb_true; } break; case TB_HTTP_OPTION_SET_POST_DATA: { // post data tb_byte_t const* data = (tb_byte_t const*)tb_va_arg(args, tb_byte_t const*); // post size tb_size_t size = (tb_size_t)tb_va_arg(args, tb_size_t); // clear post url tb_url_clear(&option->post_url); // set post data option->post_data = data; option->post_size = size; return tb_true; } break; case TB_HTTP_OPTION_GET_POST_DATA: { // pdata and psize tb_byte_t const** pdata = (tb_byte_t const**)tb_va_arg(args, tb_byte_t const**); tb_size_t* psize = (tb_size_t*)tb_va_arg(args, tb_size_t*); tb_assert_and_check_return_val(pdata && psize, tb_false); // get post data and size *pdata = option->post_data; *psize = option->post_size; return tb_true; } break; case TB_HTTP_OPTION_SET_POST_FUNC: { // func tb_http_post_func_t func = (tb_http_post_func_t)tb_va_arg(args, tb_http_post_func_t); // set post func option->post_func = func; return tb_true; } break; case TB_HTTP_OPTION_GET_POST_FUNC: { // pfunc tb_http_post_func_t* pfunc = (tb_http_post_func_t*)tb_va_arg(args, tb_http_post_func_t*); tb_assert_and_check_return_val(pfunc, tb_false); // get post func *pfunc = option->post_func; return tb_true; } break; case TB_HTTP_OPTION_SET_POST_PRIV: { // post priv tb_cpointer_t priv = (tb_pointer_t)tb_va_arg(args, tb_pointer_t); // set post priv option->post_priv = priv; return tb_true; } break; case TB_HTTP_OPTION_GET_POST_PRIV: { // ppost priv tb_cpointer_t* ppriv = (tb_cpointer_t*)tb_va_arg(args, tb_cpointer_t*); tb_assert_and_check_return_val(ppriv, tb_false); // get post priv *ppriv = option->post_priv; return tb_true; } break; case TB_HTTP_OPTION_SET_POST_LRATE: { // post lrate tb_size_t lrate = (tb_size_t)tb_va_arg(args, tb_size_t); // set post lrate option->post_lrate = lrate; return tb_true; } break; case TB_HTTP_OPTION_GET_POST_LRATE: { // ppost lrate tb_size_t* plrate = (tb_size_t*)tb_va_arg(args, tb_size_t*); tb_assert_and_check_return_val(plrate, tb_false); // get post lrate *plrate = option->post_lrate; return tb_true; } break; case TB_HTTP_OPTION_SET_AUTO_UNZIP: { // bunzip tb_bool_t bunzip = (tb_bool_t)tb_va_arg(args, tb_bool_t); // set bunzip option->bunzip = bunzip? 1 : 0; return tb_true; } break; case TB_HTTP_OPTION_GET_AUTO_UNZIP: { // pbunzip tb_bool_t* pbunzip = (tb_bool_t*)tb_va_arg(args, tb_bool_t*); tb_assert_and_check_return_val(pbunzip, tb_false); // get bunzip *pbunzip = option->bunzip? tb_true : tb_false; return tb_true; } break; case TB_HTTP_OPTION_SET_REDIRECT: { // redirect tb_size_t redirect = (tb_size_t)tb_va_arg(args, tb_size_t); // set redirect option->redirect = redirect; return tb_true; } break; case TB_HTTP_OPTION_GET_REDIRECT: { // predirect tb_size_t* predirect = (tb_size_t*)tb_va_arg(args, tb_size_t*); tb_assert_and_check_return_val(predirect, tb_false); // get redirect *predirect = option->redirect; return tb_true; } break; case TB_HTTP_OPTION_SET_VERSION: { // version tb_size_t version = (tb_size_t)tb_va_arg(args, tb_size_t); // set version option->version = version; return tb_true; } break; case TB_HTTP_OPTION_GET_VERSION: { // pversion tb_size_t* pversion = (tb_size_t*)tb_va_arg(args, tb_size_t*); tb_assert_and_check_return_val(pversion, tb_false); // get version *pversion = option->version; return tb_true; } break; default: break; } // failed return tb_false; } #ifdef __tb_debug__ tb_void_t tb_http_option_dump(tb_http_option_t* option) { // check tb_assert_and_check_return(option); // dump option tb_trace_i("======================================================================"); tb_trace_i("option: "); tb_trace_i("option: url: %s", tb_url_cstr(&option->url)); tb_trace_i("option: version: HTTP/1.%1u", option->version); tb_trace_i("option: method: %s", tb_http_method_cstr(option->method)); tb_trace_i("option: redirect: %d", option->redirect); tb_trace_i("option: range: %llu-%llu", option->range.bof, option->range.eof); tb_trace_i("option: bunzip: %s", option->bunzip? "true" : "false"); // dump head tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&option->head_data); tb_char_t const* head_tail = head_data + tb_buffer_size(&option->head_data); while (head_data < head_tail) { // the name and data tb_char_t const* name = head_data; tb_char_t const* data = head_data + tb_strlen(name) + 1; tb_check_break(data < head_tail); // trace tb_trace_i("option: head: %s: %s", name, data); // next head_data = data + tb_strlen(data) + 1; } // dump end tb_trace_i(""); } #endif tbox-1.6.7/src/tbox/network/impl/http/option.h 0000664 0000000 0000000 00000003721 14142237372 0021346 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file option.h * @ingroup network * */ #ifndef TB_NETWORK_IMPL_HTTP_OPTION_H #define TB_NETWORK_IMPL_HTTP_OPTION_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init option * * @param option the option * * @return tb_true or tb_false */ tb_bool_t tb_http_option_init(tb_http_option_t* option); /* exit option * * @param option the option */ tb_void_t tb_http_option_exit(tb_http_option_t* option); /* ctrl option * * @param option the option * @param ctrl the ctrl code * @param args the ctrl args */ tb_bool_t tb_http_option_ctrl(tb_http_option_t* option, tb_size_t code, tb_va_list_t args); #ifdef __tb_debug__ /* dump option * * @param option the option */ tb_void_t tb_http_option_dump(tb_http_option_t* option); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/impl/http/prefix.h 0000664 0000000 0000000 00000003021 14142237372 0021324 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_NETWORK_IMPL_HTTP_PREFIX_H #define TB_NETWORK_IMPL_HTTP_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../../url.h" #include "../../http.h" #include "../../cookies.h" #include "../../../libc/libc.h" #include "../../../string/string.h" #include "../../../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the http default timeout, 10s #define TB_HTTP_DEFAULT_TIMEOUT (10000) /// the http default redirect maxn #define TB_HTTP_DEFAULT_REDIRECT (10) /// the http default port #define TB_HTTP_DEFAULT_PORT (80) /// the http default port for ssl #define TB_HTTP_DEFAULT_PORT_SSL (443) #endif tbox-1.6.7/src/tbox/network/impl/http/status.c 0000664 0000000 0000000 00000006725 14142237372 0021363 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file status.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "http_status" #define TB_TRACE_MODULE_DEBUG (1) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "status.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_http_status_init(tb_http_status_t* status) { // check tb_assert_and_check_return_val(status, tb_false); // init status using the default value status->version = 1; // init content type if (!tb_string_init(&status->content_type)) return tb_false; // init location if (!tb_string_init(&status->location)) return tb_false; // ok return tb_true; } tb_void_t tb_http_status_exit(tb_http_status_t* status) { // check tb_assert_and_check_return(status); // exit the content type tb_string_exit(&status->content_type); // exit location tb_string_exit(&status->location); } tb_void_t tb_http_status_cler(tb_http_status_t* status, tb_bool_t host_changed) { // check tb_assert_and_check_return(status); // clear status status->code = 0; status->bgzip = 0; status->bdeflate = 0; status->bchunked = 0; status->content_size = -1; status->document_size = -1; status->state = TB_STATE_OK; // clear content type tb_string_clear(&status->content_type); // clear location tb_string_clear(&status->location); // host is changed? clear the alived state if (host_changed) { status->version = 1; status->balived = 0; status->bseeked = 0; } } #ifdef __tb_debug__ tb_void_t tb_http_status_dump(tb_http_status_t* status) { // check tb_assert_and_check_return(status); // dump status tb_trace_i("======================================================================"); tb_trace_i("status: "); tb_trace_i("status: code: %d", status->code); tb_trace_i("status: version: HTTP/1.%1u", status->version); tb_trace_i("status: content:type: %s", tb_string_cstr(&status->content_type)); tb_trace_i("status: content:size: %lld", status->content_size); tb_trace_i("status: document:size: %lld", status->document_size); tb_trace_i("status: location: %s", tb_string_cstr(&status->location)); tb_trace_i("status: bgzip: %s", status->bgzip? "true" : "false"); tb_trace_i("status: bdeflate: %s", status->bdeflate? "true" : "false"); tb_trace_i("status: balived: %s", status->balived? "true" : "false"); tb_trace_i("status: bseeked: %s", status->bseeked? "true" : "false"); tb_trace_i("status: bchunked: %s", status->bchunked? "true" : "false"); // dump end tb_trace_i(""); } #endif tbox-1.6.7/src/tbox/network/impl/http/status.h 0000664 0000000 0000000 00000003614 14142237372 0021362 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file status.h */ #ifndef TB_NETWORK_IMPL_HTTP_STATUS_H #define TB_NETWORK_IMPL_HTTP_STATUS_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init status * * @param status the status * * @return tb_true or tb_false */ tb_bool_t tb_http_status_init(tb_http_status_t* status); /* exit status * * @param status the status */ tb_void_t tb_http_status_exit(tb_http_status_t* status); /* clear status * * @param status the status * @param host_changed the host is changed */ tb_void_t tb_http_status_cler(tb_http_status_t* status, tb_bool_t host_changed); #ifdef __tb_debug__ /* dump status * * @param status the status */ tb_void_t tb_http_status_dump(tb_http_status_t* status); #endif /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/impl/impl.h 0000664 0000000 0000000 00000001623 14142237372 0020017 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file network.h * @ingroup network * */ #ifndef TB_NETWORK_IMPL_H #define TB_NETWORK_IMPL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "network.h" #endif tbox-1.6.7/src/tbox/network/impl/network.c 0000664 0000000 0000000 00000010003 14142237372 0020532 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file network.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "network.h" #include "../network.h" #include "../../libc/libc.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ #ifndef TB_CONFIG_MICRO_ENABLE static tb_long_t tb_network_printf_format_ipv4(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(object && cstr && maxn, -1); // the ipv4 tb_ipv4_ref_t ipv4 = (tb_ipv4_ref_t)object; // make it cstr = (tb_char_t*)tb_ipv4_cstr(ipv4, cstr, maxn); // ok? return cstr? tb_strlen(cstr) : -1; } static tb_long_t tb_network_printf_format_ipv6(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(object && cstr && maxn, -1); // the ipv6 tb_ipv6_ref_t ipv6 = (tb_ipv6_ref_t)object; // make it cstr = (tb_char_t*)tb_ipv6_cstr(ipv6, cstr, maxn); // ok? return cstr? tb_strlen(cstr) : -1; } static tb_long_t tb_network_printf_format_unixaddr(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(object && cstr && maxn, -1); // the unixaddr tb_unixaddr_ref_t unixaddr = (tb_unixaddr_ref_t)object; // make it cstr = (tb_char_t*)tb_unixaddr_cstr(unixaddr, cstr, maxn); // ok? return cstr? tb_strlen(cstr) : -1; } static tb_long_t tb_network_printf_format_ipaddr(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(object && cstr && maxn, -1); // the ipaddr tb_ipaddr_ref_t ipaddr = (tb_ipaddr_ref_t)object; // make it cstr = (tb_char_t*)tb_ipaddr_cstr(ipaddr, cstr, maxn); // ok? return cstr? tb_strlen(cstr) : -1; } static tb_long_t tb_network_printf_format_hwaddr(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn) { // check tb_assert_and_check_return_val(object && cstr && maxn, -1); // the hwaddr tb_hwaddr_ref_t hwaddr = (tb_hwaddr_ref_t)object; // make it cstr = (tb_char_t*)tb_hwaddr_cstr(hwaddr, cstr, maxn); // ok? return cstr? tb_strlen(cstr) : -1; } #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_network_init_env() { #ifndef TB_CONFIG_MICRO_ENABLE // init dns server if (!tb_dns_server_init()) return tb_false; // init dns cache if (!tb_dns_cache_init()) return tb_false; // register printf("%{ipv4}", &ipv4); tb_printf_object_register("ipv4", tb_network_printf_format_ipv4); // register printf("%{ipv6}", &ipv6); tb_printf_object_register("ipv6", tb_network_printf_format_ipv6); // register printf("%{unixaddr}", &unixaddr); tb_printf_object_register("unixaddr", tb_network_printf_format_unixaddr); // register printf("%{ipaddr}", &ipaddr); tb_printf_object_register("ipaddr", tb_network_printf_format_ipaddr); // register printf("%{hwaddr}", &hwaddr); tb_printf_object_register("hwaddr", tb_network_printf_format_hwaddr); #endif // ok return tb_true; } tb_void_t tb_network_exit_env() { #ifndef TB_CONFIG_MICRO_ENABLE // exit dns cache tb_dns_cache_exit(); // exit dns server tb_dns_server_exit(); #endif } tbox-1.6.7/src/tbox/network/impl/network.h 0000664 0000000 0000000 00000002725 14142237372 0020553 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file network.h * @ingroup network * */ #ifndef TB_NETWORK_IMPL_NETWORK_H #define TB_NETWORK_IMPL_NETWORK_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init network environment * * @return tb_true or tb_false */ tb_bool_t tb_network_init_env(tb_noarg_t); /// exit network environment tb_void_t tb_network_exit_env(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/impl/prefix.h 0000664 0000000 0000000 00000001611 14142237372 0020350 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_NETWORK_IMPL_PREFIX_H #define TB_NETWORK_IMPL_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #endif tbox-1.6.7/src/tbox/network/impl/ssl/ 0000775 0000000 0000000 00000000000 14142237372 0017504 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/network/impl/ssl/mbedtls.c 0000664 0000000 0000000 00000044040 14142237372 0021304 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file mbedtls.c * @ingroup network * */ #define TB_TRACE_MODULE_NAME "mbedtls" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include
* xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx * xxxx::xxxx:xxxx * ::ffff:xxx.xxx.xxx.xxx * ::fe80:1%1 **/ typedef struct __tb_ipv6_t { /// the scope id tb_uint32_t scope_id; /// the address union { /// u32, little-endian tb_uint32_t u32[4]; /// u16, little-endian tb_uint16_t u16[8]; /// u8 tb_uint8_t u8[16]; } addr; }tb_ipv6_t, *tb_ipv6_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! clear the ipv6 * * @param ipv6 the ipv6 */ tb_void_t tb_ipv6_clear(tb_ipv6_ref_t ipv6); /*! is any address? * * @param ipv6 the ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_any(tb_ipv6_ref_t ipv6); /*! is loopback address? * * @param ipv6 the ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_loopback(tb_ipv6_ref_t ipv6); /*! is linklocal address? * * @param ipv6 the ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_linklocal(tb_ipv6_ref_t ipv6); /*! is mc linklocal address? * * @param ipv6 the ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_mc_linklocal(tb_ipv6_ref_t ipv6); /*! is sitelocal address? * * @param ipv6 the ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_sitelocal(tb_ipv6_ref_t ipv6); /*! is multicast address? * * @param ipv6 the ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_multicast(tb_ipv6_ref_t ipv6); /*! is equal? * * @param ipv6 the ipv6 * @param other the other ipv6 * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_is_equal(tb_ipv6_ref_t ipv6, tb_ipv6_ref_t other); /*! get the ipv6 string * * @param ipv6 the ipv6 * @param data the ipv6 string data * @param maxn the ipv6 string data maxn * * @return the ipv6 string */ tb_char_t const* tb_ipv6_cstr(tb_ipv6_ref_t ipv6, tb_char_t* data, tb_size_t maxn); /*! set the ipv6 from string * * @param ipv6 the ipv6 * @param cstr the ipv6 string * * @return tb_true or tb_false */ tb_bool_t tb_ipv6_cstr_set(tb_ipv6_ref_t ipv6, tb_char_t const* cstr); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/network.h 0000664 0000000 0000000 00000002107 14142237372 0017604 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file network.h * @defgroup network * */ #ifndef TB_NETWORK_H #define TB_NETWORK_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "ssl.h" #include "url.h" #include "ipv4.h" #include "ipv6.h" #include "unixaddr.h" #include "ipaddr.h" #include "hwaddr.h" #include "http.h" #include "cookies.h" #include "dns/dns.h" #endif tbox-1.6.7/src/tbox/network/prefix.h 0000664 0000000 0000000 00000001577 14142237372 0017422 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * */ #ifndef TB_NETWORK_PREFIX_H #define TB_NETWORK_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #endif tbox-1.6.7/src/tbox/network/ssl.h 0000664 0000000 0000000 00000013453 14142237372 0016722 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file ssl.h * @ingroup network * */ #ifndef TB_NETWORK_SSL_H #define TB_NETWORK_SSL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // enable ssl? #if defined(TB_CONFIG_PACKAGE_HAVE_OPENSSL) \ || defined(TB_CONFIG_PACKAGE_HAVE_MBEDTLS) \ || defined(TB_CONFIG_PACKAGE_HAVE_POLARSSL) # define TB_SSL_ENABLE #else # undef TB_SSL_ENABLE #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the ssl read func type * * @param priv the priv data for context * @param data the data * @param size the size * * @return the real size, no data: 0, failed: -1 */ typedef tb_long_t (*tb_ssl_func_read_t)(tb_cpointer_t priv, tb_byte_t* data, tb_size_t size); /*! the ssl writ func type * * @param priv the priv data for context * @param data the data * @param size the size * * @return the real size, no data: 0, failed: -1 */ typedef tb_long_t (*tb_ssl_func_writ_t)(tb_cpointer_t priv, tb_byte_t const* data, tb_size_t size); /*! the ssl wait func type * * @param priv the priv data for context * @param code the events code * @param timeout the timeout * * @return the real code, no event: 0, failed or closed: -1 */ typedef tb_long_t (*tb_ssl_func_wait_t)(tb_cpointer_t priv, tb_size_t code, tb_long_t timeout); /// the ssl ref type typedef __tb_typeref__(ssl); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init ssl * * @param bserver is server endpoint? * * @return the ssl */ tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver); /*! exit ssl * * @param ssl the ssl */ tb_void_t tb_ssl_exit(tb_ssl_ref_t ssl); /*! set ssl bio sock * * @param ssl the ssl * @param sock the sock handle, non-blocking */ tb_void_t tb_ssl_set_bio_sock(tb_ssl_ref_t ssl, tb_socket_ref_t sock); /*! set ssl bio read and writ func * * @param ssl the ssl * @param read the read func * @param writ the writ func * #param wait the wait func only for tb_ssl_open and tb_ssl_wait * @param priv the priv data */ tb_void_t tb_ssl_set_bio_func(tb_ssl_ref_t ssl, tb_ssl_func_read_t read, tb_ssl_func_writ_t writ, tb_ssl_func_wait_t wait, tb_cpointer_t priv); /*! set ssl timeout for opening * * @param ssl the ssl * @param timeout the timeout */ tb_void_t tb_ssl_set_timeout(tb_ssl_ref_t ssl, tb_long_t timeout); /*! open ssl using blocking mode * * @note need wait func * * @param ssl the ssl * * @return tb_true or tb_false */ tb_bool_t tb_ssl_open(tb_ssl_ref_t ssl); /*! try opening ssl using non-blocking mode * * @code * // open it tb_long_t ok = -1; while (!(ok = tb_ssl_open_try(handle))) { // wait it ok = tb_ssl_wait(handle, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, timeout); tb_check_break(ok > 0); } * @endcode * * @param ssl the ssl * * @return ok: 1, continue: 0, failed: -1 */ tb_long_t tb_ssl_open_try(tb_ssl_ref_t ssl); /*! clos ssl * * @param ssl the ssl * * @return tb_true or tb_false */ tb_bool_t tb_ssl_close(tb_ssl_ref_t ssl); /*! try closing ssl using non-blocking mode * * @code * // open it tb_long_t ok = -1; while (!(ok = tb_ssl_close_try(handle))) { // wait it ok = tb_ssl_wait(handle, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, timeout); tb_check_break(ok > 0); } * @endcode * * @param ssl the ssl * * @return ok: 1, continue: 0, failed: -1 */ tb_long_t tb_ssl_close_try(tb_ssl_ref_t ssl); /*! read ssl data * * @param ssl the ssl * @param data the data * @param size the size * * @return the real size, no data: 0 and see state for waiting, failed: -1 */ tb_long_t tb_ssl_read(tb_ssl_ref_t ssl, tb_byte_t* data, tb_size_t size); /*! writ ssl data * * @param ssl the ssl * @param data the data * @param size the size * * @return the real size, no data: 0 and see state for waiting, failed: -1 */ tb_long_t tb_ssl_writ(tb_ssl_ref_t ssl, tb_byte_t const* data, tb_size_t size); /*! wait ssl data * * @param ssl the ssl * @param events the events * @param timeout the timeout * * @return the real events, no event: 0, failed or closed: -1 */ tb_long_t tb_ssl_wait(tb_ssl_ref_t ssl, tb_size_t events, tb_long_t timeout); /*! the ssl state see the stream ssl state * * @param ssl the ssl * * @return the ssl state */ tb_size_t tb_ssl_state(tb_ssl_ref_t ssl); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/unixaddr.c 0000664 0000000 0000000 00000005126 14142237372 0017730 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author CodeHz * @file unixaddr.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "unixaddr" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "unixaddr.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../string/string.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_void_t tb_unixaddr_clear(tb_unixaddr_ref_t unixaddr) { // check tb_assert_and_check_return(unixaddr); // clear it tb_memset(unixaddr->path, 0, sizeof(unixaddr->path)); } tb_bool_t tb_unixaddr_is_abstract(tb_unixaddr_ref_t unixaddr) { // check tb_assert_and_check_return_val(unixaddr, tb_false); // is abstract? return unixaddr->is_abstract; } tb_bool_t tb_unixaddr_is_equal(tb_unixaddr_ref_t unixaddr, tb_unixaddr_ref_t other) { // check tb_assert_and_check_return_val(unixaddr && other, tb_false); // is equal? return tb_strcmp(unixaddr->path, other->path) == 0; } tb_char_t const* tb_unixaddr_cstr(tb_unixaddr_ref_t unixaddr, tb_char_t* data, tb_size_t maxn) { // check tb_assert_and_check_return_val(unixaddr && data && maxn >= TB_UNIXADDR_CSTR_MAXN, tb_null); // make it tb_long_t size = tb_snprintf(data, maxn - 1, "%s", unixaddr->path); if (size >= 0) data[size] = '\0'; // ok return data; } tb_bool_t tb_unixaddr_cstr_set(tb_unixaddr_ref_t unixaddr, tb_char_t const* cstr, tb_bool_t is_abstract) { // check tb_assert_and_check_return_val(cstr, tb_false); // set is_abstract unixaddr->is_abstract = is_abstract; // copy and report return tb_strlcpy(unixaddr->path, cstr, TB_UNIXADDR_CSTR_MAXN) < TB_UNIXADDR_CSTR_MAXN; } tbox-1.6.7/src/tbox/network/unixaddr.h 0000664 0000000 0000000 00000005504 14142237372 0017735 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author CodeHz * @file unixaddr.h * @ingroup network * */ #ifndef TB_NETWORK_UNIX_H #define TB_NETWORK_UNIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ /// the unixaddr string data maxn #define TB_UNIXADDR_CSTR_MAXN (108) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /*! the unix type * * /path/to.sock */ typedef struct __tb_unixaddr_t { /// is abstract tb_bool_t is_abstract; /// path tb_char_t path[TB_UNIXADDR_CSTR_MAXN]; }tb_unixaddr_t, *tb_unixaddr_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! clear the unixaddr * * @param unixaddr the unixaddr */ tb_void_t tb_unixaddr_clear(tb_unixaddr_ref_t unixaddr); /*! is abstract? * * @param unixaddr the unixaddr * * @return tb_true or tb_false */ tb_bool_t tb_unixaddr_is_abstract(tb_unixaddr_ref_t unixaddr); /*! is equal? * * @param unixaddr the unixaddr * @param other the other unixaddr * * @return tb_true or tb_false */ tb_bool_t tb_unixaddr_is_equal(tb_unixaddr_ref_t unixaddr, tb_unixaddr_ref_t other); /*! get the unixaddr string * * @param unixaddr the unixaddr * @param data the unixaddr data * @param maxn the data maxn * * @return the unixaddr path */ tb_char_t const* tb_unixaddr_cstr(tb_unixaddr_ref_t unixaddr, tb_char_t* data, tb_size_t maxn); /*! set the unixaddr from string * * @param unixaddr the unixaddr * @param cstr the unixaddr path * * @return tb_true or tb_false */ tb_bool_t tb_unixaddr_cstr_set(tb_unixaddr_ref_t unixaddr, tb_char_t const* cstr, tb_bool_t is_abstract); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/network/url.c 0000664 0000000 0000000 00000046107 14142237372 0016720 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file url.c * @ingroup network * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "url" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "url.h" #include "http.h" #include "impl/http/prefix.h" #include "../libc/libc.h" #include "../math/math.h" #include "../utils/utils.h" #include "../platform/platform.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_char_t const* tb_url_parse_args(tb_string_ref_t args, tb_char_t const* p) { // check tb_assert_and_check_return_val(args && p, tb_null); // clear args tb_string_clear(args); // skip '?' or ' ' while (*p && (*p == '?' || tb_isspace(*p))) p++; // done while (*p) tb_string_chrcat(args, *p++); // end return p; } static tb_char_t const* tb_url_parse_path(tb_string_ref_t path, tb_char_t const* p, tb_size_t protocol) { // check tb_assert_and_check_return_val(path && p, tb_null); // clear path tb_string_clear(path); // skip ' ' while (*p && tb_isspace(*p)) p++; // append root: '/' if (*p != '/' && *p != '\\') tb_string_chrcat(path, '/'); // done tb_char_t ch; while ((ch = *p) && ((ch != '?' && ch != '#') || protocol == TB_URL_PROTOCOL_FILE)) { // replace '\\' => '/' if (ch == '\\') tb_string_chrcat(path, '/'); // append character else tb_string_chrcat(path, ch); // next p++; } // end return p; } static tb_char_t const* tb_url_parse_host(tb_string_ref_t host, tb_char_t const* p) { // check tb_assert_and_check_return_val(host && p, tb_null); // clear path tb_string_clear(host); // ipv6? [xxxx:xxxx:...]:port if (*p == '[') { // skip '[' p++; // parse host tb_char_t ch; while ((ch = *p) && ch != ']') { // append character tb_string_chrcat(host, ch); // next p++; } // append ']' if (ch == ']') p++; } else { // parse host tb_char_t ch; while ((ch = *p) && !tb_isspace(ch) && ch != ':' && ch != '/' && ch != '\\' && ch != '?' && ch != '&') { // append character tb_string_chrcat(host, ch); // next p++; } } // end return p; } static tb_char_t const* tb_url_parse_port(tb_uint16_t* port, tb_char_t const* p) { // check tb_assert_and_check_return_val(port && p, tb_null); // done tb_char_t data[12] = {0}; tb_char_t* pb = data; tb_char_t* pe = data + sizeof(data); while (pb < pe && *p && tb_isdigit(*p)) *pb++ = *p++; *port = (tb_uint16_t)tb_s10tou32(data); // end return p; } static tb_char_t const* tb_url_parse_data(tb_string_ref_t data, tb_char_t const* p) { // check tb_assert_and_check_return_val(data && p, tb_null); // clear path tb_string_clear(data); // skip '/' and '\\' and ' ' while (*p && (*p == '/' || *p == '\\' || tb_isspace(*p))) p++; // done tb_char_t ch; while ((ch = *p) && !tb_isspace(ch)) { // append data tb_string_chrcat(data, ch); // next p++; } // end return p; } /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_url_init(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_false); // done tb_bool_t ok = tb_false; do { // init url url->protocol = TB_URL_PROTOCOL_NONE; url->is_ssl = 0; url->is_win = 0; url->pwin = 0; tb_ipaddr_clear(&url->addr); if (!tb_string_init(&url->host)) break; if (!tb_string_init(&url->path)) break; if (!tb_string_init(&url->args)) break; if (!tb_string_init(&url->cache)) break; // ok ok = tb_true; } while (0); // failed? exit it if (!ok) tb_url_exit(url); // ok return ok; } tb_bool_t tb_url_init_from_cstr(tb_url_ref_t url, tb_char_t const* cstr) { return tb_url_init(url) && tb_url_cstr_set(url, cstr); } tb_void_t tb_url_exit(tb_url_ref_t url) { if (url) { tb_string_exit(&url->host); tb_string_exit(&url->path); tb_string_exit(&url->args); tb_string_exit(&url->cache); } } tb_void_t tb_url_clear(tb_url_ref_t url) { // check tb_assert_and_check_return(url); // clear url->protocol = TB_URL_PROTOCOL_NONE; url->is_ssl = 0; url->is_win = 0; url->pwin = 0; tb_ipaddr_clear(&url->addr); tb_string_clear(&url->host); tb_string_clear(&url->path); tb_string_clear(&url->args); tb_string_clear(&url->cache); } tb_char_t const* tb_url_cstr(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_null); // exists? return it directly if (tb_string_size(&url->cache)) return tb_string_cstr(&url->cache); // make switch (url->protocol) { case TB_URL_PROTOCOL_FILE: { // check tb_check_return_val(tb_string_size(&url->path), tb_null); // add protocol for win if (url->is_win) { tb_assert(url->pwin); tb_string_cstrfcpy(&url->cache, "%c:/", url->pwin); } // add path tb_string_cstrncat(&url->cache, tb_string_cstr(&url->path), tb_string_size(&url->path)); } break; case TB_URL_PROTOCOL_SOCK: case TB_URL_PROTOCOL_HTTP: case TB_URL_PROTOCOL_RTSP: { // the port tb_uint16_t port = tb_ipaddr_port(&url->addr); // check tb_check_return_val(port && tb_string_size(&url->host), tb_null); // add protocol if (url->protocol == TB_URL_PROTOCOL_HTTP) tb_string_cstrcpy(&url->cache, "http"); else if (url->protocol == TB_URL_PROTOCOL_SOCK) tb_string_cstrcpy(&url->cache, "sock"); else if (url->protocol == TB_URL_PROTOCOL_RTSP) tb_string_cstrcpy(&url->cache, "rtsp"); else tb_assert_and_check_break(0); // add ssl if (url->is_ssl) tb_string_chrcat(&url->cache, 's'); // add :// tb_string_cstrncat(&url->cache, "://", 3); // add host for ipv6 if (tb_ipaddr_family(&url->addr) == TB_IPADDR_FAMILY_IPV6) { tb_string_chrcat(&url->cache, '['); tb_string_cstrncat(&url->cache, tb_string_cstr(&url->host), tb_string_size(&url->host)); tb_string_chrcat(&url->cache, ']'); } // add host for ipv4 else tb_string_cstrncat(&url->cache, tb_string_cstr(&url->host), tb_string_size(&url->host)); // add port if ( (url->protocol != TB_URL_PROTOCOL_HTTP) || (url->is_ssl && port != TB_HTTP_DEFAULT_PORT_SSL) || (!url->is_ssl && port != TB_HTTP_DEFAULT_PORT)) { tb_string_cstrfcat(&url->cache, ":%u", port); } // add path if (tb_string_size(&url->path)) tb_string_cstrncat(&url->cache, tb_string_cstr(&url->path), tb_string_size(&url->path)); // add args if (tb_string_size(&url->args)) { tb_string_chrcat(&url->cache, '?'); tb_string_strcat(&url->cache, &url->args); } } break; case TB_URL_PROTOCOL_SQL: { // add protocol tb_string_cstrcpy(&url->cache, "sql://"); // add host and port if (tb_string_size(&url->host)) { // the port tb_uint16_t port = tb_ipaddr_port(&url->addr); // add host tb_string_cstrncat(&url->cache, tb_string_cstr(&url->host), tb_string_size(&url->host)); // add port if (port) tb_string_cstrfcat(&url->cache, ":%u", port); } // add path if (tb_string_size(&url->path)) tb_string_cstrncat(&url->cache, tb_string_cstr(&url->path), tb_string_size(&url->path)); // add args if (tb_string_size(&url->args)) { tb_string_chrcat(&url->cache, '?'); tb_string_strcat(&url->cache, &url->args); } } break; case TB_URL_PROTOCOL_DATA: break; default: break; } // ok? return tb_string_size(&url->cache)? tb_string_cstr(&url->cache) : tb_null; } tb_bool_t tb_url_cstr_set(tb_url_ref_t url, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(url && cstr, tb_false); // done tb_bool_t ok = tb_false; do { // init tb_url_clear(url); // parse proto tb_char_t const* p = cstr; tb_char_t full[TB_PATH_MAXN]; if (!tb_strnicmp(p, "http://", 7)) { url->protocol = TB_URL_PROTOCOL_HTTP; url->is_ssl = 0; p += 7; } else if (!tb_strnicmp(p, "sock://", 7)) { url->protocol = TB_URL_PROTOCOL_SOCK; url->is_ssl = 0; p += 7; } else if (!tb_strnicmp(p, "file://", 7)) { url->protocol = TB_URL_PROTOCOL_FILE; url->is_ssl = 0; p += 7; } else if (!tb_strnicmp(p, "rtsp://", 7)) { url->protocol = TB_URL_PROTOCOL_RTSP; url->is_ssl = 0; p += 7; } else if (!tb_strnicmp(p, "data://", 7)) { url->protocol = TB_URL_PROTOCOL_DATA; url->is_ssl = 0; p += 7; } else if (!tb_strnicmp(p, "https://", 8)) { url->protocol = TB_URL_PROTOCOL_HTTP; url->is_ssl = 1; p += 8; } else if (!tb_strnicmp(p, "socks://", 8)) { url->protocol = TB_URL_PROTOCOL_SOCK; url->is_ssl = 1; p += 8; } else if (!tb_strnicmp(p, "sql://", 6)) { url->protocol = TB_URL_PROTOCOL_SQL; url->is_ssl = 0; p += 6; } // ./file or /home/file or c:/file or c:\\file ... else if ((p = tb_path_absolute(cstr, full, TB_PATH_MAXN))) { // for unix style path if ((*p == '/') || (!tb_strnicmp(p, "file://", 7))) { url->protocol = TB_URL_PROTOCOL_FILE; url->is_ssl = 0; if (*p != '/') p += 7; } // for windows style path else if (tb_isalpha(p[0]) && p[1] == ':' && (p[2] == '/' || p[2] == '\\')) { url->protocol = TB_URL_PROTOCOL_FILE; url->is_ssl = 0; url->is_win = 1; url->pwin = *p; // skip the drive prefix p += 3; } else break; } else { // trace tb_trace_w("[url]: unknown prefix for url: %s", p); break; } // end? tb_assert_and_check_break(*p); // parse host and port for http or sock or rtsp if ( url->protocol == TB_URL_PROTOCOL_HTTP || url->protocol == TB_URL_PROTOCOL_SOCK || url->protocol == TB_URL_PROTOCOL_RTSP || url->protocol == TB_URL_PROTOCOL_SQL) { // parse host p = tb_url_parse_host(&url->host, p); tb_assert_and_check_break(p); // attempt to parse address if (tb_string_size(&url->host)) tb_ipaddr_ip_cstr_set(&url->addr, tb_string_cstr(&url->host), TB_IPADDR_FAMILY_NONE); // parse port tb_uint16_t port = 0; if (*p == ':') { // parse it p = tb_url_parse_port(&port, p + 1); tb_assert_and_check_break(p); // no port? using the default port if (!port) port = url->is_ssl? TB_HTTP_DEFAULT_PORT_SSL : TB_HTTP_DEFAULT_PORT; } else if (url->protocol == TB_URL_PROTOCOL_HTTP) port = url->is_ssl? TB_HTTP_DEFAULT_PORT_SSL : TB_HTTP_DEFAULT_PORT; else if (url->protocol != TB_URL_PROTOCOL_SQL) break; // save port tb_ipaddr_port_set(&url->addr, port); } // parse path and args if (url->protocol != TB_URL_PROTOCOL_DATA) { // parse path p = tb_url_parse_path(&url->path, p, url->protocol); tb_assert_and_check_break(p); // find args while (*p && *p != '?') p++; // parse args if (*p == '?') tb_url_parse_args(&url->args, p); } // parse data else p = tb_url_parse_data(&url->cache, p); // ok ok = tb_true; } while (0); // failed? clear the url if (!ok) tb_url_clear(url); // ok? return ok; } tb_void_t tb_url_copy(tb_url_ref_t url, tb_url_ref_t copy) { // check tb_assert_and_check_return(url && copy); // copy it url->protocol = copy->protocol; url->addr = copy->addr; url->is_ssl = copy->is_ssl; url->is_win = copy->is_win; url->pwin = copy->pwin; tb_string_strcpy(&url->host, ©->host); tb_string_strcpy(&url->path, ©->path); tb_string_strcpy(&url->args, ©->args); tb_string_strcpy(&url->cache, ©->cache); } tb_bool_t tb_url_ssl(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_false); // get ssl return url->is_ssl? tb_true : tb_false; } tb_void_t tb_url_ssl_set(tb_url_ref_t url, tb_bool_t is_ssl) { // check tb_assert_and_check_return(url); // set ssl url->is_ssl = is_ssl? 1 : 0; } tb_size_t tb_url_protocol(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, TB_URL_PROTOCOL_NONE); // get protocol return url->protocol; } tb_void_t tb_url_protocol_set(tb_url_ref_t url, tb_size_t protocol) { // check tb_assert_and_check_return(url); // set protocol url->protocol = protocol; } tb_char_t const* tb_url_protocol_cstr(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_null); // the protocols static tb_char_t const* s_protocols[] = { tb_null , "file" , "sock" , "http" , "data" , "rtsp" , "sql" }; tb_assert_and_check_return_val(url->protocol < tb_arrayn(s_protocols), tb_null); // ok return s_protocols[url->protocol]; } tb_size_t tb_url_protocol_probe(tb_char_t const* url) { // check tb_assert_and_check_return_val(url, TB_URL_PROTOCOL_NONE); // init tb_char_t const* p = url; tb_size_t protocol = TB_URL_PROTOCOL_NONE; if (!tb_strnicmp(p, "http://", 7)) protocol = TB_URL_PROTOCOL_HTTP; else if (!tb_strnicmp(p, "sock://", 7)) protocol = TB_URL_PROTOCOL_SOCK; else if (!tb_strnicmp(p, "file://", 7)) protocol = TB_URL_PROTOCOL_FILE; else if (!tb_strnicmp(p, "data://", 7)) protocol = TB_URL_PROTOCOL_DATA; else if (!tb_strnicmp(p, "https://", 8)) protocol = TB_URL_PROTOCOL_HTTP; else if (!tb_strnicmp(p, "socks://", 8)) protocol = TB_URL_PROTOCOL_SOCK; else if (!tb_strnicmp(p, "rtsp://", 7)) protocol = TB_URL_PROTOCOL_RTSP; else if (!tb_strnicmp(p, "sql://", 6)) protocol = TB_URL_PROTOCOL_SQL; else if (!tb_strnstr(p, 16, "://")) protocol = TB_URL_PROTOCOL_FILE; else { tb_trace_e("unknown protocol for url: %s", url); } // ok? return protocol; } tb_uint16_t tb_url_port(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, 0); // get port return tb_ipaddr_port(&url->addr); } tb_void_t tb_url_port_set(tb_url_ref_t url, tb_uint16_t port) { // check tb_assert_and_check_return(url); // set port tb_ipaddr_port_set(&url->addr, port); // clear url tb_string_clear(&url->cache); } tb_char_t const* tb_url_host(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_null); // get host return tb_string_size(&url->host)? tb_string_cstr(&url->host) : tb_null; } tb_void_t tb_url_host_set(tb_url_ref_t url, tb_char_t const* host) { // check tb_assert_and_check_return(url); // clear cache tb_string_clear(&url->cache); // clear address tb_ipaddr_clear(&url->addr); // parse host tb_url_parse_host(&url->host, host); // attempt to parse address tb_ipaddr_ip_cstr_set(&url->addr, tb_string_cstr(&url->host), TB_IPADDR_FAMILY_NONE); } tb_ipaddr_ref_t tb_url_addr(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_null); // get address return &(url->addr); } tb_void_t tb_url_addr_set(tb_url_ref_t url, tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return(url && addr); // changed? if (!tb_ipaddr_is_equal(&url->addr, addr)) { // set addr url->addr = *addr; // set it if the host not exists if (!tb_string_size(&url->host)) { // address => host tb_char_t data[TB_IPADDR_CSTR_MAXN]; tb_char_t const* host = tb_ipaddr_ip_cstr(addr, data, sizeof(data)); if (host) tb_string_cstrcpy(&url->host, host); // clear url tb_string_clear(&url->cache); } } } tb_char_t const* tb_url_path(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_null); // get path return tb_string_size(&url->path)? tb_string_cstr(&url->path) : tb_null; } tb_void_t tb_url_path_set(tb_url_ref_t url, tb_char_t const* path) { // check tb_assert_and_check_return(url); // clear cache tb_string_clear(&url->cache); // parse path tb_url_parse_path(&url->path, path, url->protocol); } tb_char_t const* tb_url_args(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, tb_null); // get args return tb_string_size(&url->args)? tb_string_cstr(&url->args) : tb_null; } tb_void_t tb_url_args_set(tb_url_ref_t url, tb_char_t const* args) { // check tb_assert_and_check_return(url); // clear cache tb_string_clear(&url->cache); // parse args tb_url_parse_args(&url->args, args); } tbox-1.6.7/src/tbox/network/url.h 0000664 0000000 0000000 00000014033 14142237372 0016716 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file url.h * @ingroup network * */ #ifndef TB_NETWORK_URL_H #define TB_NETWORK_URL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "ipaddr.h" #include "../string/string.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the url protocol type typedef enum __tb_url_protocol_t { TB_URL_PROTOCOL_NONE = 0 , TB_URL_PROTOCOL_FILE = 1 //!< file://... , TB_URL_PROTOCOL_SOCK = 2 //!< sock://... or socks://... , TB_URL_PROTOCOL_HTTP = 3 //!< http://... or https://... , TB_URL_PROTOCOL_DATA = 4 //!< data://... , TB_URL_PROTOCOL_RTSP = 5 //!< rtsp://... , TB_URL_PROTOCOL_SQL = 6 //!< sql://... }tb_url_protocol_t; /// the url type typedef struct __tb_url_t { // the protocol tb_uint16_t protocol: 6; // is ssl? tb_uint16_t is_ssl: 1; // is win? tb_uint16_t is_win: 1; // the windows prefix tb_uint16_t pwin: 8; // the addr tb_ipaddr_t addr; // the host tb_string_t host; // the path tb_string_t path; // the args tb_string_t args; // the url cache tb_string_t cache; }tb_url_t, *tb_url_ref_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init url * * @param url the url * * @return tb_true or tb_false */ tb_bool_t tb_url_init(tb_url_ref_t url); /*! init url from c-string * * @param url the url * @param cstr the url c-string * * @return tb_true or tb_false */ tb_bool_t tb_url_init_from_cstr(tb_url_ref_t url, tb_char_t const* cstr); /*! exit url * * @param url the url */ tb_void_t tb_url_exit(tb_url_ref_t url); /*! clear url * * @param url the url */ tb_void_t tb_url_clear(tb_url_ref_t url); /*! get the url c-string * * @param url the url * * @return the c-string */ tb_char_t const* tb_url_cstr(tb_url_ref_t url); /*! set the url c-string * * @param url the url * @param cstr the url c-string * * @return tb_true or tb_false */ tb_bool_t tb_url_cstr_set(tb_url_ref_t url, tb_char_t const* cstr); /*! copy the url * * @param url the url * @param copy the copied url */ tb_void_t tb_url_copy(tb_url_ref_t url, tb_url_ref_t copy); /*! is ssl? * * @param url the url * * @return tb_true or tb_false */ tb_bool_t tb_url_ssl(tb_url_ref_t url); /*! set ssl * * @param url the url * @param is_ssl is ssl? */ tb_void_t tb_url_ssl_set(tb_url_ref_t url, tb_bool_t is_ssl); /*! get the protocol from the url * * @param url the url * * @return the url protocol */ tb_size_t tb_url_protocol(tb_url_ref_t url); /*! set the protocol to the url * * @param url the url * @param protocol the url protocol */ tb_void_t tb_url_protocol_set(tb_url_ref_t url, tb_size_t protocol); /*! the protocol c-string * * @param url the url * * @return the url protocol c-string */ tb_char_t const* tb_url_protocol_cstr(tb_url_ref_t url); /*! probe the protocol from the url * * @param url the url * * @return the url protocol */ tb_size_t tb_url_protocol_probe(tb_char_t const* url); /*! get the port from the url * * @param url the url * * @return the url port */ tb_uint16_t tb_url_port(tb_url_ref_t url); /*! set the port to the url * * @param url the url * @param port the url port */ tb_void_t tb_url_port_set(tb_url_ref_t url, tb_uint16_t port); /*! get the address from the url * * @param url the url * * @return the url address */ tb_ipaddr_ref_t tb_url_addr(tb_url_ref_t url); /*! set the address to the url * * @param url the url * @param addr the url address */ tb_void_t tb_url_addr_set(tb_url_ref_t url, tb_ipaddr_ref_t addr); /*! get the host from the url * * @param url the url * * @return the url host */ tb_char_t const* tb_url_host(tb_url_ref_t url); /*! set the host to the url * * @param url the url * @param host the url host */ tb_void_t tb_url_host_set(tb_url_ref_t url, tb_char_t const* host); /*! get the path from the url * * @param url the url * * @return the url path */ tb_char_t const* tb_url_path(tb_url_ref_t url); /*! set the path to the url * * @param url the url * @param path the url path */ tb_void_t tb_url_path_set(tb_url_ref_t url, tb_char_t const* path); /*! get the arguments from the url * * @param url the url * * @return the url arguments */ tb_char_t const* tb_url_args(tb_url_ref_t url); /*! set the arguments to the url * * @param url the url * @param args the url arguments */ tb_void_t tb_url_args_set(tb_url_ref_t url, tb_char_t const* args); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/ 0000775 0000000 0000000 00000000000 14142237372 0015517 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/object/array.c 0000664 0000000 0000000 00000015277 14142237372 0017015 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file array.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_array" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the array type typedef struct __tb_oc_array_t { // the object base tb_object_t base; // the vector tb_vector_ref_t vector; // is increase refn? tb_bool_t incr; }tb_oc_array_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_oc_array_t* tb_oc_array_cast(tb_object_ref_t object) { // check tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_ARRAY, tb_null); // cast return (tb_oc_array_t*)object; } static tb_object_ref_t tb_oc_array_copy(tb_object_ref_t object) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return_val(array && array->vector, tb_null); // init copy tb_oc_array_t* copy = (tb_oc_array_t*)tb_oc_array_init(tb_vector_grow(array->vector), array->incr); tb_assert_and_check_return_val(copy && copy->vector, tb_null); // refn++ tb_for_all (tb_object_ref_t, item, array->vector) { if (item) tb_object_retain(item); } // copy tb_vector_copy(copy->vector, array->vector); // ok return (tb_object_ref_t)copy; } static tb_void_t tb_oc_array_exit(tb_object_ref_t object) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array); // exit vector if (array->vector) tb_vector_exit(array->vector); array->vector = tb_null; // exit it tb_free(array); } static tb_void_t tb_oc_array_clear(tb_object_ref_t object) { tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array && array->vector); // clear vector tb_vector_clear(array->vector); } static tb_oc_array_t* tb_oc_array_init_base() { // done tb_bool_t ok = tb_false; tb_oc_array_t* array = tb_null; do { // make array array = tb_malloc0_type(tb_oc_array_t); tb_assert_and_check_break(array); // init array if (!tb_object_init((tb_object_ref_t)array, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_ARRAY)) break; // init base array->base.copy = tb_oc_array_copy; array->base.exit = tb_oc_array_exit; array->base.clear = tb_oc_array_clear; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (array) tb_object_exit((tb_object_ref_t)array); array = tb_null; } // ok? return array; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_object_ref_t tb_oc_array_init(tb_size_t grow, tb_bool_t incr) { // done tb_bool_t ok = tb_false; tb_oc_array_t* array = tb_null; do { // make array array = tb_oc_array_init_base(); tb_assert_and_check_break(array); // init element tb_element_t element = tb_element_obj(); // init vector array->vector = tb_vector_init(grow, element); tb_assert_and_check_break(array->vector); // init incr array->incr = incr; // ok ok = tb_true; } while (0); // failed if (!ok) { // exit it if (array) tb_oc_array_exit((tb_object_ref_t)array); array = tb_null; } // ok? return (tb_object_ref_t)array; } tb_size_t tb_oc_array_size(tb_object_ref_t object) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return_val(array && array->vector, 0); // size return tb_vector_size(array->vector); } tb_object_ref_t tb_oc_array_item(tb_object_ref_t object, tb_size_t index) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return_val(array && array->vector, tb_null); // item return (tb_object_ref_t)tb_iterator_item(array->vector, index); } tb_iterator_ref_t tb_oc_array_itor(tb_object_ref_t object) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return_val(array, tb_null); // iterator return (tb_iterator_ref_t)array->vector; } tb_void_t tb_oc_array_remove(tb_object_ref_t object, tb_size_t index) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array && array->vector); // remove tb_vector_remove(array->vector, index); } tb_void_t tb_oc_array_append(tb_object_ref_t object, tb_object_ref_t item) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array && array->vector && item); // insert tb_vector_insert_tail(array->vector, item); // refn-- if (!array->incr) tb_object_exit(item); } tb_void_t tb_oc_array_insert(tb_object_ref_t object, tb_size_t index, tb_object_ref_t item) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array && array->vector && item); // insert tb_vector_insert_prev(array->vector, index, item); // refn-- if (!array->incr) tb_object_exit(item); } tb_void_t tb_oc_array_replace(tb_object_ref_t object, tb_size_t index, tb_object_ref_t item) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array && array->vector && item); // replace tb_vector_replace(array->vector, index, item); // refn-- if (!array->incr) tb_object_exit(item); } tb_void_t tb_oc_array_incr(tb_object_ref_t object, tb_bool_t incr) { // check tb_oc_array_t* array = tb_oc_array_cast(object); tb_assert_and_check_return(array); array->incr = incr; } tbox-1.6.7/src/tbox/object/array.h 0000664 0000000 0000000 00000006256 14142237372 0017017 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file array.h * @ingroup object * */ #ifndef TB_OBJECT_ARRAY_H #define TB_OBJECT_ARRAY_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init array * * @param grow the array grow * @param incr is increase refn? * * @return the array object */ tb_object_ref_t tb_oc_array_init(tb_size_t grow, tb_bool_t incr); /*! the array size * * @param array the array object * * @return the array size */ tb_size_t tb_oc_array_size(tb_object_ref_t array); /*! the array item at index * * @param array the array object * @param index the array index * * @return the array item */ tb_object_ref_t tb_oc_array_item(tb_object_ref_t array, tb_size_t index); /*! set the array incr * * @param array the array object * @param incr is increase refn? */ tb_void_t tb_oc_array_incr(tb_object_ref_t array, tb_bool_t incr); /*! the array iterator * * @param array the array object * * @return the array iterator * * @code * tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(array)) * { * if (item) * { * // ... * } * } * @endcode */ tb_iterator_ref_t tb_oc_array_itor(tb_object_ref_t array); /*! remove the item from index * * @param array the array object * @param index the array index */ tb_void_t tb_oc_array_remove(tb_object_ref_t array, tb_size_t index); /*! append item to array * * @param array the array object * @param item the array item */ tb_void_t tb_oc_array_append(tb_object_ref_t array, tb_object_ref_t item); /*! insert item to array * * @param array the array object * @param index the array index * @param item the array item */ tb_void_t tb_oc_array_insert(tb_object_ref_t array, tb_size_t index, tb_object_ref_t item); /*! replace item to array * * @param array the array object * @param index the array index * @param item the array item */ tb_void_t tb_oc_array_replace(tb_object_ref_t array, tb_size_t index, tb_object_ref_t item); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/boolean.c 0000664 0000000 0000000 00000006112 14142237372 0017302 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file boolean.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_boolean" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the boolean type typedef struct __tb_oc_boolean_t { // the object base tb_object_t base; // the boolean value tb_bool_t value; }tb_oc_boolean_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_oc_boolean_t* tb_oc_boolean_cast(tb_object_ref_t object) { // check tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_BOOLEAN, tb_null); // cast return (tb_oc_boolean_t*)object; } static tb_object_ref_t tb_oc_boolean_copy(tb_object_ref_t object) { // check tb_oc_boolean_t* boolean = (tb_oc_boolean_t*)object; tb_assert_and_check_return_val(boolean, tb_null); // copy return object; } /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // true static tb_oc_boolean_t const g_boolean_true = { { TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON , TB_OBJECT_TYPE_BOOLEAN , 1 , tb_null , tb_oc_boolean_copy , tb_null , tb_null } , tb_true }; // false static tb_oc_boolean_t const g_boolean_false = { { TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON , TB_OBJECT_TYPE_BOOLEAN , 1 , tb_null , tb_oc_boolean_copy , tb_null , tb_null } , tb_false }; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_object_ref_t tb_oc_boolean_init(tb_bool_t value) { return value? tb_oc_boolean_true() : tb_oc_boolean_false(); } tb_object_ref_t tb_oc_boolean_true() { return (tb_object_ref_t)&g_boolean_true; } tb_object_ref_t tb_oc_boolean_false() { return (tb_object_ref_t)&g_boolean_false; } tb_bool_t tb_oc_boolean_bool(tb_object_ref_t object) { tb_oc_boolean_t* boolean = tb_oc_boolean_cast(object); tb_assert_and_check_return_val(boolean, tb_false); return boolean->value; } tbox-1.6.7/src/tbox/object/boolean.h 0000664 0000000 0000000 00000003514 14142237372 0017312 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file boolean.h * @ingroup object * */ #ifndef TB_OBJECT_BOOLEAN_H #define TB_OBJECT_BOOLEAN_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init boolean * * @param value the value * * @return the boolean object */ tb_object_ref_t tb_oc_boolean_init(tb_bool_t value); /*! the boolean value: true * * @return the boolean object */ tb_object_ref_t tb_oc_boolean_true(tb_noarg_t); /*! the boolean value: false * * @return the boolean object */ tb_object_ref_t tb_oc_boolean_false(tb_noarg_t); /*! the boolean value * * @param boolean the boolean object * * @return tb_true or tb_false */ tb_bool_t tb_oc_boolean_bool(tb_object_ref_t boolean); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/data.c 0000664 0000000 0000000 00000015001 14142237372 0016571 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file data.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_data" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" #include "../utils/utils.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the data type typedef struct __tb_oc_data_t { // the object base tb_object_t base; // the data buffer tb_buffer_t buffer; }tb_oc_data_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_oc_data_t* tb_oc_data_cast(tb_object_ref_t object) { // check tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DATA, tb_null); // cast return (tb_oc_data_t*)object; } static tb_object_ref_t tb_oc_data_copy(tb_object_ref_t object) { return tb_oc_data_init_from_data(tb_oc_data_getp(object), tb_oc_data_size(object)); } static tb_void_t tb_oc_data_exit(tb_object_ref_t object) { tb_oc_data_t* data = tb_oc_data_cast(object); if (data) { tb_buffer_exit(&data->buffer); tb_free(data); } } static tb_void_t tb_oc_data_clear(tb_object_ref_t object) { tb_oc_data_t* data = tb_oc_data_cast(object); if (data) tb_buffer_clear(&data->buffer); } static tb_oc_data_t* tb_oc_data_init_base() { // done tb_bool_t ok = tb_false; tb_oc_data_t* data = tb_null; do { // make data data = tb_malloc0_type(tb_oc_data_t); tb_assert_and_check_break(data); // init data if (!tb_object_init((tb_object_ref_t)data, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DATA)) break; // init base data->base.copy = tb_oc_data_copy; data->base.exit = tb_oc_data_exit; data->base.clear = tb_oc_data_clear; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (data) tb_object_exit((tb_object_ref_t)data); data = tb_null; } // ok? return data; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_object_ref_t tb_oc_data_init_from_url(tb_char_t const* url) { // check tb_assert_and_check_return_val(url, tb_null); // init stream tb_stream_ref_t stream = tb_stream_init_from_url(url); tb_assert_and_check_return_val(stream, tb_null); // make stream tb_object_ref_t object = tb_null; if (tb_stream_open(stream)) { // read all data tb_size_t size = 0; tb_byte_t* data = (tb_byte_t*)tb_stream_bread_all(stream, tb_false, &size); if (data) { // make object object = tb_oc_data_init_from_data(data, size); // exit data tb_free(data); } // exit stream tb_stream_exit(stream); } // ok? return object; } tb_object_ref_t tb_oc_data_init_from_data(tb_pointer_t addr, tb_size_t size) { // make tb_oc_data_t* data = tb_oc_data_init_base(); tb_assert_and_check_return_val(data, tb_null); // init buffer if (!tb_buffer_init(&data->buffer)) { tb_oc_data_exit((tb_object_ref_t)data); return tb_null; } // copy data if (addr && size) tb_buffer_memncpy(&data->buffer, (tb_byte_t const*)addr, size); // ok return (tb_object_ref_t)data; } tb_object_ref_t tb_oc_data_init_from_buffer(tb_buffer_ref_t pbuf) { // make tb_oc_data_t* data = tb_oc_data_init_base(); tb_assert_and_check_return_val(data, tb_null); // init buffer if (!tb_buffer_init(&data->buffer)) { tb_oc_data_exit((tb_object_ref_t)data); return tb_null; } // copy data if (pbuf) tb_buffer_memcpy(&data->buffer, pbuf); // ok return (tb_object_ref_t)data; } tb_pointer_t tb_oc_data_getp(tb_object_ref_t object) { // check tb_oc_data_t* data = tb_oc_data_cast(object); tb_assert_and_check_return_val(data, tb_null); // data return tb_buffer_data(&data->buffer); } tb_bool_t tb_oc_data_setp(tb_object_ref_t object, tb_pointer_t addr, tb_size_t size) { // check tb_oc_data_t* data = tb_oc_data_cast(object); tb_assert_and_check_return_val(data && addr, tb_false); // data tb_buffer_memncpy(&data->buffer, (tb_byte_t const*)addr, size); // ok return tb_true; } tb_size_t tb_oc_data_size(tb_object_ref_t object) { // check tb_oc_data_t* data = tb_oc_data_cast(object); tb_assert_and_check_return_val(data, 0); // data return tb_buffer_size(&data->buffer); } tb_buffer_ref_t tb_oc_data_buffer(tb_object_ref_t object) { // check tb_oc_data_t* data = tb_oc_data_cast(object); tb_assert_and_check_return_val(data, tb_null); // buffer return &data->buffer; } tb_bool_t tb_oc_data_writ_to_url(tb_object_ref_t object, tb_char_t const* url) { // check tb_oc_data_t* data = tb_oc_data_cast(object); tb_assert_and_check_return_val(data && tb_oc_data_getp((tb_object_ref_t)data) && url, tb_false); // make stream tb_stream_ref_t stream = tb_stream_init_from_url(url); tb_assert_and_check_return_val(stream, tb_false); // ctrl if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE) tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_WO | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC); // open stream tb_bool_t ok = tb_false; if (tb_stream_open(stream)) { // writ stream if (tb_stream_bwrit(stream, (tb_byte_t const*)tb_oc_data_getp((tb_object_ref_t)data), tb_oc_data_size((tb_object_ref_t)data))) ok = tb_true; } // exit stream tb_stream_exit(stream); // ok? return ok; } tbox-1.6.7/src/tbox/object/data.h 0000664 0000000 0000000 00000005324 14142237372 0016605 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file data.h * @ingroup object * */ #ifndef TB_OBJECT_DATA_H #define TB_OBJECT_DATA_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init data from url * * @param url the url * * @return the data object */ tb_object_ref_t tb_oc_data_init_from_url(tb_char_t const* url); /*! init data from data * * @param data the data * @param size the size * * @return the data object */ tb_object_ref_t tb_oc_data_init_from_data(tb_pointer_t data, tb_size_t size); /*! init data from buffer * * @param buffer the buffer * * @return the data object */ tb_object_ref_t tb_oc_data_init_from_buffer(tb_buffer_ref_t buffer); /*! get the data * * @param data the data object * * @return the data address */ tb_pointer_t tb_oc_data_getp(tb_object_ref_t data); /*! set the data * * @param data the data object * @param addr the data address * @param size the data size * * @return tb_true or tb_false */ tb_bool_t tb_oc_data_setp(tb_object_ref_t data, tb_pointer_t addr, tb_size_t size); /*! the data size * * @param data the data object * * @return the data size */ tb_size_t tb_oc_data_size(tb_object_ref_t data); /*! the data buffer * * @param data the data object * * @return the data buffer */ tb_buffer_ref_t tb_oc_data_buffer(tb_object_ref_t data); /*! writ data to url * * @param data the data object * * @return tb_true or tb_false */ tb_bool_t tb_oc_data_writ_to_url(tb_object_ref_t data, tb_char_t const* url); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/date.c 0000664 0000000 0000000 00000010100 14142237372 0016570 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file date.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_date" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" #include "../utils/utils.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the date type typedef struct __tb_oc_date_t { // the object base tb_object_t base; // the date time tb_time_t time; }tb_oc_date_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_oc_date_t* tb_oc_date_cast(tb_object_ref_t object) { // check tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DATE, tb_null); // cast return (tb_oc_date_t*)object; } static tb_object_ref_t tb_oc_date_copy(tb_object_ref_t object) { return tb_oc_date_init_from_time(tb_oc_date_time(object)); } static tb_void_t tb_oc_date_exit(tb_object_ref_t object) { if (object) tb_free(object); } static tb_void_t tb_oc_date_clear(tb_object_ref_t object) { tb_oc_date_t* date = tb_oc_date_cast(object); if (date) date->time = 0; } static tb_oc_date_t* tb_oc_date_init_base() { // done tb_bool_t ok = tb_false; tb_oc_date_t* date = tb_null; do { // make date date = tb_malloc0_type(tb_oc_date_t); tb_assert_and_check_break(date); // init date if (!tb_object_init((tb_object_ref_t)date, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DATE)) break; // init base date->base.copy = tb_oc_date_copy; date->base.exit = tb_oc_date_exit; date->base.clear = tb_oc_date_clear; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (date) tb_object_exit((tb_object_ref_t)date); date = tb_null; } // ok? return date; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_object_ref_t tb_oc_date_init_from_now() { // make tb_oc_date_t* date = tb_oc_date_init_base(); tb_assert_and_check_return_val(date, tb_null); // init time date->time = tb_time(); // ok return (tb_object_ref_t)date; } tb_object_ref_t tb_oc_date_init_from_time(tb_time_t time) { // make tb_oc_date_t* date = tb_oc_date_init_base(); tb_assert_and_check_return_val(date, tb_null); // init time if (time > 0) date->time = time; // ok return (tb_object_ref_t)date; } tb_time_t tb_oc_date_time(tb_object_ref_t object) { // check tb_oc_date_t* date = tb_oc_date_cast(object); tb_assert_and_check_return_val(date, -1); // time return date->time; } tb_bool_t tb_oc_date_time_set(tb_object_ref_t object, tb_time_t time) { // check tb_oc_date_t* date = tb_oc_date_cast(object); tb_assert_and_check_return_val(date, tb_false); // set time date->time = time; // ok return tb_true; } tb_bool_t tb_oc_date_time_set_now(tb_object_ref_t object) { // check tb_oc_date_t* date = tb_oc_date_cast(object); tb_assert_and_check_return_val(date, tb_false); // set time date->time = tb_time(); // ok return tb_true; } tbox-1.6.7/src/tbox/object/date.h 0000664 0000000 0000000 00000004120 14142237372 0016602 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file date.h * @ingroup object * */ #ifndef TB_OBJECT_DATE_H #define TB_OBJECT_DATE_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init date from now * * @return the date object */ tb_object_ref_t tb_oc_date_init_from_now(tb_noarg_t); /*! init date from time * * @param time the date time * * @return the date object */ tb_object_ref_t tb_oc_date_init_from_time(tb_time_t time); /*! the date time * * @param date the date object * * @return the date time */ tb_time_t tb_oc_date_time(tb_object_ref_t date); /*! set the date time * * @param date the date object * @param time the date time * * @return tb_true or tb_false */ tb_bool_t tb_oc_date_time_set(tb_object_ref_t date, tb_time_t time); /*! set the date time for now * * @param date the date object * * @return tb_true or tb_false */ tb_bool_t tb_oc_date_time_set_now(tb_object_ref_t date); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/dictionary.c 0000664 0000000 0000000 00000016200 14142237372 0020027 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file dictionary.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_dictionary" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" #include "../string/string.h" #include "../algorithm/algorithm.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ #ifdef __tb_small__ # define TB_OC_DICTIONARY_SIZE_DEFAULT TB_OC_DICTIONARY_SIZE_MICRO #else # define TB_OC_DICTIONARY_SIZE_DEFAULT TB_OC_DICTIONARY_SIZE_SMALL #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the dictionary type typedef struct __tb_oc_dictionary_t { // the object base tb_object_t base; // the capacity size tb_size_t size; // the object hash tb_hash_map_ref_t hash; // increase refn? tb_bool_t incr; }tb_oc_dictionary_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_oc_dictionary_t* tb_oc_dictionary_cast(tb_object_ref_t object) { // check tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DICTIONARY, tb_null); // cast return (tb_oc_dictionary_t*)object; } static tb_object_ref_t tb_oc_dictionary_copy(tb_object_ref_t object) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return_val(dictionary, tb_null); // init copy tb_oc_dictionary_t* copy = (tb_oc_dictionary_t*)tb_oc_dictionary_init(dictionary->size, dictionary->incr); tb_assert_and_check_return_val(copy, tb_null); // walk copy tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor((tb_object_ref_t)dictionary)) { if (item && item->key) { // refn++ if (item->val) tb_object_retain(item->val); // copy tb_oc_dictionary_insert((tb_object_ref_t)copy, item->key, item->val); } } // ok return (tb_object_ref_t)copy; } static tb_void_t tb_oc_dictionary_exit(tb_object_ref_t object) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return(dictionary); // exit hash if (dictionary->hash) tb_hash_map_exit(dictionary->hash); dictionary->hash = tb_null; // exit it tb_free(dictionary); } static tb_void_t tb_oc_dictionary_clear(tb_object_ref_t object) { tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return(dictionary); // clear if (dictionary->hash) tb_hash_map_clear(dictionary->hash); } static tb_oc_dictionary_t* tb_oc_dictionary_init_base() { // done tb_bool_t ok = tb_false; tb_oc_dictionary_t* dictionary = tb_null; do { // make dictionary dictionary = tb_malloc0_type(tb_oc_dictionary_t); tb_assert_and_check_break(dictionary); // init dictionary if (!tb_object_init((tb_object_ref_t)dictionary, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DICTIONARY)) break; // init base dictionary->base.copy = tb_oc_dictionary_copy; dictionary->base.exit = tb_oc_dictionary_exit; dictionary->base.clear = tb_oc_dictionary_clear; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (dictionary) tb_object_exit((tb_object_ref_t)dictionary); dictionary = tb_null; } // ok? return dictionary; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_object_ref_t tb_oc_dictionary_init(tb_size_t size, tb_bool_t incr) { // done tb_bool_t ok = tb_false; tb_oc_dictionary_t* dictionary = tb_null; do { // make dictionary dictionary = tb_oc_dictionary_init_base(); tb_assert_and_check_break(dictionary); // using the default size if (!size) size = TB_OC_DICTIONARY_SIZE_DEFAULT; // init dictionary->size = size; dictionary->incr = incr; // init hash dictionary->hash = tb_hash_map_init(size, tb_element_str(tb_true), tb_element_obj()); tb_assert_and_check_break(dictionary->hash); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (dictionary) tb_oc_dictionary_exit((tb_object_ref_t)dictionary); dictionary = tb_null; } // ok? return (tb_object_ref_t)dictionary; } tb_size_t tb_oc_dictionary_size(tb_object_ref_t object) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return_val(dictionary && dictionary->hash, 0); // size return tb_hash_map_size(dictionary->hash); } tb_iterator_ref_t tb_oc_dictionary_itor(tb_object_ref_t object) { tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return_val(dictionary, tb_null); // iterator return (tb_iterator_ref_t)dictionary->hash; } tb_object_ref_t tb_oc_dictionary_value(tb_object_ref_t object, tb_char_t const* key) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return_val(dictionary && dictionary->hash && key, tb_null); // value return (tb_object_ref_t)tb_hash_map_get(dictionary->hash, key); } tb_void_t tb_oc_dictionary_remove(tb_object_ref_t object, tb_char_t const* key) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return(dictionary && dictionary->hash && key); // del return tb_hash_map_remove(dictionary->hash, key); } tb_void_t tb_oc_dictionary_insert(tb_object_ref_t object, tb_char_t const* key, tb_object_ref_t val) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return(dictionary && dictionary->hash && key && val); // add tb_hash_map_insert(dictionary->hash, key, val); // refn-- if (!dictionary->incr) tb_object_exit(val); } tb_void_t tb_oc_dictionary_incr(tb_object_ref_t object, tb_bool_t incr) { // check tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); tb_assert_and_check_return(dictionary); dictionary->incr = incr; } tbox-1.6.7/src/tbox/object/dictionary.h 0000664 0000000 0000000 00000010565 14142237372 0020044 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file dictionary.h * @ingroup object * */ #ifndef TB_OBJECT_DICTIONARY_H #define TB_OBJECT_DICTIONARY_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ #define TB_OC_DICTIONARY_SIZE_MICRO (64) #define TB_OC_DICTIONARY_SIZE_SMALL (256) #define TB_OC_DICTIONARY_SIZE_LARGE (65536) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the dictionary item type typedef struct __tb_oc_dictionary_item_t { /// the key tb_char_t const* key; /// the value tb_object_ref_t val; }tb_oc_dictionary_item_t; /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init dictionary * * @code // init dictionary // {"key1": "hello", "key2" :"world", "key3": 12345, "key4": true} tb_object_ref_t dict = tb_oc_dictionary_init(0, tb_false); if (dict) { // key1 => hello tb_oc_dictionary_insert(dict, "key1", tb_oc_string_init_from_cstr("hello")); // key2 => world tb_oc_dictionary_insert(dict, "key2", tb_oc_string_init_from_cstr("world")); // key3 => 12345 tb_oc_dictionary_insert(dict, "key3", tb_oc_number_init_from_sint32(12345)); // key4 => true tb_oc_dictionary_insert(dict, "key4", tb_oc_boolean_true()); // exit dictionary tb_object_exit(dict); } * @endcode * * @param size the dictionary size, using the default size if be zero * @param incr is increase refn? * * @return the dictionary object */ tb_object_ref_t tb_oc_dictionary_init(tb_size_t size, tb_bool_t incr); /*! the dictionary size * * @param dictionary the dictionary object * * @return the dictionary size */ tb_size_t tb_oc_dictionary_size(tb_object_ref_t dictionary); /*! set the dictionary incr * * @param dictionary the dictionary object * @param incr is increase refn? */ tb_void_t tb_oc_dictionary_incr(tb_object_ref_t dictionary, tb_bool_t incr); /*! the dictionary iterator * * @param dictionary the dictionary object * * @return the dictionary iterator * * @code tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(dictionary)) { if (item) { tb_char_t const* key = item->key; tb_object_ref_t val = item->val; // ... } } * @endcode */ tb_iterator_ref_t tb_oc_dictionary_itor(tb_object_ref_t dictionary); /*! get the dictionary value * * @param dictionary the dictionary object * @param key the key * * @return the dictionary value */ tb_object_ref_t tb_oc_dictionary_value(tb_object_ref_t dictionary, tb_char_t const* key); /*! insert dictionary item * * @param dictionary the dictionary object * @param key the key * @param val the value */ tb_void_t tb_oc_dictionary_insert(tb_object_ref_t dictionary, tb_char_t const* key, tb_object_ref_t val); /*! remove dictionary item * * @param dictionary the dictionary object * @param key the key */ tb_void_t tb_oc_dictionary_remove(tb_object_ref_t dictionary, tb_char_t const* key); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/ 0000775 0000000 0000000 00000000000 14142237372 0016460 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/object/impl/impl.h 0000664 0000000 0000000 00000001701 14142237372 0017571 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file impl.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_H #define TB_OBJECT_IMPL_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" #include "reader/reader.h" #include "writer/writer.h" #endif tbox-1.6.7/src/tbox/object/impl/object.c 0000664 0000000 0000000 00000005567 14142237372 0020107 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file object.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "object" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "object.h" #include "reader/reader.h" #include "writer/writer.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_object_init_env() { // register reader if (!tb_oc_reader_set(TB_OBJECT_FORMAT_BIN, tb_oc_bin_reader())) return tb_false; if (!tb_oc_reader_set(TB_OBJECT_FORMAT_JSON, tb_oc_json_reader())) return tb_false; if (!tb_oc_reader_set(TB_OBJECT_FORMAT_BPLIST, tb_oc_bplist_reader())) return tb_false; // register writer if (!tb_oc_writer_set(TB_OBJECT_FORMAT_BIN, tb_oc_bin_writer())) return tb_false; if (!tb_oc_writer_set(TB_OBJECT_FORMAT_JSON, tb_oc_json_writer())) return tb_false; if (!tb_oc_writer_set(TB_OBJECT_FORMAT_BPLIST, tb_oc_bplist_writer())) return tb_false; // register reader and writer for xml #ifdef TB_CONFIG_MODULE_HAVE_XML if (!tb_oc_reader_set(TB_OBJECT_FORMAT_XML, tb_oc_xml_reader())) return tb_false; if (!tb_oc_writer_set(TB_OBJECT_FORMAT_XML, tb_oc_xml_writer())) return tb_false; if (!tb_oc_reader_set(TB_OBJECT_FORMAT_XPLIST, tb_oc_xplist_reader())) return tb_false; if (!tb_oc_writer_set(TB_OBJECT_FORMAT_XPLIST, tb_oc_xplist_writer())) return tb_false; #endif // ok return tb_true; } tb_void_t tb_object_exit_env() { // remove reader tb_oc_reader_remove(TB_OBJECT_FORMAT_BIN); tb_oc_reader_remove(TB_OBJECT_FORMAT_JSON); tb_oc_reader_remove(TB_OBJECT_FORMAT_BPLIST); // remove writer tb_oc_writer_remove(TB_OBJECT_FORMAT_BIN); tb_oc_writer_remove(TB_OBJECT_FORMAT_JSON); tb_oc_writer_remove(TB_OBJECT_FORMAT_BPLIST); // remove reader and writer for xml #ifdef TB_CONFIG_MODULE_HAVE_XML tb_oc_reader_remove(TB_OBJECT_FORMAT_XML); tb_oc_writer_remove(TB_OBJECT_FORMAT_XML); tb_oc_reader_remove(TB_OBJECT_FORMAT_XPLIST); tb_oc_writer_remove(TB_OBJECT_FORMAT_XPLIST); #endif } tbox-1.6.7/src/tbox/object/impl/object.h 0000664 0000000 0000000 00000002726 14142237372 0020106 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file object.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_OBJECT_H #define TB_OBJECT_IMPL_OBJECT_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /* init object environment * * @return tb_true or tb_false */ tb_bool_t tb_object_init_env(tb_noarg_t); // exit object environment tb_void_t tb_object_exit_env(tb_noarg_t); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/prefix.h 0000664 0000000 0000000 00000004115 14142237372 0020127 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_PREFIX_H #define TB_OBJECT_IMPL_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" #include "../object.h" #include "../../stream/stream.h" #include "../../charset/charset.h" #include "../../container/container.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // need bytes #define tb_object_need_bytes(x) \ (((tb_uint64_t)(x)) < (1ull << 8) ? 1 : \ (((tb_uint64_t)(x)) < (1ull << 16) ? 2 : \ (((tb_uint64_t)(x)) < (1ull << 32) ? 4 : 8))) /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the object reader type typedef struct __tb_oc_reader_t { /// the hooker tb_hash_map_ref_t hooker; /// probe format tb_size_t (*probe)(tb_stream_ref_t stream); /// read it tb_object_ref_t (*read)(tb_stream_ref_t stream); }tb_oc_reader_t; // the object writer type typedef struct __tb_oc_writer_t { /// the hooker tb_hash_map_ref_t hooker; /// writ it tb_long_t (*writ)(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate); }tb_oc_writer_t; #endif tbox-1.6.7/src/tbox/object/impl/reader/ 0000775 0000000 0000000 00000000000 14142237372 0017722 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/object/impl/reader/bin.c 0000664 0000000 0000000 00000040016 14142237372 0020637 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file bin.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_reader_bin" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "bin.h" #include "reader.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the array grow #ifdef __tb_small__ # define TB_OC_BIN_READER_ARRAY_GROW (64) #else # define TB_OC_BIN_READER_ARRAY_GROW (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_oc_bin_reader_func_null(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // ok return tb_oc_null_init(); } static tb_object_ref_t tb_oc_bin_reader_func_date(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // ok return tb_oc_date_init_from_time((tb_time_t)size); } static tb_object_ref_t tb_oc_bin_reader_func_data(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // empty? if (!size) return tb_oc_data_init_from_data(tb_null, 0); // make data tb_char_t* data = tb_malloc0_cstr((tb_size_t)size); tb_assert_and_check_return_val(data, tb_null); // read data if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size)) { tb_free(data); return tb_null; } // decode data { tb_byte_t* pb = (tb_byte_t*)data; tb_byte_t* pe = (tb_byte_t*)data + size; tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff)); for (; pb < pe; pb++, xb++) *pb ^= xb; } // make the data object tb_object_ref_t object = tb_oc_data_init_from_data(data, (tb_size_t)size); // exit data tb_free(data); // ok? return object; } static tb_object_ref_t tb_oc_bin_reader_func_array(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // empty? if (!size) return tb_oc_array_init(TB_OC_BIN_READER_ARRAY_GROW, tb_false); // init array tb_object_ref_t array = tb_oc_array_init(TB_OC_BIN_READER_ARRAY_GROW, tb_false); tb_assert_and_check_return_val(array, tb_null); // walk tb_size_t i = 0; tb_size_t n = (tb_size_t)size; for (i = 0; i < n; i++) { // the type & size tb_size_t type = 0; tb_uint64_t size = 0; tb_oc_reader_bin_type_size(reader->stream, &type, &size); // trace tb_trace_d("item: type: %lu, size: %llu", type, size); // is index? tb_object_ref_t item = tb_null; if (!type) { // the object index tb_size_t index = (tb_size_t)size; // check tb_assert_and_check_break(index < tb_vector_size(reader->list)); // the item item = (tb_object_ref_t)tb_iterator_item(reader->list, index); // refn++ if (item) tb_object_retain(item); } else { // the reader func tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); tb_assert_and_check_break(func); // read it item = func(reader, type, size); // save it tb_vector_insert_tail(reader->list, item); } // check tb_assert_and_check_break(item); // append item tb_oc_array_append(array, item); } // failed? if (i != n) { if (array) tb_object_exit(array); array = tb_null; } // ok? return array; } static tb_object_ref_t tb_oc_bin_reader_func_string(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // empty? if (!size) return tb_oc_string_init_from_cstr(tb_null); // make data tb_char_t* data = tb_malloc0_cstr((tb_size_t)size + 1); tb_assert_and_check_return_val(data, tb_null); // read data if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size)) { tb_free(data); return tb_null; } // decode string { tb_byte_t* pb = (tb_byte_t*)data; tb_byte_t* pe = (tb_byte_t*)data + size; tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff)); for (; pb < pe; pb++, xb++) *pb ^= xb; } // make string tb_object_ref_t string = tb_oc_string_init_from_cstr(data); // exit data tb_free(data); // ok? return string; } static tb_object_ref_t tb_oc_bin_reader_func_number(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // the number type tb_size_t number_type = (tb_size_t)size; // read number tb_value_t value; tb_object_ref_t number = tb_null; switch (number_type) { case TB_OC_NUMBER_TYPE_UINT64: { // read and init number if (tb_stream_bread_u64_be(reader->stream, &value.u64)) number = tb_oc_number_init_from_uint64(value.u64); } break; case TB_OC_NUMBER_TYPE_SINT64: { // read and init number if (tb_stream_bread_s64_be(reader->stream, &value.s64)) number = tb_oc_number_init_from_sint64(value.s64); } break; case TB_OC_NUMBER_TYPE_UINT32: { // read and init number if (tb_stream_bread_u32_be(reader->stream, &value.u32)) number = tb_oc_number_init_from_uint32(value.u32); } break; case TB_OC_NUMBER_TYPE_SINT32: { // read and init number if (tb_stream_bread_s32_be(reader->stream, &value.s32)) number = tb_oc_number_init_from_sint32(value.s32); } break; case TB_OC_NUMBER_TYPE_UINT16: { // read and init number if (tb_stream_bread_u16_be(reader->stream, &value.u16)) number = tb_oc_number_init_from_uint16(value.u16); } break; case TB_OC_NUMBER_TYPE_SINT16: { // read and init number if (tb_stream_bread_s16_be(reader->stream, &value.s16)) number = tb_oc_number_init_from_sint16(value.s16); } break; case TB_OC_NUMBER_TYPE_UINT8: { // read and init number if (tb_stream_bread_u8(reader->stream, &value.u8)) number = tb_oc_number_init_from_uint8(value.u8); } break; case TB_OC_NUMBER_TYPE_SINT8: { // read and init number if (tb_stream_bread_s8(reader->stream, &value.s8)) number = tb_oc_number_init_from_sint8(value.s8); } break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OC_NUMBER_TYPE_FLOAT: { // read and init number if (tb_stream_bread_float_be(reader->stream, &value.f)) number = tb_oc_number_init_from_float(value.f); } break; case TB_OC_NUMBER_TYPE_DOUBLE: { // read and init number if (tb_stream_bread_double_bbe(reader->stream, &value.d)) number = tb_oc_number_init_from_double(value.d); } break; #endif default: tb_assert_and_check_return_val(0, tb_null); break; } // ok? return number; } static tb_object_ref_t tb_oc_bin_reader_func_boolean(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // ok? return tb_oc_boolean_init(size? tb_true : tb_false); } static tb_object_ref_t tb_oc_bin_reader_func_dictionary(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) { // check tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); // empty? if (!size) return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); // init dictionary tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); tb_assert_and_check_return_val(dictionary, tb_null); // walk tb_size_t i = 0; tb_size_t n = (tb_size_t)size; for (i = 0; i < n; i++) { // read key tb_object_ref_t key = tb_null; do { // the type & size tb_size_t type = 0; tb_uint64_t size = 0; tb_oc_reader_bin_type_size(reader->stream, &type, &size); // trace tb_trace_d("key: type: %lu, size: %llu", type, size); // is index? if (!type) { // the object index tb_size_t index = (tb_size_t)size; // check tb_assert_and_check_break(index < tb_vector_size(reader->list)); // the item key = (tb_object_ref_t)tb_iterator_item(reader->list, index); } else { // check tb_assert_and_check_break(type == TB_OBJECT_TYPE_STRING); // the reader func tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); tb_assert_and_check_break(func); // read it key = func(reader, type, size); tb_assert_and_check_break(key); // save it tb_vector_insert_tail(reader->list, key); // refn-- tb_object_exit(key); } } while (0); // check tb_assert_and_check_break(key && tb_object_type(key) == TB_OBJECT_TYPE_STRING); tb_assert_and_check_break(tb_oc_string_size(key) && tb_oc_string_cstr(key)); // read val tb_object_ref_t val = tb_null; do { // the type & size tb_size_t type = 0; tb_uint64_t size = 0; tb_oc_reader_bin_type_size(reader->stream, &type, &size); // trace tb_trace_d("val: type: %lu, size: %llu", type, size); // is index? if (!type) { // the object index tb_size_t index = (tb_size_t)size; // check tb_assert_and_check_break(index < tb_vector_size(reader->list)); // the item val = (tb_object_ref_t)tb_iterator_item(reader->list, index); // refn++ if (val) tb_object_retain(val); } else { // the reader func tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); tb_assert_and_check_break(func); // read it val = func(reader, type, size); // save it if (val) tb_vector_insert_tail(reader->list, val); } } while (0); // check tb_assert_and_check_break(val); // set key => val tb_oc_dictionary_insert(dictionary, tb_oc_string_cstr(key), val); } // failed? if (i != n) { if (dictionary) tb_object_exit(dictionary); dictionary = tb_null; } // ok? return dictionary; } static tb_object_ref_t tb_oc_bin_reader_done(tb_stream_ref_t stream) { // read bin header tb_byte_t data[32] = {0}; if (!tb_stream_bread(stream, data, 5)) return tb_null; // check if (tb_strnicmp((tb_char_t const*)data, "tbo00", 5)) return tb_null; // init tb_object_ref_t object = tb_null; tb_oc_bin_reader_t reader = {0}; // init reader reader.stream = stream; reader.list = tb_vector_init(256, tb_element_obj()); tb_assert_and_check_return_val(reader.list, tb_null); // the type & size tb_size_t type = 0; tb_uint64_t size = 0; tb_oc_reader_bin_type_size(stream, &type, &size); // trace tb_trace_d("root: type: %lu, size: %llu", type, size); // the func tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); // check tb_assert(func); // read it if (func) object = func(&reader, type, size); // exit the list if (reader.list) tb_vector_exit(reader.list); // ok? return object; } static tb_size_t tb_oc_bin_reader_probe(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, 0); // need it tb_byte_t* p = tb_null; if (!tb_stream_need(stream, &p, 3)) return 0; tb_assert_and_check_return_val(p, 0); // ok? return !tb_strnicmp((tb_char_t const*)p, "tbo", 3)? 80 : 0; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_oc_reader_t* tb_oc_bin_reader() { // the reader static tb_oc_reader_t s_reader = {0}; // init reader s_reader.read = tb_oc_bin_reader_done; s_reader.probe = tb_oc_bin_reader_probe; // init hooker s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); tb_assert_and_check_return_val(s_reader.hooker, tb_null); // hook reader tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_bin_reader_func_null); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bin_reader_func_date); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bin_reader_func_data); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bin_reader_func_array); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bin_reader_func_string); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bin_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bin_reader_func_boolean); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bin_reader_func_dictionary); // ok return &s_reader; } tb_bool_t tb_oc_bin_reader_hook(tb_size_t type, tb_oc_bin_reader_func_t func) { // check tb_assert_and_check_return_val(type && func, tb_false); // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BIN); tb_assert_and_check_return_val(reader && reader->hooker, tb_false); // hook it tb_hash_map_insert(reader->hooker, (tb_pointer_t)type, func); // ok return tb_true; } tb_oc_bin_reader_func_t tb_oc_bin_reader_func(tb_size_t type) { // check tb_assert_and_check_return_val(type, tb_null); // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BIN); tb_assert_and_check_return_val(reader && reader->hooker, tb_null); // the func return (tb_oc_bin_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)type); } tbox-1.6.7/src/tbox/object/impl/reader/bin.h 0000664 0000000 0000000 00000004527 14142237372 0020653 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file bin.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_READER_BIN_H #define TB_OBJECT_IMPL_READER_BIN_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the bin reader type typedef struct __tb_oc_bin_reader_t { /// the stream tb_stream_ref_t stream; /// the object list tb_vector_ref_t list; }tb_oc_bin_reader_t; /// the bin reader func type typedef tb_object_ref_t (*tb_oc_bin_reader_func_t)(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the bin reader * * @return the bin object reader */ tb_oc_reader_t* tb_oc_bin_reader(tb_noarg_t); /*! hook the bin reader * * @param type the object type * @param func the reader func * * @return tb_true or tb_false */ tb_bool_t tb_oc_bin_reader_hook(tb_size_t type, tb_oc_bin_reader_func_t func); /*! the bin reader func * * @param type the object type * * @return the object reader func */ tb_oc_bin_reader_func_t tb_oc_bin_reader_func(tb_size_t type); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/reader/bplist.c 0000664 0000000 0000000 00000063774 14142237372 0021404 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file bplist.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_reader_bplist" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "bplist.h" #include "reader.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the array grow #ifdef __tb_small__ # define TB_OC_BPLIST_READER_ARRAY_GROW (64) #else # define TB_OC_BPLIST_READER_ARRAY_GROW (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * types */ // the bplist type enum typedef enum __tb_oc_bplist_type_e { TB_OC_BPLIST_TYPE_NONE = 0x00 , TB_OC_BPLIST_TYPE_FALSE = 0x08 , TB_OC_BPLIST_TYPE_TRUE = 0x09 , TB_OC_BPLIST_TYPE_UINT = 0x10 , TB_OC_BPLIST_TYPE_REAL = 0x20 , TB_OC_BPLIST_TYPE_DATE = 0x30 , TB_OC_BPLIST_TYPE_DATA = 0x40 , TB_OC_BPLIST_TYPE_STRING = 0x50 , TB_OC_BPLIST_TYPE_UNICODE = 0x60 , TB_OC_BPLIST_TYPE_UID = 0x80 , TB_OC_BPLIST_TYPE_ARRAY = 0xA0 , TB_OC_BPLIST_TYPE_SET = 0xC0 , TB_OC_BPLIST_TYPE_DICT = 0xD0 , TB_OC_BPLIST_TYPE_MASK = 0xF0 }tb_oc_bplist_type_e; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_time_t tb_oc_bplist_reader_time_apple2host(tb_time_t time) { tb_tm_t tm = {0}; if (tb_localtime(time, &tm)) { if (tm.year < 2000) tm.year += 31; time = tb_mktime(&tm); } return time; } static __tb_inline__ tb_size_t tb_oc_bplist_bits_get(tb_byte_t const* p, tb_size_t n) { tb_size_t v = 0; switch (n) { case 1: v = tb_bits_get_u8((p)); break; case 2: v = tb_bits_get_u16_be((p)); break; case 4: v = tb_bits_get_u32_be((p)); break; case 8: v = tb_bits_get_u64_be((p)); break; default: break; } return v; } static tb_object_ref_t tb_oc_bplist_reader_func_object(tb_oc_bplist_reader_t* reader, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // read the object type tb_uint8_t type = 0; tb_bool_t ok = tb_stream_bread_u8(reader->stream, &type); tb_assert_and_check_return_val(ok, tb_null); // read the object type and size tb_uint8_t size = type & 0x0f; type &= 0xf0; tb_trace_d("type: %x, size: %x", type, size); // the func tb_oc_bplist_reader_func_t func = tb_oc_bplist_reader_func(type); tb_assert_and_check_return_val(func, tb_null); // read return func(reader, type, size, item_size); } static tb_long_t tb_oc_bplist_reader_func_size(tb_oc_bplist_reader_t* reader, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, -1); // read size tb_object_ref_t object = tb_oc_bplist_reader_func_object(reader, item_size); tb_assert_and_check_return_val(object, -1); tb_long_t size = -1; if (tb_object_type(object) == TB_OBJECT_TYPE_NUMBER) size = tb_oc_number_uint32(object); // exit tb_object_exit(object); // size return size; } static tb_object_ref_t tb_oc_bplist_reader_func_data(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init tb_byte_t* data = tb_null; tb_object_ref_t object = tb_null; // size is too large? if (size == 0x0f) { // read size tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); tb_assert_and_check_return_val(val >= 0, tb_null); size = (tb_size_t)val; } // no empty? if (size) { // make data data = tb_malloc_bytes(size); tb_assert_and_check_return_val(data, tb_null); // read data if (tb_stream_bread(reader->stream, data, size)) object = tb_oc_data_init_from_data(data, size); } else object = tb_oc_data_init_from_data(tb_null, 0); // exit if (data) tb_free(data); // ok? return object; } static tb_object_ref_t tb_oc_bplist_reader_func_array(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init tb_object_ref_t object = tb_null; // size is too large? if (size == 0x0f) { // read size tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); tb_assert_and_check_return_val(val >= 0, tb_null); size = (tb_size_t)val; } // init array object = tb_oc_array_init(size? size : 16, tb_false); tb_assert_and_check_return_val(object, tb_null); // init items data if (size) { tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size)); if (data) { if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size)) { tb_bits_set_u32_ne(data, (tb_uint32_t)size); // FIXME: not using the user private data tb_object_setp(object, data); } else tb_free(data); } } // ok? return object; } static tb_object_ref_t tb_oc_bplist_reader_func_string(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init tb_char_t* utf8 = tb_null; tb_char_t* utf16 = tb_null; tb_object_ref_t object = tb_null; // read switch (type) { case TB_OC_BPLIST_TYPE_STRING: { // size is too large? if (size == 0x0f) { // read size tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); tb_assert_and_check_return_val(val >= 0, tb_null); size = (tb_size_t)val; } // read string if (size) { // init utf8 utf8 = tb_malloc_cstr(size + 1); tb_assert_and_check_break(utf8); // read utf8 if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf8, size)) break; utf8[size] = '\0'; } // init object object = tb_oc_string_init_from_cstr(utf8); } break; case TB_OC_BPLIST_TYPE_UNICODE: { #ifdef TB_CONFIG_MODULE_HAVE_CHARSET // size is too large? if (size == 0x0f) { // read size tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); tb_assert_and_check_return_val(val >= 0, tb_null); size = (tb_size_t)val; } // read string if (size) { // init utf8 & utf16 data utf8 = tb_malloc_cstr((size + 1) << 2); utf16 = tb_malloc_cstr(size << 1); tb_assert_and_check_break(utf8 && utf16); // read utf16 if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf16, size << 1)) break; // utf16 to utf8 tb_long_t osize = tb_charset_conv_data(TB_CHARSET_TYPE_UTF16, TB_CHARSET_TYPE_UTF8, (tb_byte_t*)utf16, size << 1, (tb_byte_t*)utf8, (size + 1) << 2); tb_assert_and_check_break(osize > 0 && osize < (tb_long_t)((size + 1) << 2)); utf8[osize] = '\0'; // init object object = tb_oc_string_init_from_cstr(utf8); } #else // trace tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!"); #endif } break; default: break; } // exit if (utf8) tb_free(utf8); if (utf16) tb_free(utf16); // ok? return object; } static tb_object_ref_t tb_oc_bplist_reader_func_number(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // adjust size size = (tb_size_t)1 << size; // done tb_value_t value; tb_object_ref_t object = tb_null; switch (size) { case 1: { // read and init object if (tb_stream_bread_u8(reader->stream, &value.u8)) object = tb_oc_number_init_from_uint8(value.u8); } break; case 2: { // read and init object if (tb_stream_bread_u16_be(reader->stream, &value.u16)) object = tb_oc_number_init_from_uint16(value.u16); } break; case 4: { switch (type) { case TB_OC_BPLIST_TYPE_UID: case TB_OC_BPLIST_TYPE_UINT: { // read and init object if (tb_stream_bread_u32_be(reader->stream, &value.u32)) object = tb_oc_number_init_from_uint32(value.u32); } break; case TB_OC_BPLIST_TYPE_REAL: { #ifdef TB_CONFIG_TYPE_HAVE_FLOAT // read and init object if (tb_stream_bread_float_be(reader->stream, &value.f)) object = tb_oc_number_init_from_float(value.f); #else tb_trace_e("real type is not supported! please enable float config."); #endif } break; default: tb_assert(0); break; } } break; case 8: { switch (type) { case TB_OC_BPLIST_TYPE_UID: case TB_OC_BPLIST_TYPE_UINT: { // read and init object if (tb_stream_bread_u64_be(reader->stream, &value.u64)) object = tb_oc_number_init_from_uint64(value.u64); } break; case TB_OC_BPLIST_TYPE_REAL: { #ifdef TB_CONFIG_TYPE_HAVE_FLOAT // read and init object if (tb_stream_bread_double_bbe(reader->stream, &value.d)) object = tb_oc_number_init_from_double(value.d); #else tb_trace_e("real type is not supported! please enable float config."); #endif } break; default: tb_assert(0); break; } } break; default: tb_assert(0); break; } // ok? return object; } static tb_object_ref_t tb_oc_bplist_reader_func_uid(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // done tb_bool_t ok = tb_false; tb_object_ref_t uid = tb_null; tb_object_ref_t value = tb_null; do { // read uid value value = tb_oc_bplist_reader_func_number(reader, TB_OC_BPLIST_TYPE_UINT, size, item_size); tb_assert_and_check_break(value); // init uid object uid = tb_oc_dictionary_init(8, tb_false); tb_assert_and_check_break(uid); // save this uid value tb_oc_dictionary_insert(uid, "CF$UID", value); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit value if (value) tb_object_exit(value); value = tb_null; } // ok? return uid; } static tb_object_ref_t tb_oc_bplist_reader_func_date(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // the date data tb_object_ref_t data = tb_oc_bplist_reader_func_number(reader, TB_OC_BPLIST_TYPE_REAL, size, item_size); tb_assert_and_check_return_val(data, tb_null); // init date tb_object_ref_t date = tb_oc_date_init_from_time(tb_oc_bplist_reader_time_apple2host((tb_time_t)tb_oc_number_uint64(data))); // exit data tb_object_exit(data); // ok? return date; } static tb_object_ref_t tb_oc_bplist_reader_func_boolean(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // init tb_object_ref_t object = tb_null; // read switch (size) { case TB_OC_BPLIST_TYPE_TRUE: object = tb_oc_boolean_init(tb_true); break; case TB_OC_BPLIST_TYPE_FALSE: object = tb_oc_boolean_init(tb_false); break; default: tb_assert(0); break; } return object; } static tb_object_ref_t tb_oc_bplist_reader_func_dictionary(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init tb_object_ref_t object = tb_null; // size is too large? if (size == 0x0f) { // read size tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); tb_assert_and_check_return_val(val >= 0, tb_null); size = (tb_size_t)val; } // init dictionary object = tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); tb_assert_and_check_return_val(object, tb_null); // init items data if (size) { item_size <<= 1; tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size)); if (data) { if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size)) { tb_bits_set_u32_ne(data, (tb_uint32_t)size); tb_object_setp(object, data); } else tb_free(data); } } // ok? return object; } static tb_object_ref_t tb_oc_bplist_reader_done(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, tb_null); // init root tb_object_ref_t root = tb_null; // init reader tb_oc_bplist_reader_t reader = {0}; reader.stream = stream; // init size tb_hize_t size = tb_stream_size(stream); tb_assert_and_check_return_val(size, tb_null); // init data tb_byte_t data[32] = {0}; // read magic & version if (!tb_stream_bread(stream, data, 8)) return tb_null; // check magic & version if (tb_strncmp((tb_char_t const*)data, "bplist00", 8)) return tb_null; // seek to tail if (!tb_stream_seek(stream, size - 26)) return tb_null; // read offset size tb_uint8_t offset_size = 0; if (!tb_stream_bread_u8(stream, &offset_size)) return tb_null; // read item size for array and dictionary tb_uint8_t item_size = 0; if (!tb_stream_bread_u8(stream, &item_size)) return tb_null; // read object count tb_uint64_t object_count = 0; if (!tb_stream_bread_u64_be(stream, &object_count)) return tb_null; // read root object tb_uint64_t root_object = 0; if (!tb_stream_bread_u64_be(stream, &root_object)) return tb_null; // read offset table index tb_uint64_t offset_table_index = 0; if (!tb_stream_bread_u64_be(stream, &offset_table_index)) return tb_null; // trace tb_trace_d("offset_size: %u", offset_size); tb_trace_d("item_size: %u", item_size); tb_trace_d("object_count: %llu", object_count); tb_trace_d("root_object: %llu", root_object); tb_trace_d("offset_table_index: %llu", offset_table_index); // check tb_assert_and_check_return_val(item_size && offset_size && object_count, tb_null); // init object hash tb_object_ref_t* object_hash = (tb_object_ref_t*)tb_malloc0(sizeof(tb_object_ref_t) * (tb_size_t)object_count); tb_assert_and_check_return_val(object_hash, tb_null); // done tb_bool_t failed = tb_false; do { // walk tb_size_t i = 0; for (i = 0; i < object_count; i++) { // seek to the offset entry if (!tb_stream_seek(stream, offset_table_index + i * offset_size)) { failed = tb_true; break; } // read the object offset tb_value_t value; tb_hize_t offset = 0; switch (offset_size) { case 1: if (tb_stream_bread_u8(stream, &value.u8)) offset = value.u8; break; case 2: if (tb_stream_bread_u16_be(stream, &value.u16)) offset = value.u16; break; case 4: if (tb_stream_bread_u32_be(stream, &value.u32)) offset = value.u32; break; case 8: if (tb_stream_bread_u64_be(stream, &value.u64)) offset = value.u64; break; default: return tb_null; break; } tb_check_break(!failed); // seek to the object offset if (!tb_stream_seek(stream, offset)) { failed = tb_true; break; } // read object object_hash[i] = tb_oc_bplist_reader_func_object(&reader, item_size); } // failed? tb_check_break(!failed); // build array and dictionary items for (i = 0; i < object_count; i++) { tb_object_ref_t object = object_hash[i]; if (object) { switch (tb_object_type(object)) { case TB_OBJECT_TYPE_ARRAY: { // the priv data tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object); if (priv) { // count tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv); if (count) { // goto item data tb_byte_t const* p = priv + sizeof(tb_uint32_t); // walk items tb_size_t j = 0; for (j = 0; j < count; j++) { // the item index tb_size_t item = tb_oc_bplist_bits_get(p + j * item_size, item_size); tb_assert(item < object_count && object_hash[item]); // append item if (item < object_count && object_hash[item]) { tb_object_retain(object_hash[item]); tb_oc_array_append(object, object_hash[item]); } } } // exit priv tb_free(priv); tb_object_setp(object, tb_null); } } break; case TB_OBJECT_TYPE_DICTIONARY: { // the priv data tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object); if (priv) { // count tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv); if (count) { // goto item data tb_byte_t const* p = priv + sizeof(tb_uint32_t); // walk items tb_size_t j = 0; for (j = 0; j < count; j++) { // the key and val tb_size_t key = tb_oc_bplist_bits_get(p + j * item_size, item_size); tb_size_t val = tb_oc_bplist_bits_get(p + (count + j) * item_size, item_size); tb_assert(key < object_count && object_hash[key]); tb_assert(val < object_count && object_hash[val]); // append the key & val if (key < object_count && val < object_count && object_hash[key] && object_hash[val]) { // key must be string now. tb_assert(tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING); if (tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING) { // set key => val tb_char_t const* skey = tb_oc_string_cstr(object_hash[key]); if (skey) { tb_object_retain(object_hash[val]); tb_oc_dictionary_insert(object, skey, object_hash[val]); } tb_assert(skey); } } } } // exit priv tb_free(priv); tb_object_setp(object, tb_null); } } break; default: break; } } } } while (0); // exit object hash if (object_hash) { // root if (root_object < object_count) root = object_hash[root_object]; // refn-- tb_size_t i; for (i = 0; i < object_count; i++) { if (object_hash[i] && i != root_object) tb_object_exit(object_hash[i]); } // exit object hash tb_free(object_hash); object_hash = tb_null; } // ok? return root; } static tb_size_t tb_oc_bplist_reader_probe(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, 0); // need it tb_byte_t* p = tb_null; if (!tb_stream_need(stream, &p, 6)) return 0; tb_assert_and_check_return_val(p, 0); // ok? return !tb_strnicmp((tb_char_t const*)p, "bplist", 6)? 80 : 0; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_oc_reader_t* tb_oc_bplist_reader() { // the reader static tb_oc_reader_t s_reader = {0}; // init reader s_reader.read = tb_oc_bplist_reader_done; s_reader.probe = tb_oc_bplist_reader_probe; // init hooker s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); tb_assert_and_check_return_val(s_reader.hooker, tb_null); // hook reader tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DATE, tb_oc_bplist_reader_func_date); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DATA, tb_oc_bplist_reader_func_data); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UID, tb_oc_bplist_reader_func_uid); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_ARRAY, tb_oc_bplist_reader_func_array); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_STRING, tb_oc_bplist_reader_func_string); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UNICODE, tb_oc_bplist_reader_func_string); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UINT, tb_oc_bplist_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_REAL, tb_oc_bplist_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_NONE, tb_oc_bplist_reader_func_boolean); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_SET, tb_oc_bplist_reader_func_dictionary); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DICT, tb_oc_bplist_reader_func_dictionary); // ok return &s_reader; } tb_bool_t tb_oc_bplist_reader_hook(tb_size_t type, tb_oc_bplist_reader_func_t func) { // check tb_assert_and_check_return_val(func, tb_false); // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BPLIST); tb_assert_and_check_return_val(reader && reader->hooker, tb_false); // hook it tb_hash_map_insert(reader->hooker, (tb_pointer_t)type, func); // ok return tb_true; } tb_oc_bplist_reader_func_t tb_oc_bplist_reader_func(tb_size_t type) { // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BPLIST); tb_assert_and_check_return_val(reader && reader->hooker, tb_null); // the func return (tb_oc_bplist_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)type); } tbox-1.6.7/src/tbox/object/impl/reader/bplist.h 0000664 0000000 0000000 00000004536 14142237372 0021400 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file bplist.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_READER_BPLIST_H #define TB_OBJECT_IMPL_READER_BPLIST_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the bplist reader type typedef struct __tb_oc_bplist_reader_t { /// the stream tb_stream_ref_t stream; }tb_oc_bplist_reader_t; /// the bplist reader func type typedef tb_object_ref_t (*tb_oc_bplist_reader_func_t)(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the bplist reader * * @return the bplist object reader */ tb_oc_reader_t* tb_oc_bplist_reader(tb_noarg_t); /*! hook the bplist reader * * @param type the object type * @param func the reader func * * @return tb_true or tb_false */ tb_bool_t tb_oc_bplist_reader_hook(tb_size_t type, tb_oc_bplist_reader_func_t func); /*! the bplist reader func * * @param type the object type * * @return the object reader func */ tb_oc_bplist_reader_func_t tb_oc_bplist_reader_func(tb_size_t type); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/reader/json.c 0000664 0000000 0000000 00000044621 14142237372 0021046 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file json.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_reader_json" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "json.h" #include "reader.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the array grow #ifdef __tb_small__ # define TB_OC_JSON_READER_ARRAY_GROW (64) #else # define TB_OC_JSON_READER_ARRAY_GROW (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_oc_json_reader_func_null(tb_oc_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init data tb_static_string_t data; tb_char_t buff[256]; if (!tb_static_string_init(&data, buff, 256)) return tb_null; // done tb_object_ref_t null = tb_null; do { // append character tb_static_string_chrcat(&data, type); // walk tb_bool_t failed = tb_false; while (!failed && tb_stream_left(reader->stream)) { // need one character tb_byte_t* p = tb_null; if (!tb_stream_need(reader->stream, &p, 1) && p) { failed = tb_true; break; } // the character tb_char_t ch = *p; // append character if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); else break; // skip it tb_stream_skip(reader->stream, 1); } // failed? tb_check_break(!failed); // check tb_assert_and_check_break(tb_static_string_size(&data)); // trace tb_trace_d("null: %s", tb_static_string_cstr(&data)); // null? if (!tb_stricmp(tb_static_string_cstr(&data), "null")) null = tb_oc_null_init(); } while (0); // exit data tb_static_string_exit(&data); // ok? return null; } static tb_object_ref_t tb_oc_json_reader_func_array(tb_oc_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream && type == '[', tb_null); // init array tb_object_ref_t array = tb_oc_array_init(TB_OC_JSON_READER_ARRAY_GROW, tb_false); tb_assert_and_check_return_val(array, tb_null); // done tb_char_t ch; tb_bool_t ok = tb_true; while (ok && tb_stream_left(reader->stream)) { // read one character if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; // end? if (ch == ']') break; // no space? skip ',' else if (!tb_isspace(ch) && ch != ',') { // the func tb_oc_json_reader_func_t func = tb_oc_json_reader_func(ch); tb_assert_and_check_break_state(func, ok, tb_false); // read item tb_object_ref_t item = func(reader, ch); tb_assert_and_check_break_state(item, ok, tb_false); // append item tb_oc_array_append(array, item); } } // failed? if (!ok) { // exit it if (array) tb_object_exit(array); array = tb_null; } // ok? return array; } static tb_object_ref_t tb_oc_json_reader_func_string(tb_oc_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream && (type == '\"' || type == '\''), tb_null); // init data tb_string_t data; if (!tb_string_init(&data)) return tb_null; // walk tb_char_t ch; while (tb_stream_left(reader->stream)) { // read one character if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; // end? if (ch == '\"' || ch == '\'') break; // the escaped character? else if (ch == '\\') { // read one character if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; // unicode? if (ch == 'u') { #ifdef TB_CONFIG_MODULE_HAVE_CHARSET // the unicode string tb_char_t unicode_str[5]; if (!tb_stream_bread(reader->stream, (tb_byte_t*)unicode_str, 4)) break; unicode_str[4] = '\0'; // the unicode value tb_uint16_t unicode_val = tb_s16toi32(unicode_str); // the utf8 stream tb_char_t utf8_data[16] = {0}; tb_static_stream_t utf8_stream; tb_static_stream_init(&utf8_stream, (tb_byte_t*)utf8_data, sizeof(utf8_data)); // the unicode stream tb_static_stream_t unicode_stream = {0}; tb_static_stream_init(&unicode_stream, (tb_byte_t*)&unicode_val, 2); // unicode to utf8 tb_long_t utf8_size = tb_charset_conv_bst(TB_CHARSET_TYPE_UCS2 | TB_CHARSET_TYPE_NE, TB_CHARSET_TYPE_UTF8, &unicode_stream, &utf8_stream); if (utf8_size > 0) tb_string_cstrncat(&data, utf8_data, utf8_size); #else // trace tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!"); // only append it tb_string_chrcat(&data, ch); #endif } // append escaped character else tb_string_chrcat(&data, ch); } // append character else tb_string_chrcat(&data, ch); } // init string tb_object_ref_t string = tb_oc_string_init_from_cstr(tb_string_cstr(&data)); // trace tb_trace_d("string: %s", tb_string_cstr(&data)); // exit data tb_string_exit(&data); // ok? return string; } static tb_object_ref_t tb_oc_json_reader_func_number(tb_oc_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init data tb_static_string_t data; tb_char_t buff[256]; if (!tb_static_string_init(&data, buff, 256)) return tb_null; // done tb_object_ref_t number = tb_null; do { // append character tb_static_string_chrcat(&data, type); // walk tb_bool_t bs = (type == '-')? tb_true : tb_false; tb_bool_t bf = (type == '.')? tb_true : tb_false; tb_bool_t failed = tb_false; while (!failed && tb_stream_left(reader->stream)) { // need one character tb_byte_t* p = tb_null; if (!tb_stream_need(reader->stream, &p, 1) && p) { failed = tb_true; break; } // the character tb_char_t ch = *p; // is float? if (!bf && ch == '.') bf = tb_true; else if (bf && ch == '.') { failed = tb_true; break; } // append character if (tb_isdigit10(ch) || ch == '.' || ch == 'e' || ch == 'E' || ch == '-' || ch == '+') tb_static_string_chrcat(&data, ch); else break; // skip it tb_stream_skip(reader->stream, 1); } // failed? tb_check_break(!failed); // check tb_assert_and_check_break(tb_static_string_size(&data)); // trace tb_trace_d("number: %s", tb_static_string_cstr(&data)); // init number #ifdef TB_CONFIG_TYPE_HAVE_FLOAT if (bf) number = tb_oc_number_init_from_float(tb_stof(tb_static_string_cstr(&data))); #else if (bf) tb_trace_noimpl(); #endif else if (bs) { tb_sint64_t value = tb_stoi64(tb_static_string_cstr(&data)); tb_size_t bytes = tb_object_need_bytes(-value); switch (bytes) { case 1: number = tb_oc_number_init_from_sint8((tb_sint8_t)value); break; case 2: number = tb_oc_number_init_from_sint16((tb_sint16_t)value); break; case 4: number = tb_oc_number_init_from_sint32((tb_sint32_t)value); break; case 8: number = tb_oc_number_init_from_sint64((tb_sint64_t)value); break; default: break; } } else { tb_uint64_t value = tb_stou64(tb_static_string_cstr(&data)); tb_size_t bytes = tb_object_need_bytes(value); switch (bytes) { case 1: number = tb_oc_number_init_from_uint8((tb_uint8_t)value); break; case 2: number = tb_oc_number_init_from_uint16((tb_uint16_t)value); break; case 4: number = tb_oc_number_init_from_uint32((tb_uint32_t)value); break; case 8: number = tb_oc_number_init_from_uint64((tb_uint64_t)value); break; default: break; } } } while (0); // exit data tb_static_string_exit(&data); // ok? return number; } static tb_object_ref_t tb_oc_json_reader_func_boolean(tb_oc_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init data tb_static_string_t data; tb_char_t buff[256]; if (!tb_static_string_init(&data, buff, 256)) return tb_null; // done tb_object_ref_t boolean = tb_null; do { // append character tb_static_string_chrcat(&data, type); // walk tb_bool_t failed = tb_false; while (!failed && tb_stream_left(reader->stream)) { // need one character tb_byte_t* p = tb_null; if (!tb_stream_need(reader->stream, &p, 1) && p) { failed = tb_true; break; } // the character tb_char_t ch = *p; // append character if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); else break; // skip it tb_stream_skip(reader->stream, 1); } // failed? tb_check_break(!failed); // check tb_assert_and_check_break(tb_static_string_size(&data)); // trace tb_trace_d("boolean: %s", tb_static_string_cstr(&data)); // true? if (!tb_stricmp(tb_static_string_cstr(&data), "true")) boolean = tb_oc_boolean_init(tb_true); // false? else if (!tb_stricmp(tb_static_string_cstr(&data), "false")) boolean = tb_oc_boolean_init(tb_false); } while (0); // exit data tb_static_string_exit(&data); // ok? return boolean; } static tb_object_ref_t tb_oc_json_reader_func_dictionary(tb_oc_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream && type == '{', tb_null); // init key name tb_static_string_t kname; tb_char_t kdata[8192]; if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; // init dictionary tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); tb_assert_and_check_return_val(dictionary, tb_null); // walk tb_char_t ch; tb_bool_t ok = tb_true; tb_bool_t bkey = tb_false; tb_size_t bstr = 0; while (ok && tb_stream_left(reader->stream)) { // read one character if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; // end? if (ch == '}') break; // no space? skip ',' else if (!tb_isspace(ch) && ch != ',') { // no key? if (!bkey) { // is str? if (ch == '\"' || ch == '\'') bstr = !bstr; // is key end? else if (!bstr && ch == ':') bkey = tb_true; // append key else if (bstr) tb_static_string_chrcat(&kname, ch); } // key ok? read val else { // trace tb_trace_d("key: %s", tb_static_string_cstr(&kname)); // the func tb_oc_json_reader_func_t func = tb_oc_json_reader_func(ch); tb_assert_and_check_break_state(func, ok, tb_false); // read val tb_object_ref_t val = func(reader, ch); tb_assert_and_check_break_state(val, ok, tb_false); // set key => val tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), val); // reset key bstr = 0; bkey = tb_false; tb_static_string_clear(&kname); } } } // failed? if (!ok) { // exit it if (dictionary) tb_object_exit(dictionary); dictionary = tb_null; } // exit key name tb_static_string_exit(&kname); // ok? return dictionary; } static tb_object_ref_t tb_oc_json_reader_done(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, tb_null); // init reader tb_oc_json_reader_t reader = {0}; reader.stream = stream; // skip spaces tb_char_t type = '\0'; while (tb_stream_left(stream)) { if (!tb_stream_bread_s8(stream, (tb_sint8_t*)&type)) break; if (!tb_isspace(type)) break; } // empty? tb_check_return_val(tb_stream_left(stream), tb_null); // the func tb_oc_json_reader_func_t func = tb_oc_json_reader_func(type); tb_assert_and_check_return_val(func, tb_null); // read it return func(&reader, type); } static tb_size_t tb_oc_json_reader_probe(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, 0); // need it tb_byte_t* p = tb_null; if (!tb_stream_need(stream, &p, 5)) return 0; tb_assert_and_check_return_val(p, 0); // probe it tb_size_t s = 10; tb_byte_t* e = p + 5; for (; p < e && *p; p++) { if (*p == '{' || *p == '[') { s = 50; break; } else if (!tb_isgraph(*p)) { s = 0; break; } } // ok? return s; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_oc_reader_t* tb_oc_json_reader() { // the reader static tb_oc_reader_t s_reader = {0}; // init reader s_reader.read = tb_oc_json_reader_done; s_reader.probe = tb_oc_json_reader_probe; // init hooker s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint8(), tb_element_ptr(tb_null, tb_null)); tb_assert_and_check_return_val(s_reader.hooker, tb_null); // hook reader tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'n', tb_oc_json_reader_func_null); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'N', tb_oc_json_reader_func_null); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'[', tb_oc_json_reader_func_array); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'\'', tb_oc_json_reader_func_string); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'\"', tb_oc_json_reader_func_string); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'0', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'1', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'2', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'3', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'4', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'5', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'6', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'7', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'8', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'9', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'.', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'-', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'+', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'e', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'E', tb_oc_json_reader_func_number); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'t', tb_oc_json_reader_func_boolean); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'T', tb_oc_json_reader_func_boolean); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'f', tb_oc_json_reader_func_boolean); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'F', tb_oc_json_reader_func_boolean); tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'{', tb_oc_json_reader_func_dictionary); // ok return &s_reader; } tb_bool_t tb_oc_json_reader_hook(tb_char_t type, tb_oc_json_reader_func_t func) { // check tb_assert_and_check_return_val(type && func, tb_false); // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_JSON); tb_assert_and_check_return_val(reader && reader->hooker, tb_false); // hook it tb_hash_map_insert(reader->hooker, (tb_pointer_t)(tb_size_t)type, func); // ok return tb_true; } tb_oc_json_reader_func_t tb_oc_json_reader_func(tb_char_t type) { // check tb_assert_and_check_return_val(type, tb_null); // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_JSON); tb_assert_and_check_return_val(reader && reader->hooker, tb_null); // the func return (tb_oc_json_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)(tb_size_t)type); } tbox-1.6.7/src/tbox/object/impl/reader/json.h 0000664 0000000 0000000 00000004446 14142237372 0021054 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file json.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_READER_JSON_H #define TB_OBJECT_IMPL_READER_JSON_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the json reader type typedef struct __tb_oc_json_reader_t { /// the stream tb_stream_ref_t stream; }tb_oc_json_reader_t; /// the json reader func type typedef tb_object_ref_t (*tb_oc_json_reader_func_t)(tb_oc_json_reader_t* reader, tb_char_t type); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the json object reader * * @return the json object reader */ tb_oc_reader_t* tb_oc_json_reader(tb_noarg_t); /*! hook the json reader * * @param type the object type name * @param func the reader func * * @return tb_true or tb_false */ tb_bool_t tb_oc_json_reader_hook(tb_char_t type, tb_oc_json_reader_func_t func); /*! the json reader func * * @param type the object type name * * @return the object reader func */ tb_oc_json_reader_func_t tb_oc_json_reader_func(tb_char_t type); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/reader/prefix.h 0000664 0000000 0000000 00000004353 14142237372 0021375 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file prefix.h * @ingroup object * */ #ifndef TB_OBJECT_READER_PREFIX_H #define TB_OBJECT_READER_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "../prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * inlines */ static __tb_inline__ tb_void_t tb_oc_reader_bin_type_size(tb_stream_ref_t stream, tb_size_t* ptype, tb_uint64_t* psize) { // check tb_assert_and_check_return(stream); // clear it first if (ptype) *ptype = 0; if (psize) *psize = 0; // the flag tb_uint8_t flag = 0; tb_bool_t ok = tb_stream_bread_u8(stream, &flag); tb_assert_and_check_return(ok); // read type and size tb_size_t type = flag >> 4; tb_uint64_t size = flag & 0x0f; if (type == 0xf) { tb_uint8_t value = 0; if (tb_stream_bread_u8(stream, &value)) type = value; } // done tb_value_t value; switch (size) { case 0xc: if (tb_stream_bread_u8(stream, &value.u8)) size = value.u8; break; case 0xd: if (tb_stream_bread_u16_be(stream, &value.u16)) size = value.u16; break; case 0xe: if (tb_stream_bread_u32_be(stream, &value.u32)) size = value.u32; break; case 0xf: if (tb_stream_bread_u64_be(stream, &value.u64)) size = value.u64; break; default: break; } // trace // tb_trace_d("type: %lu, size: %llu", type, size); // save if (ptype) *ptype = type; if (psize) *psize = size; } #endif tbox-1.6.7/src/tbox/object/impl/reader/reader.c 0000664 0000000 0000000 00000005433 14142237372 0021335 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file reader.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "reader.h" /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ // the object reader static tb_oc_reader_t* g_reader[TB_OBJECT_FORMAT_MAXN] = {tb_null}; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t tb_oc_reader_set(tb_size_t format, tb_oc_reader_t* reader) { // check format &= 0x00ff; tb_assert_and_check_return_val(reader && (format < tb_arrayn(g_reader)), tb_false); // exit the older reader if exists tb_oc_reader_remove(format); // set g_reader[format] = reader; // ok return tb_true; } tb_void_t tb_oc_reader_remove(tb_size_t format) { // check format &= 0x00ff; tb_assert_and_check_return((format < tb_arrayn(g_reader))); // exit it if (g_reader[format]) { // exit hooker if (g_reader[format]->hooker) tb_hash_map_exit(g_reader[format]->hooker); g_reader[format]->hooker = tb_null; // clear it g_reader[format] = tb_null; } } tb_oc_reader_t* tb_oc_reader_get(tb_size_t format) { // check format &= 0x00ff; tb_assert_and_check_return_val((format < tb_arrayn(g_reader)), tb_null); // ok return g_reader[format]; } tb_object_ref_t tb_oc_reader_done(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, tb_null); // probe it tb_size_t i = 0; tb_size_t n = tb_arrayn(g_reader); tb_size_t m = 0; tb_size_t f = 0; for (i = 0; i < n && m < 100; i++) { // the reader tb_oc_reader_t* reader = g_reader[i]; if (reader && reader->probe) { // the probe score tb_size_t score = reader->probe(stream); if (score > m) { m = score; f = i; } } } // ok? read it return (m && g_reader[f] && g_reader[f]->read)? g_reader[f]->read(stream) : tb_null; } tbox-1.6.7/src/tbox/object/impl/reader/reader.h 0000664 0000000 0000000 00000004030 14142237372 0021332 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file reader.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_READER_H #define TB_OBJECT_IMPL_READER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "xml.h" #include "bin.h" #include "json.h" #include "xplist.h" #include "bplist.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! set object reader * * @param format the reader format * @param reader the reader * * @return tb_true or tb_false */ tb_bool_t tb_oc_reader_set(tb_size_t format, tb_oc_reader_t* reader); /*! get object reader * * @param format the reader format * * @return the object reader */ tb_oc_reader_t* tb_oc_reader_get(tb_size_t format); /*! remove object reader * * @param format the reader format */ tb_void_t tb_oc_reader_remove(tb_size_t format); /*! done reader * * @param stream the stream * * @return the object */ tb_object_ref_t tb_oc_reader_done(tb_stream_ref_t stream); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/reader/xml.c 0000664 0000000 0000000 00000050372 14142237372 0020675 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file xml.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_reader_xml" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "xml.h" #include "reader.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the array grow #ifdef __tb_small__ # define TB_OC_XML_READER_ARRAY_GROW (64) #else # define TB_OC_XML_READER_ARRAY_GROW (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_oc_xml_reader_func_null(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // ok return (tb_object_ref_t)tb_oc_null_init(); } static tb_object_ref_t tb_oc_xml_reader_func_date(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_date_init_from_time(0); // walk tb_object_ref_t date = tb_null; tb_bool_t leave = tb_false; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "date")) { // empty? if (!date) date = tb_oc_date_init_from_time(0); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("date: %s", text); // done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld tb_tm_t tm = {0}; tb_char_t const* p = text; tb_char_t const* e = text + tb_strlen(text); // init year while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.year = tb_atoi(p); // init month while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.month = tb_atoi(p); // init day while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.mday = tb_atoi(p); // init hour while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.hour = tb_atoi(p); // init minute while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.minute = tb_atoi(p); // init second while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.second = tb_atoi(p); // time tb_time_t time = tb_mktime(&tm); tb_assert_and_check_break_state(time >= 0, leave, tb_true); // date date = tb_oc_date_init_from_time(time); } break; default: break; } } // ok? return date; } static tb_object_ref_t tb_oc_xml_reader_func_data(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_data_init_from_data(tb_null, 0); // walk tb_object_ref_t data = tb_null; tb_char_t* base64 = tb_null; tb_bool_t leave = tb_false; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "data")) { // empty? if (!data) data = tb_oc_data_init_from_data(tb_null, 0); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("data: %s", text); // base64 base64 = tb_strdup(text); tb_char_t* p = base64; tb_char_t* q = p; for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p; *q = '\0'; // decode base64 data tb_char_t const* ib = base64; tb_size_t in = tb_strlen(base64); if (in) { tb_size_t on = in; tb_byte_t* ob = tb_malloc0_bytes(on); tb_assert_and_check_break_state(ob && on, leave, tb_true); on = tb_base64_decode(ib, in, ob, on); tb_trace_d("base64: %u => %u", in, on); // init data data = tb_oc_data_init_from_data(ob, on); tb_free(ob); } else data = tb_oc_data_init_from_data(tb_null, 0); tb_assert_and_check_break_state(data, leave, tb_true); } break; default: break; } } // exit base64 if (base64) tb_free(base64); base64 = tb_null; // ok? return data; } static tb_object_ref_t tb_oc_xml_reader_func_array(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_array_init(TB_OC_XML_READER_ARRAY_GROW, tb_false); // init array tb_object_ref_t array = tb_oc_array_init(TB_OC_XML_READER_ARRAY_GROW, tb_false); tb_assert_and_check_return_val(array, tb_null); // done tb_long_t ok = 0; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("item: %s", name); // func tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); // append object if (object) tb_oc_array_append(array, object); } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "array")) ok = 1; } break; default: break; } } // failed? if (ok < 0) { // exit it if (array) tb_object_exit(array); array = tb_null; } // ok? return array; } static tb_object_ref_t tb_oc_xml_reader_func_string(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_string_init_from_cstr(tb_null); // done tb_bool_t leave = tb_false; tb_object_ref_t string = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "string")) { // empty? if (!string) string = tb_oc_string_init_from_cstr(tb_null); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("string: %s", text); // string string = tb_oc_string_init_from_cstr(text); tb_assert_and_check_break_state(string, leave, tb_true); } break; default: break; } } // ok? return string; } static tb_object_ref_t tb_oc_xml_reader_func_number(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_number_init_from_uint32(0); // done tb_bool_t leave = tb_false; tb_object_ref_t number = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "number")) leave = tb_true; } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("number: %s", text); // has sign? is float? tb_size_t s = 0; tb_size_t f = 0; tb_char_t const* p = text; for (; *p; p++) { if (!s && *p == '-') s = 1; if (!f && *p == '.') f = 1; if (s && f) break; } // number #ifdef TB_CONFIG_TYPE_HAVE_FLOAT if (f) number = tb_oc_number_init_from_double(tb_atof(text)); #else if (f) tb_trace_noimpl(); #endif else number = s? tb_oc_number_init_from_sint64(tb_stoi64(text)) : tb_oc_number_init_from_uint64(tb_stou64(text)); tb_assert_and_check_break_state(number, leave, tb_true); } break; default: break; } } // ok? return number; } static tb_object_ref_t tb_oc_xml_reader_func_boolean(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_return_val(name, tb_null); tb_trace_d("boolean: %s", name); // the boolean value tb_bool_t val = tb_false; if (!tb_stricmp(name, "true")) val = tb_true; else if (!tb_stricmp(name, "false")) val = tb_false; else return tb_null; // ok? return (tb_object_ref_t)tb_oc_boolean_init(val); } static tb_object_ref_t tb_oc_xml_reader_func_dictionary(tb_oc_xml_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); // init key name tb_static_string_t kname; tb_char_t kdata[8192]; if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; // init dictionary tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); tb_assert_and_check_return_val(dictionary, tb_null); // walk tb_long_t ok = 0; tb_bool_t key = tb_false; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("%s", name); // is key if (!tb_stricmp(name, "key")) key = tb_true; else if (!key) { // func tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object); tb_assert_and_check_break_state(object, ok, -1); // set key & value if (tb_static_string_size(&kname) && dictionary) tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object); // clear key name tb_static_string_clear(&kname); } } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "dict")) ok = 1; else if (!tb_stricmp(name, "key")) key = tb_false; } break; case TB_XML_READER_EVENT_TEXT: { if (key) { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, ok, -1); // writ key name tb_static_string_cstrcpy(&kname, text); } } break; default: break; } } // failed? if (ok < 0) { // exit it if (dictionary) tb_object_exit(dictionary); dictionary = tb_null; } // exit key name tb_static_string_exit(&kname); // ok? return dictionary; } static tb_object_ref_t tb_oc_xml_reader_done(tb_stream_ref_t stream) { // init reader tb_oc_xml_reader_t reader = {0}; reader.reader = tb_xml_reader_init(); tb_assert_and_check_return_val(reader.reader, tb_null); // open reader tb_object_ref_t object = tb_null; if (tb_xml_reader_open(reader.reader, stream, tb_false)) { // done tb_bool_t leave = tb_false; tb_size_t event = TB_XML_READER_EVENT_NONE; while (!leave && !object && (event = tb_xml_reader_next(reader.reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_EMPTY: case TB_XML_READER_EVENT_ELEMENT_BEG: { // name tb_char_t const* name = tb_xml_reader_element(reader.reader); tb_assert_and_check_break_state(name, leave, tb_true); // func tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name); tb_assert_and_check_break_state(func, leave, tb_true); // read object = func(&reader, event); } break; default: break; } } } // exit reader tb_xml_reader_exit(reader.reader); // ok? return object; } static tb_size_t tb_oc_xml_reader_probe(tb_stream_ref_t stream) { // check tb_assert_and_check_return_val(stream, 0); // need it tb_byte_t* p = tb_null; if (!tb_stream_need(stream, &p, 5)) return 0; tb_assert_and_check_return_val(p, 0); // ok? return !tb_strnicmp((tb_char_t const*)p, "hooker, tb_false); // hook it tb_hash_map_insert(reader->hooker, type, func); // ok return tb_true; } tb_oc_xml_reader_func_t tb_oc_xml_reader_func(tb_char_t const* type) { // check tb_assert_and_check_return_val(type, tb_null); // the reader tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XML); tb_assert_and_check_return_val(reader && reader->hooker, tb_null); // the func return (tb_oc_xml_reader_func_t)tb_hash_map_get(reader->hooker, type); } tbox-1.6.7/src/tbox/object/impl/reader/xml.h 0000664 0000000 0000000 00000004452 14142237372 0020700 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file xml.h * @ingroup object * */ #ifndef TB_OBJECT_IMPL_READER_XML_H #define TB_OBJECT_IMPL_READER_XML_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the xml reader type typedef struct __tb_oc_xml_reader_t { /// the xml reader tb_xml_reader_ref_t reader; }tb_oc_xml_reader_t; /// the xml reader func type typedef tb_object_ref_t (*tb_oc_xml_reader_func_t)(tb_oc_xml_reader_t* reader, tb_size_t event); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! the xml object reader * * @return the xml object reader */ tb_oc_reader_t* tb_oc_xml_reader(tb_noarg_t); /*! hook the xml reader * * @param type the object type name * @param func the reader func * * @return tb_true or tb_false */ tb_bool_t tb_oc_xml_reader_hook(tb_char_t const* type, tb_oc_xml_reader_func_t func); /*! the xml reader func * * @param type the object type name * * @return the object reader func */ tb_oc_xml_reader_func_t tb_oc_xml_reader_func(tb_char_t const* type); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/object/impl/reader/xplist.c 0000664 0000000 0000000 00000051103 14142237372 0021411 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file xplist.c * @ingroup object * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "oc_reader_xplist" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "xplist.h" #include "reader.h" /* ////////////////////////////////////////////////////////////////////////////////////// * macros */ // the array grow #ifdef __tb_small__ # define TB_OC_XPLIST_READER_ARRAY_GROW (64) #else # define TB_OC_XPLIST_READER_ARRAY_GROW (256) #endif /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_oc_xplist_reader_func_date(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_date_init_from_time(0); // done tb_bool_t leave = tb_false; tb_object_ref_t date = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "date")) { // empty? if (!date) date = tb_oc_date_init_from_time(0); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("date: %s", text); // done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld tb_tm_t tm = {0}; tb_char_t const* p = text; tb_char_t const* e = text + tb_strlen(text); // init year while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.year = tb_atoi(p); // init month while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.month = tb_atoi(p); // init day while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.mday = tb_atoi(p); // init hour while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.hour = tb_atoi(p); // init minute while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.minute = tb_atoi(p); // init second while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.second = tb_atoi(p); // time tb_time_t time = tb_mktime(&tm); tb_assert_and_check_break_state(time >= 0, leave, tb_true); // date date = tb_oc_date_init_from_time(time); } break; default: break; } } // ok? return date; } static tb_object_ref_t tb_oc_xplist_reader_func_data(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_data_init_from_data(tb_null, 0); // done tb_bool_t leave = tb_false; tb_char_t* base64 = tb_null; tb_object_ref_t data = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "data")) { // empty? if (!data) data = tb_oc_data_init_from_data(tb_null, 0); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("data: %s", text); // base64 base64 = tb_strdup(text); tb_char_t* p = base64; tb_char_t* q = p; for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p; *q = '\0'; // decode base64 data tb_char_t const* ib = base64; tb_size_t in = tb_strlen(base64); if (in) { tb_size_t on = in; tb_byte_t* ob = tb_malloc0_bytes(on); tb_assert_and_check_break_state(ob && on, leave, tb_true); on = tb_base64_decode(ib, in, ob, on); tb_trace_d("base64: %u => %u", in, on); // init data data = tb_oc_data_init_from_data(ob, on); tb_free(ob); } else data = tb_oc_data_init_from_data(tb_null, 0); tb_assert_and_check_break_state(data, leave, tb_true); } break; default: break; } } // free if (base64) tb_free(base64); // ok? return data; } static tb_object_ref_t tb_oc_xplist_reader_func_array(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_array_init(TB_OC_XPLIST_READER_ARRAY_GROW, tb_false); // init array tb_object_ref_t array = tb_oc_array_init(TB_OC_XPLIST_READER_ARRAY_GROW, tb_false); tb_assert_and_check_return_val(array, tb_null); // done tb_long_t ok = 0; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("item: %s", name); // func tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); // append object if (object) tb_oc_array_append(array, object); } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "array")) ok = 1; } break; default: break; } } // failed? if (ok < 0) { // exit it if (array) tb_object_exit(array); array = tb_null; } // ok? return array; } static tb_object_ref_t tb_oc_xplist_reader_func_string(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_string_init_from_cstr(tb_null); // done tb_bool_t leave = tb_false; tb_object_ref_t string = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "string")) { // empty? if (!string) string = tb_oc_string_init_from_cstr(tb_null); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("string: %s", text); // string string = tb_oc_string_init_from_cstr(text); tb_assert_and_check_break_state(string, leave, tb_true); } break; default: break; } } // ok? return string; } static tb_object_ref_t tb_oc_xplist_reader_func_number(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_number_init_from_uint32(0); // done tb_bool_t leave = tb_false; tb_object_ref_t number = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "integer") || !tb_stricmp(name, "real")) leave = tb_true; } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("number: %s", text); // has sign? is float? tb_size_t s = 0; tb_size_t f = 0; tb_char_t const* p = text; for (; *p; p++) { if (!s && *p == '-') s = 1; if (!f && *p == '.') f = 1; if (s && f) break; } // number #ifdef TB_CONFIG_TYPE_HAVE_FLOAT if (f) number = tb_oc_number_init_from_double(tb_atof(text)); #else if (f) tb_trace_noimpl(); #endif else number = s? tb_oc_number_init_from_sint64(tb_stoi64(text)) : tb_oc_number_init_from_uint64(tb_stou64(text)); tb_assert_and_check_break_state(number, leave, tb_true); } break; default: break; } } // ok? return number; } static tb_object_ref_t tb_oc_xplist_reader_func_boolean(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_return_val(name, tb_null); tb_trace_d("boolean: %s", name); // the boolean value tb_bool_t val = tb_false; if (!tb_stricmp(name, "true")) val = tb_true; else if (!tb_stricmp(name, "false")) val = tb_false; else return tb_null; // ok? return (tb_object_ref_t)tb_oc_boolean_init(val); } static tb_object_ref_t tb_oc_xplist_reader_func_dictionary(tb_oc_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); // init key name tb_static_string_t kname; tb_char_t kdata[8192]; if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; // init dictionary tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); tb_assert_and_check_return_val(dictionary, tb_null); // done tb_long_t ok = 0; tb_bool_t key = tb_false; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("%s", name); // is key if (!tb_stricmp(name, "key")) key = tb_true; else if (!key) { // func tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object); tb_assert_and_check_break_state(object, ok, -1); // set key & value if (tb_static_string_size(&kname) && dictionary) tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object); // clear key name tb_static_string_clear(&kname); } } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "dict")) ok = 1; else if (!tb_stricmp(name, "key")) key = tb_false; } break; case TB_XML_READER_EVENT_TEXT: { if (key) { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, ok, -1); // writ key name tb_static_string_cstrcpy(&kname, text); } } break; default: break; } } // failed if (ok < 0) { // exit it if (dictionary) tb_object_exit(dictionary); dictionary = tb_null; } // exit key name tb_static_string_exit(&kname); // ok? return dictionary; } static tb_object_ref_t tb_oc_xplist_reader_done(tb_stream_ref_t stream) { // init reader tb_oc_xplist_reader_t reader = {0}; reader.reader = tb_xml_reader_init(); tb_assert_and_check_return_val(reader.reader, tb_null); // open reader tb_object_ref_t object = tb_null; if (tb_xml_reader_open(reader.reader, stream, tb_false)) { // done tb_bool_t leave = tb_false; tb_size_t event = TB_XML_READER_EVENT_NONE; while (!leave && !object && (event = tb_xml_reader_next(reader.reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_EMPTY: case TB_XML_READER_EVENT_ELEMENT_BEG: { // name tb_char_t const* name = tb_xml_reader_element(reader.reader); tb_assert_and_check_break_state(name, leave, tb_true); //
*
file:
{
"string": "hello world!"
, "com.xxx.xxx": "hello world"
, "integer": 31415926
, "array":
[
"hello world!"
, 31415926
, 3.1415926
, false
, true
, { "string": "hello world!" }
]
, "macro": "$.array[2]"
, "macro2": "$.com\\\\.xxx\\\\.xxx"
, "macro3": "$.macro"
, "macro4": "$.array"
}
path:
1. ".string" : hello world!
2. ".array[1]" : 31415926
3. ".array[5].string" : hello world!
4. ".com\\.xxx\\.xxx" : hello world
5. ".macro" : 3.1415926
6. ".macro2" : hello world
7. ".macro3" : 3.1415926
8. ".macro4[0]" : "hello world!"
*
*
*
* @param object the object
* @param path the object path
* @param bmacro enable macro(like "$.path")?
*
*
* tb_object_ref_t object = tb_object_seek(root, ".array[5].string", tb_false);
* if (object)
* {
* tb_trace_d("%s", tb_oc_string_cstr(object));
* }
*
*
*
* @return the object
*/
tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_bool_t bmacro);
/*! dump the object
*
* @param object the object
* @param format the format, support: .xml, .xplist, .json
*
* @return the object
*/
tb_object_ref_t tb_object_dump(tb_object_ref_t object, tb_size_t format);
/*! the object reference count
*
* @param object the object
*
* @return the object reference count
*/
tb_size_t tb_object_refn(tb_object_ref_t object);
/*! retain object and increase the object reference count
*
* @param object the object
*/
tb_void_t tb_object_retain(tb_object_ref_t object);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.6.7/src/tbox/object/prefix.h 0000664 0000000 0000000 00000005616 14142237372 0017175 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_PREFIX_H
#define TB_OBJECT_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../xml/xml.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object type enum
typedef enum __tb_object_type_e
{
TB_OBJECT_TYPE_NONE = 0
, TB_OBJECT_TYPE_DATA = 1
, TB_OBJECT_TYPE_DATE = 2
, TB_OBJECT_TYPE_ARRAY = 3
, TB_OBJECT_TYPE_STRING = 4
, TB_OBJECT_TYPE_NUMBER = 5
, TB_OBJECT_TYPE_BOOLEAN = 6
, TB_OBJECT_TYPE_DICTIONARY = 7
, TB_OBJECT_TYPE_NULL = 8
, TB_OBJECT_TYPE_USER = 9 //!< the user defined type, ...
}tb_object_type_e;
/// the object flag enum
typedef enum __tb_object_flag_e
{
TB_OBJECT_FLAG_NONE = 0
, TB_OBJECT_FLAG_READONLY = 1
, TB_OBJECT_FLAG_SINGLETON = 2
}tb_object_flag_e;
/// the object format enum
typedef enum __tb_object_format_e
{
TB_OBJECT_FORMAT_NONE = 0x0000 //!< none
, TB_OBJECT_FORMAT_BIN = 0x0001 //!< the tbox binary format
, TB_OBJECT_FORMAT_BPLIST = 0x0002 //!< the bplist format for apple
, TB_OBJECT_FORMAT_XPLIST = 0x0003 //!< the xplist format for apple
, TB_OBJECT_FORMAT_XML = 0x0004 //!< the xml format
, TB_OBJECT_FORMAT_JSON = 0x0005 //!< the json format
, TB_OBJECT_FORMAT_MAXN = 0x000f //!< the format maxn
, TB_OBJECT_FORMAT_DEFLATE = 0x0100 //!< deflate?
}tb_object_format_e;
/// the object type
typedef struct __tb_object_t
{
/// the object flag
tb_uint8_t flag;
/// the object type
tb_uint16_t type;
/// the object reference count
tb_size_t refn;
/// the object private data
tb_cpointer_t priv;
/// the copy func
struct __tb_object_t* (*copy)(struct __tb_object_t* object);
/// the clear func
tb_void_t (*clear)(struct __tb_object_t* object);
/// the exit func
tb_void_t (*exit)(struct __tb_object_t* object);
}tb_object_t, *tb_object_ref_t;
#endif
tbox-1.6.7/src/tbox/object/string.c 0000664 0000000 0000000 00000012633 14142237372 0017176 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_string"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "../string/string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the scache string size
#define TB_OBJECT_STRING_CACHE_SIZE (64)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the string type
typedef struct __tb_oc_string_t
{
// the object base
tb_object_t base;
// the string
tb_string_t str;
}tb_oc_string_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_string_t* tb_oc_string_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_STRING, tb_null);
// cast
return (tb_oc_string_t*)object;
}
static tb_object_ref_t tb_oc_string_copy(tb_object_ref_t object)
{
return tb_oc_string_init_from_cstr(tb_oc_string_cstr(object));
}
static tb_void_t tb_oc_string_exit(tb_object_ref_t object)
{
tb_oc_string_t* string = tb_oc_string_cast(object);
if (string)
{
// exit the string
tb_string_exit(&string->str);
// exit the object
tb_free(object);
}
}
static tb_void_t tb_oc_string_clear(tb_object_ref_t object)
{
tb_oc_string_t* string = tb_oc_string_cast(object);
if (string)
{
// clear the string
tb_string_clear(&string->str);
}
}
static tb_oc_string_t* tb_oc_string_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_string_t* string = tb_null;
do
{
// make string
string = tb_malloc0_type(tb_oc_string_t);
tb_assert_and_check_break(string);
// init string
if (!tb_object_init((tb_object_ref_t)string, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_STRING)) break;
// init base
string->base.copy = tb_oc_string_copy;
string->base.exit = tb_oc_string_exit;
string->base.clear = tb_oc_string_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (string) tb_object_exit((tb_object_ref_t)string);
string = tb_null;
}
// ok?
return string;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_string_init_from_cstr(tb_char_t const* cstr)
{
// done
tb_bool_t ok = tb_false;
tb_oc_string_t* string = tb_null;
do
{
// make string
string = tb_oc_string_init_base();
tb_assert_and_check_break(string);
// init str
if (!tb_string_init(&string->str)) break;
// copy string
if (cstr) tb_string_cstrcpy(&string->str, cstr);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
tb_oc_string_exit((tb_object_ref_t)string);
string = tb_null;
}
// ok?
return (tb_object_ref_t)string;
}
tb_object_ref_t tb_oc_string_init_from_str(tb_string_ref_t str)
{
// done
tb_bool_t ok = tb_false;
tb_oc_string_t* string = tb_null;
do
{
// make string
string = tb_oc_string_init_base();
tb_assert_and_check_break(string);
// init str
if (!tb_string_init(&string->str)) break;
// copy string
if (str) tb_string_strcpy(&string->str, str);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
tb_oc_string_exit((tb_object_ref_t)string);
string = tb_null;
}
// ok?
return (tb_object_ref_t)string;
}
tb_char_t const* tb_oc_string_cstr(tb_object_ref_t object)
{
// check
tb_oc_string_t* string = tb_oc_string_cast(object);
tb_assert_and_check_return_val(string, tb_null);
// cstr
return tb_string_cstr(&string->str);
}
tb_size_t tb_oc_string_cstr_set(tb_object_ref_t object, tb_char_t const* cstr)
{
// check
tb_oc_string_t* string = tb_oc_string_cast(object);
tb_assert_and_check_return_val(string && cstr, 0);
// copy string
tb_string_cstrcpy(&string->str, cstr);
// ok?
return tb_string_size(&string->str);
}
tb_size_t tb_oc_string_size(tb_object_ref_t object)
{
// check
tb_oc_string_t* string = tb_oc_string_cast(object);
tb_assert_and_check_return_val(string, 0);
// size
return tb_string_size(&string->str);
}
tbox-1.6.7/src/tbox/object/string.h 0000664 0000000 0000000 00000004225 14142237372 0017201 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_STRING_H
#define TB_OBJECT_STRING_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init string from c-string
*
* @param cstr the c-string
*
* @return the string object
*/
tb_object_ref_t tb_oc_string_init_from_cstr(tb_char_t const* cstr);
/*! init string from string
*
* @param str the string
*
* @return the string object
*/
tb_object_ref_t tb_oc_string_init_from_str(tb_string_ref_t str);
/*! the c-string
*
* @param string the string object
*
* @return the c-string
*/
tb_char_t const* tb_oc_string_cstr(tb_object_ref_t string);
/*! set the c-string
*
* @param string the string object
* @param cstr the c-string
*
* @return the string size
*/
tb_size_t tb_oc_string_cstr_set(tb_object_ref_t string, tb_char_t const* cstr);
/*! the string size
*
* @param string the string object
*
* @return the string size
*/
tb_size_t tb_oc_string_size(tb_object_ref_t string);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.6.7/src/tbox/platform/ 0000775 0000000 0000000 00000000000 14142237372 0016075 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/platform/addrinfo.c 0000664 0000000 0000000 00000004504 14142237372 0020032 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "addrinfo"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "addrinfo.h"
#include "../network/network.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# define TB_ADDRINFO_ADDR_IMPL
# include "windows/addrinfo.c"
# undef TB_ADDRINFO_ADDR_IMPL
#elif defined(TB_CONFIG_POSIX_HAVE_GETADDRINFO) || \
defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME)
# define TB_ADDRINFO_ADDR_IMPL
# include "posix/addrinfo.c"
# undef TB_ADDRINFO_ADDR_IMPL
#else
tb_bool_t tb_addrinfo_addr(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
#ifndef TB_CONFIG_MICRO_ENABLE
// attempt to get address using dns looker
if (tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6 && tb_dns_looker_done(name, addr))
return tb_true;
#endif
// not implemented
tb_trace_noimpl();
return tb_false;
}
#endif
#if defined(TB_CONFIG_OS_WINDOWS)
# define TB_ADDRINFO_NAME_IMPL
# include "windows/addrinfo.c"
# undef TB_ADDRINFO_NAME_IMPL
#elif defined(TB_CONFIG_POSIX_HAVE_GETNAMEINFO) || \
defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYADDR)
# define TB_ADDRINFO_NAME_IMPL
# include "posix/addrinfo.c"
# undef TB_ADDRINFO_NAME_IMPL
#else
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
{
tb_trace_noimpl();
return tb_null;
}
#endif
tbox-1.6.7/src/tbox/platform/addrinfo.h 0000664 0000000 0000000 00000005030 14142237372 0020032 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_ADDRINFO_H
#define TB_PLATFORM_ADDRINFO_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../network/ipaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! get the first dns address from the host name
*
* @code
// get the default address (ipv4)
tb_ipaddr_t addr = {0};
if (tb_addrinfo_addr("www.tboox.org", &addr))
tb_trace_i("%{ipaddr}", &addr);
// get the ipv6 address by the hint info
tb_ipaddr_t addr = {0};
tb_ipaddr_family_set(&addr, TB_IPADDR_FAMILY_IPV6);
if (tb_addrinfo_addr("www.tboox.org", &addr))
tb_trace_i("%{ipaddr}", &addr);
* @endcode
*
* @param name the host name (cannot be null)
* @param addr the ip address (we can fill some hint info first)
*
* @return tb_true or tb_false
*/
tb_bool_t tb_addrinfo_addr(tb_char_t const* name, tb_ipaddr_ref_t addr);
/*! get the host name from the given address
*
* @code
// get the host name by address
tb_ipaddr_t addr;
tb_char_t host[256];
tb_ipaddr_ip_cstr_set(&addr, "127.0.0.1");
tb_trace_i("%s", tb_addrinfo_name(&addr, host, sizeof(host)));
* @endcode
*
* @param addr the ip address (cannot be null)
* @param name the host name buffer
* @param maxn the host name buffer maxn
*
* @return the host name or tb_null
*/
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.6.7/src/tbox/platform/android/ 0000775 0000000 0000000 00000000000 14142237372 0017515 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/platform/android/android.c 0000664 0000000 0000000 00000003103 14142237372 0021276 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file android.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "android.h"
#include "../atomic.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_atomic_t g_jvm = 0;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_android_init_env(JavaVM* jvm)
{
// check
if (!jvm)
{
// warning
tb_trace_w("the java machine be not inited, please pass it to the tb_init function!");
}
// init it
tb_atomic_set(&g_jvm, (tb_size_t)jvm);
// ok
return tb_true;
}
tb_void_t tb_android_exit_env()
{
// clear it
tb_atomic_set(&g_jvm, 0);
}
JavaVM* tb_android_jvm()
{
// get it
return (JavaVM*)tb_atomic_get(&g_jvm);
}
tbox-1.6.7/src/tbox/platform/android/android.h 0000664 0000000 0000000 00000002616 14142237372 0021313 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file android.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_ANDROID_H
#define TB_PLATFORM_ANDROID_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the android platform
*
* @param jvm the java machine pointer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_android_init_env(JavaVM* jvm);
/// exit the android platform
tb_void_t tb_android_exit_env(tb_noarg_t);
/*! the java machine pointer
*
* @return the java machine pointer
*/
JavaVM* tb_android_jvm(tb_noarg_t);
#endif
tbox-1.6.7/src/tbox/platform/android/backtrace.c 0000664 0000000 0000000 00000027770 14142237372 0021615 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../atomic.h"
#include "../memory.h"
#include "../dynamic.h"
#include "../native_memory.h"
#if 0
# include * * tick: 1s * * 1s 1s .. * wheel: |-----|-----|-----|-----|-----|-----|---- ... -----| <= circle queue * timers * btime ==================> now * | | | * | | | * | | | => the same timeout timer_task list (vector) * | * **/ typedef struct __tb_ltimer_t { // the grow tb_uint16_t grow; // is stoped? tb_atomic_flag_t stop; // is worked? tb_atomic32_t work; // the base time tb_hong_t btime; // cache time? tb_bool_t ctime; // the tick tb_size_t tick; // the lock tb_spinlock_t lock; // the pool tb_fixed_pool_ref_t pool; // the expired tasks tb_vector_ref_t expired; // the wheel tb_vector_ref_t wheel[TB_LTIMER_WHEEL_MAXN]; // the wheel base tb_size_t wbase; }tb_ltimer_t; /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static __tb_inline__ tb_hong_t tb_ltimer_now(tb_ltimer_t* timer) { // using the real time? if (!timer->ctime) { // get the time tb_timeval_t tv = {0}; if (tb_gettimeofday(&tv, tb_null)) return ((tb_hong_t)tv.tv_sec * 1000 + tv.tv_usec / 1000); } // using cached time return tb_cache_time_mclock(); } static tb_bool_t tb_ltimer_add_task(tb_ltimer_t* timer, tb_ltimer_task_t* timer_task) { // check tb_assert_and_check_return_val(timer && timer->pool && timer->tick, tb_false); tb_assert_and_check_return_val(timer_task && timer_task->func && timer_task->refn && timer_task->when, tb_false); // trace tb_trace_d("add: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn); // done tb_bool_t ok = tb_false; do { // empty? move to the wheel head if (!tb_fixed_pool_size(timer->pool)) { timer->btime = tb_ltimer_now(timer); timer->wbase = 0; } // trace tb_trace_d("add: btime: %lld, wbase: %lu", timer->btime, timer->wbase); // the timer difference tb_hong_t tdiff = timer_task->when - timer->btime; tb_assert_and_check_break(tdiff >= 0); // trace tb_trace_d("add: tdiff: %lld", tdiff); // the wheel difference tb_size_t wdiff = (tb_size_t)(tdiff / timer->tick); tb_assert_and_check_break(wdiff < TB_LTIMER_WHEEL_MAXN); // trace tb_trace_d("add: wdiff: %lu", wdiff); // the wheel index tb_size_t windx = (timer->wbase + wdiff) & (TB_LTIMER_WHEEL_MAXN - 1); // trace tb_trace_d("add: windx: %lu", windx); // the wheel list tb_vector_ref_t wlist = timer->wheel[windx]; if (!wlist) wlist = timer->wheel[windx] = tb_vector_init(timer->grow, tb_element_ptr(tb_null, tb_null)); tb_assert_and_check_break(wlist); // save the wheel index timer_task->windx = (tb_uint32_t)windx; // add task to the wheel list tb_vector_insert_tail(wlist, timer_task); // ok ok = tb_true; } while (0); // ok? return ok; } static tb_bool_t tb_ltimer_del_task(tb_ltimer_t* timer, tb_ltimer_task_t* timer_task) { // check tb_assert_and_check_return_val(timer && timer->pool && timer->tick, tb_false); tb_assert_and_check_return_val(timer_task && timer_task->func && timer_task->refn && timer_task->when, tb_false); // trace tb_trace_d("del: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn); // done tb_bool_t ok = tb_false; do { // check tb_assert_and_check_break(timer_task->windx != -1 && timer_task->windx < tb_arrayn(timer->wheel)); // the wheel list tb_vector_ref_t wlist = timer->wheel[timer_task->windx]; tb_assert_and_check_break(wlist); // find the task from the wheel list tb_size_t itor = tb_find_all(wlist, timer_task); tb_assert_and_check_break(itor != tb_iterator_tail(wlist)); // del the task from the wheel list tb_vector_remove(wlist, itor); // clear the wheel index timer_task->windx = -1; // ok ok = tb_true; } while (0); // ok? return ok; } static tb_bool_t tb_ltimer_expired_task_done(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv) { // the task tb_ltimer_task_t const* timer_task = (tb_ltimer_task_t const*)item; // done func if (timer_task && timer_task->func) { // trace tb_trace_d("done: expired: when: %lld, period: %u, refn: %u, killed: %u", timer_task->when, timer_task->period, timer_task->refn, timer_task->killed); // done timer_task->func(timer_task->killed? tb_true : tb_false, timer_task->priv); } // ok return tb_true; } static tb_bool_t tb_ltimer_expired_task_exit(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv) { // check tb_ltimer_t* timer = priv? (tb_ltimer_t*)(((tb_pointer_t*)priv)[0]) : tb_null; tb_hong_t* now = priv? (tb_hong_t*)(((tb_pointer_t*)priv)[1]) : tb_null; tb_assert_and_check_return_val(timer && now, tb_false); // the task tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)item; if (timer_task) { // repeat? if (timer_task->repeat) { // update when timer_task->when = *now + timer_task->period; // continue the task if (!tb_ltimer_add_task(timer, timer_task)) { // trace tb_trace_e("continue to add timer_task failed"); } } else { // refn-- if (timer_task->refn > 1) timer_task->refn--; // remove it from pool directly else tb_fixed_pool_free(timer->pool, timer_task); } } // ok return tb_true; } static tb_void_t tb_ltimer_expired_list_exit(tb_element_ref_t element, tb_pointer_t buff) { // check tb_vector_ref_t list = buff? *((tb_vector_ref_t*)buff) : tb_null; tb_assert_and_check_return(list); // exit list tb_vector_exit(list); // clear it *((tb_pointer_t*)buff) = tb_null; } /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_ltimer_ref_t tb_ltimer_init(tb_size_t grow, tb_size_t tick, tb_bool_t ctime) { // check tb_assert_and_check_return_val(tick >= TB_LTIMER_TICK_100MS, tb_null); // done tb_bool_t ok = tb_false; tb_ltimer_t* timer = tb_null; do { // make timer timer = tb_malloc0_type(tb_ltimer_t); tb_assert_and_check_break(timer); // init timer timer->grow = (tb_uint16_t)tb_max(grow, 16); timer->ctime = ctime; timer->tick = tick; timer->btime = tb_ltimer_now(timer); tb_atomic_flag_clear_explicit(&timer->stop, TB_ATOMIC_RELAXED); tb_atomic32_init(&timer->work, 0); // init lock if (!tb_spinlock_init(&timer->lock)) break; // init pool timer->pool = tb_fixed_pool_init(tb_null, timer->grow, sizeof(tb_ltimer_task_t), tb_null, tb_null, tb_null); tb_assert_and_check_break(timer->pool); // init the expired tasks timer->expired = tb_vector_init((TB_LTIMER_WHEEL_MAXN >> 3) + 8, tb_element_ptr(tb_ltimer_expired_list_exit, tb_null)); tb_assert_and_check_break(timer->expired); // register lock profiler #ifdef TB_LOCK_PROFILER_ENABLE tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&timer->lock, TB_TRACE_MODULE_NAME); #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (timer) tb_ltimer_exit((tb_ltimer_ref_t)timer); timer = tb_null; } // ok? return (tb_ltimer_ref_t)timer; } tb_void_t tb_ltimer_exit(tb_ltimer_ref_t self) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return(self); // kill it first tb_ltimer_kill(self); // wait loop exit tb_size_t tryn = 10; while (tb_atomic32_get_explicit(&timer->work, TB_ATOMIC_RELAXED) && tryn--) tb_msleep(500); // warning if (!tryn && tb_atomic32_get_explicit(&timer->work, TB_ATOMIC_RELAXED)) { tb_trace_w("[ltimer]: the loop has been not exited now!"); } // enter tb_spinlock_enter(&timer->lock); // exit wheel { tb_size_t i = 0; for (i = 0; i < TB_LTIMER_WHEEL_MAXN; i++) { if (timer->wheel[i]) tb_vector_exit(timer->wheel[i]); timer->wheel[i] = tb_null; } } // exit pool if (timer->pool) tb_fixed_pool_exit(timer->pool); timer->pool = tb_null; // leave tb_spinlock_leave(&timer->lock); // exit the expired tasks if (timer->expired) tb_vector_exit(timer->expired); timer->expired = tb_null; // exit lock tb_spinlock_exit(&timer->lock); // exit it tb_free(timer); } tb_void_t tb_ltimer_kill(tb_ltimer_ref_t self) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return(self); // stop it tb_atomic_flag_test_and_set_explicit(&timer->stop, TB_ATOMIC_RELAXED); } tb_void_t tb_ltimer_clear(tb_ltimer_ref_t self) { tb_ltimer_t* timer = (tb_ltimer_t*)self; if (timer) { // enter tb_spinlock_enter(&timer->lock); // move to the wheel head timer->btime = tb_ltimer_now(timer); timer->wbase = 0; // clear wheel { tb_size_t i = 0; for (i = 0; i < TB_LTIMER_WHEEL_MAXN; i++) { if (timer->wheel[i]) tb_vector_clear(timer->wheel[i]); } } // clear pool if (timer->pool) tb_fixed_pool_clear(timer->pool); // leave tb_spinlock_leave(&timer->lock); } } tb_size_t tb_ltimer_limit(tb_ltimer_ref_t self) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return_val(timer, 0); // the self limit return (TB_LTIMER_WHEEL_MAXN * timer->tick); } tb_size_t tb_ltimer_delay(tb_ltimer_ref_t self) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return_val(timer, -1); // ok? return timer->tick; } tb_bool_t tb_ltimer_spak(tb_ltimer_ref_t self) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return_val(timer && timer->pool && timer->tick && timer->expired, tb_false); // stoped? tb_check_return_val(!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED), tb_false); // the now time tb_hong_t now = tb_ltimer_now(timer); // enter tb_spinlock_enter(&timer->lock); // done tb_bool_t ok = tb_false; do { // less than one tick? continue to wait if (now - timer->btime < timer->tick) { ok = tb_true; break; } // empty? move to the wheel head if (!tb_fixed_pool_size(timer->pool)) { timer->btime = now; timer->wbase = 0; ok = tb_true; break; } // the diff tb_size_t diff = (tb_size_t)((now - timer->btime) / timer->tick); // trace tb_trace_d("spak: btime: %lld, wbase: %lu, now: %lld, diff: %lu", timer->btime, timer->wbase, now, diff); // walk the expired lists tb_size_t i = 0; tb_size_t n = tb_min(diff, TB_LTIMER_WHEEL_MAXN - 1); for (i = 0; i <= n; i++) { // the wheel index tb_size_t indx = (timer->wbase + i) & (TB_LTIMER_WHEEL_MAXN - 1); // the wheel list tb_vector_ref_t list = timer->wheel[indx]; tb_check_continue(list && tb_vector_size(list)); // detach the wheel list to the expired tasks tb_vector_insert_tail(timer->expired, list); timer->wheel[indx] = tb_null; } // update the base time timer->btime = now; // update the wheel base timer->wbase = (timer->wbase + diff) & (TB_LTIMER_WHEEL_MAXN - 1); // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&timer->lock); // ok? and exists expired tasks? if (ok && tb_vector_size(timer->expired)) { // done all expired list tb_for_all_if (tb_vector_ref_t, list, timer->expired, list) { // done the expired task tb_walk_all(list, tb_ltimer_expired_task_done, tb_null); // enter tb_spinlock_enter(&timer->lock); // exit the expired task tb_pointer_t data[2]; data[0] = (tb_pointer_t)self; data[1] = &now; tb_walk_all(list, tb_ltimer_expired_task_exit, data); // leave tb_spinlock_leave(&timer->lock); } } // clear expired tb_vector_clear(timer->expired); // ok? return ok; } tb_void_t tb_ltimer_loop(tb_ltimer_ref_t self) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return(timer); // work++ tb_atomic32_fetch_and_add_explicit(&timer->work, 1, TB_ATOMIC_RELAXED); // loop while (!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED)) { // the delay tb_size_t delay = tb_ltimer_delay(self); tb_assert_and_check_break(delay != -1); // wait some time if (delay) tb_msleep(delay); // spak ctime if (timer->ctime) tb_cache_time_spak(); // spak it if (!tb_ltimer_spak(self)) break; } // work-- tb_atomic32_fetch_and_sub_explicit(&timer->work, 1, TB_ATOMIC_RELAXED); } tb_ltimer_task_ref_t tb_ltimer_task_init(tb_ltimer_ref_t self, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return_val(timer && func, tb_null); // add task return tb_ltimer_task_init_at(self, tb_ltimer_now(timer) + delay, delay, repeat, func, priv); } tb_ltimer_task_ref_t tb_ltimer_task_init_at(tb_ltimer_ref_t self, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return_val(timer && timer->pool && func, tb_null); // stoped? tb_assert_and_check_return_val(!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED), tb_null); // enter tb_spinlock_enter(&timer->lock); // make task tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)tb_fixed_pool_malloc0(timer->pool); if (timer_task) { // init task timer_task->refn = 2; timer_task->func = func; timer_task->priv = priv; timer_task->when = when; timer_task->period = period; timer_task->repeat = repeat? 1 : 0; timer_task->killed = 0; timer_task->windx = -1; // add timer_task if (!tb_ltimer_add_task(timer, timer_task)) { tb_fixed_pool_free(timer->pool, timer_task); timer_task = tb_null; } } // leave tb_spinlock_leave(&timer->lock); // ok? return (tb_ltimer_task_ref_t)timer_task; } tb_ltimer_task_ref_t tb_ltimer_task_init_after(tb_ltimer_ref_t self, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return_val(timer && func, tb_null); // add task return tb_ltimer_task_init_at(self, tb_ltimer_now(timer) + after, period, repeat, func, priv); } tb_void_t tb_ltimer_task_post(tb_ltimer_ref_t self, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return(timer && func); // run task tb_ltimer_task_post_at(self, tb_ltimer_now(timer) + delay, delay, repeat, func, priv); } tb_void_t tb_ltimer_task_post_at(tb_ltimer_ref_t self, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return(timer && timer->pool && func); // stoped? tb_assert_and_check_return(!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED)); // enter tb_spinlock_enter(&timer->lock); // make task tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)tb_fixed_pool_malloc0(timer->pool); if (timer_task) { // init task timer_task->refn = 1; timer_task->func = func; timer_task->priv = priv; timer_task->when = when; timer_task->period = period; timer_task->repeat = repeat? 1 : 0; timer_task->killed = 0; timer_task->windx = -1; // add task if (!tb_ltimer_add_task(timer, timer_task)) tb_fixed_pool_free(timer->pool, timer_task); } // leave tb_spinlock_leave(&timer->lock); } tb_void_t tb_ltimer_task_post_after(tb_ltimer_ref_t self, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_assert_and_check_return(timer && func); // run task tb_ltimer_task_post_at(self, tb_ltimer_now(timer) + after, period, repeat, func, priv); } tb_void_t tb_ltimer_task_exit(tb_ltimer_ref_t self, tb_ltimer_task_ref_t task) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)task; tb_assert_and_check_return(timer && timer->pool && timer_task); // trace tb_trace_d("exit: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn); // enter tb_spinlock_enter(&timer->lock); if (timer_task->refn > 1) { // refn-- timer_task->refn--; // cancel task timer_task->func = tb_null; timer_task->priv = tb_null; timer_task->repeat = 0; } // remove it from pool directly if the task have been expired else tb_fixed_pool_free(timer->pool, timer_task); // leave tb_spinlock_leave(&timer->lock); } tb_void_t tb_ltimer_task_kill(tb_ltimer_ref_t self, tb_ltimer_task_ref_t task) { // check tb_ltimer_t* timer = (tb_ltimer_t*)self; tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)task; tb_assert_and_check_return(timer && timer->pool && timer_task); // trace tb_trace_d("kill: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn); // enter tb_spinlock_enter(&timer->lock); // done do { // expired or removed? tb_check_break(timer_task->refn == 2); // del the task first if (!tb_ltimer_del_task(timer, timer_task)) { // trace tb_trace_e("del timer_task failed"); break; } // killed timer_task->killed = 1; // no repeat timer_task->repeat = 0; // modify when => now timer_task->when = tb_ltimer_now(timer); // re-add task if (!tb_ltimer_add_task(timer, timer_task)) { // trace tb_trace_e("re-add timer_task failed"); break; } } while (0); // leave tb_spinlock_leave(&timer->lock); } tbox-1.6.7/src/tbox/platform/ltimer.h 0000664 0000000 0000000 00000015711 14142237372 0017547 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file ltimer.h * @ingroup platform * */ #ifndef TB_PLATFORM_LTIMER_H #define TB_PLATFORM_LTIMER_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "timer.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ /// the timer tick enum typedef enum __tb_ltimer_tick_e { TB_LTIMER_TICK_100MS = 100 , TB_LTIMER_TICK_S = 1000 , TB_LTIMER_TICK_M = 60000 , TB_LTIMER_TICK_H = 3600000 }tb_ltimer_tick_e; /// the ltimer task func type typedef tb_timer_task_func_t tb_ltimer_task_func_t; /// the ltimer ref type typedef __tb_typeref__(ltimer); /// the ltimer task ref type typedef __tb_typeref__(ltimer_task); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ /*! init timer * * lower tick and limit range, but faster * * @param grow the timer grow * @param tick the timer tick * @param ctime using ctime? * * @return the timer */ tb_ltimer_ref_t tb_ltimer_init(tb_size_t grow, tb_size_t tick, tb_bool_t ctime); /*! exit timer * * @param timer the timer */ tb_void_t tb_ltimer_exit(tb_ltimer_ref_t timer); /*! kill timer for tb_ltimer_loop() * * @param timer the timer */ tb_void_t tb_ltimer_kill(tb_ltimer_ref_t timer); /*! clear timer * * @param timer the timer */ tb_void_t tb_ltimer_clear(tb_ltimer_ref_t timer); /*! the timer limit * * @param timer the timer * * @return the timer limit range: [now, now + limit) */ tb_size_t tb_ltimer_limit(tb_ltimer_ref_t timer); /*! the timer delay for spak * * @param timer the timer * * @return the timer delay, (tb_size_t)-1: error or no task */ tb_size_t tb_ltimer_delay(tb_ltimer_ref_t timer); /*! spak timer for the external loop at the single thread * * @code tb_void_t tb_ltimer_loop() { while (1) { // wait wait(tb_ltimer_delay(timer)) // spak timer tb_ltimer_spak(timer); } } * @endcode * * @param timer the timer * * @return tb_true or tb_false */ tb_bool_t tb_ltimer_spak(tb_ltimer_ref_t timer); /*! loop timer for the external thread * * @code tb_void_t tb_ltimer_thread(tb_cpointer_t priv) { tb_ltimer_loop(timer); } * @endcode * * @param timer the timer * */ tb_void_t tb_ltimer_loop(tb_ltimer_ref_t timer); /*! post timer task after delay and will be auto-remove it after be expired * * @param timer the timer * @param delay the delay time, ms * @param repeat is repeat? * @param func the timer func * @param priv the timer priv * */ tb_void_t tb_ltimer_task_post(tb_ltimer_ref_t timer, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv); /*! post timer task at the absolute time and will be auto-remove it after be expired * * @param timer the timer * @param when the absolute time, ms * @param period the period time, ms * @param repeat is repeat? * @param func the timer func * @param priv the timer priv * */ tb_void_t tb_ltimer_task_post_at(tb_ltimer_ref_t timer, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv); /*! run timer task after the relative time and will be auto-remove it after be expired * * @param timer the timer * @param after the after time, ms * @param period the period time, ms * @param repeat is repeat? * @param func the timer func * @param priv the timer priv * */ tb_void_t tb_ltimer_task_post_after(tb_ltimer_ref_t timer, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv); /*! init and post timer task after delay and need remove it manually * * @param timer the timer * @param delay the delay time, ms * @param repeat is repeat? * @param func the timer func * @param priv the timer priv * * @return the timer task */ tb_ltimer_task_ref_t tb_ltimer_task_init(tb_ltimer_ref_t timer, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv); /*! init and post timer task at the absolute time and need remove it manually * * @param timer the timer * @param when the absolute time, ms * @param period the period time, ms * @param repeat is repeat? * @param func the timer func * @param priv the timer priv * * @return the timer task */ tb_ltimer_task_ref_t tb_ltimer_task_init_at(tb_ltimer_ref_t timer, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv); /*! init and post timer task after the relative time and need remove it manually * * @param timer the timer * @param after the after time, ms * @param period the period time, ms * @param repeat is repeat? * @param func the timer func * @param priv the timer priv * * @return the timer task */ tb_ltimer_task_ref_t tb_ltimer_task_init_after(tb_ltimer_ref_t timer, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv); /*! exit timer task, the task will be not called if have been not called * * @param timer the timer * @param task the timer task */ tb_void_t tb_ltimer_task_exit(tb_ltimer_ref_t timer, tb_ltimer_task_ref_t task); /*! kill timer task, the task will be called immediately if have been not called * * @param timer the timer * @param task the timer task */ tb_void_t tb_ltimer_task_kill(tb_ltimer_ref_t timer, tb_ltimer_task_ref_t task); /* ////////////////////////////////////////////////////////////////////////////////////// * extern */ __tb_extern_c_leave__ #endif tbox-1.6.7/src/tbox/platform/mach/ 0000775 0000000 0000000 00000000000 14142237372 0017005 5 ustar 00root root 0000000 0000000 tbox-1.6.7/src/tbox/platform/mach/dns.c 0000664 0000000 0000000 00000004625 14142237372 0017744 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2009-present, TBOOX Open Source Group. * * @author ruki * @file dns.c * @ingroup platform */ /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" #include "../file.h" #include "../dynamic.h" #include "../../libc/libc.h" #include "../../stream/stream.h" #include "../../network/network.h" #include "../impl/dns.h" #include