GeneratorFileDictLoader.php 3.1 KB

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