GeneratorFileDictLoader.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /*
  3. * This file is part of the overtrue/pinyin.
  4. *
  5. * (c) overtrue <i@overtrue.me>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace Overtrue\Pinyin;
  11. use Closure;
  12. use SplFileObject;
  13. use Generator;
  14. class GeneratorFileDictLoader implements DictLoaderInterface
  15. {
  16. /**
  17. * Data directory.
  18. *
  19. * @var string
  20. */
  21. protected $path;
  22. /**
  23. * Words segment name.
  24. *
  25. * @var string
  26. */
  27. protected $segmentName = 'words_%s';
  28. /**
  29. * SplFileObjects.
  30. *
  31. * @var array
  32. */
  33. protected static $handles = [];
  34. /**
  35. * surnames.
  36. *
  37. * @var SplFileObject
  38. */
  39. protected static $surnamesHandle;
  40. /**
  41. * Constructor.
  42. *
  43. * @param string $path
  44. */
  45. public function __construct($path)
  46. {
  47. $this->path = $path;
  48. for ($i = 0; $i < 100; ++$i) {
  49. $segment = $this->path . '/' . sprintf($this->segmentName, $i);
  50. if (file_exists($segment) && is_file($segment)) {
  51. array_push(static::$handles, $this->openFile($segment));
  52. }
  53. }
  54. }
  55. /**
  56. * Construct a new file object.
  57. *
  58. * @param string $filename file path
  59. * @param string $mode file open mode
  60. *
  61. * @return SplFileObject
  62. */
  63. protected function openFile($filename, $mode = 'r')
  64. {
  65. return new SplFileObject($filename, $mode);
  66. }
  67. /**
  68. * get Generator syntax.
  69. *
  70. * @param array $handles SplFileObjects
  71. *
  72. * @return Generator
  73. */
  74. protected function getGenerator(array $handles)
  75. {
  76. foreach ($handles as $handle) {
  77. $handle->seek(0);
  78. while (false === $handle->eof()) {
  79. $string = str_replace(['\'', ' ', PHP_EOL, ','], '', $handle->fgets());
  80. if (false === strpos($string, '=>')) {
  81. continue;
  82. }
  83. list($string, $pinyin) = explode('=>', $string);
  84. yield $string => $pinyin;
  85. }
  86. }
  87. }
  88. /**
  89. * Traverse the stream.
  90. *
  91. * @param Generator $generator
  92. * @param Closure $callback
  93. *
  94. * @author Seven Du <shiweidu@outlook.com>
  95. */
  96. protected function traversing(Generator $generator, Closure $callback)
  97. {
  98. foreach ($generator as $string => $pinyin) {
  99. $callback([$string => $pinyin]);
  100. }
  101. }
  102. /**
  103. * Load dict.
  104. *
  105. * @param Closure $callback
  106. */
  107. public function map(Closure $callback)
  108. {
  109. $this->traversing($this->getGenerator(static::$handles), $callback);
  110. }
  111. /**
  112. * Load surname dict.
  113. *
  114. * @param Closure $callback
  115. */
  116. public function mapSurname(Closure $callback)
  117. {
  118. if (!static::$surnamesHandle instanceof SplFileObject) {
  119. static::$surnamesHandle = $this->openFile($this->path . '/surnames');
  120. }
  121. $this->traversing($this->getGenerator([static::$surnamesHandle]), $callback);
  122. }
  123. }