Class: UniProp::PropFile
- Inherits:
-
Object
- Object
- UniProp::PropFile
- Defined in:
- lib/uniprop/inspects.rb,
lib/uniprop/unicode_elements.rb
Direct Known Subclasses
Defined Under Namespace
Classes: PropertyAliases, PropertyValueAliases, UnihanFile
Instance Attribute Summary collapse
-
#basename_prefix ⇒ Object
Returns the value of attribute basename_prefix.
-
#split_regexp ⇒ Object
Returns the value of attribute split_regexp.
-
#strip_regexp ⇒ Object
Returns the value of attribute strip_regexp.
-
#version ⇒ Object
Returns the value of attribute version.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#actual_properties ⇒ Set<Property>
修正済みメタデータを参照し、ファイル内に含まれるプロパティを取得.
- #cache_path ⇒ Pathname
-
#column_size(row) ⇒ Integer
row行目の列数を取得.
-
#comment?(row) ⇒ Boolean
rowがコメントのみから成る行かを判定.
-
#comment_ranges ⇒ Array<Range>
コメントのみから成る行の範囲を取得.
-
#contents ⇒ Array<Set<String>>
各列に含まれる値(codepointを含む)の配列の配列を取得。.
-
#download_myself ⇒ Object
:nocov: versionの、basename_prefixに該当するファイル名のファイルをUnicode.orgからダウンロード.
-
#has_property_alias?(row, prop) ⇒ Boolean
rowの中の1つ以上の列に、propのエイリアスが含まれるかを判定.
-
#information_containing_ranges ⇒ Array<Range>
空行・コメントのみ以外の行の範囲を取得.
-
#initialize(path, version, strip_regexp: /\s+/, split_regexp: /;/) ⇒ PropFile
constructor
A new instance of PropFile.
- #inspect ⇒ Object
- #is_derived? ⇒ Boolean
-
#is_meta_file? ⇒ Boolean
:nocov:.
- #is_unihan_file? ⇒ Boolean
-
#lines ⇒ Array
ファイルコンテンツを改行で区切った配列を取得.
-
#lines_without_comment ⇒ Array
ファイルコンテンツからコメントを削除したものを改行で区切った配列を取得.
-
#max_column_size(range) ⇒ Integer
rangeで指定された行の範囲内のうち、最大の列数を取得.
-
#missing_value_lines ⇒ Array<String>
missing valueについて記述された行のみを取得.
-
#netto_lines ⇒ Array
lines_without_commentのうち、空文字列となった要素を削除した配列を取得.
-
#netto_shaped_lines ⇒ Array
Valuesから空の配列を削除したArray.
-
#property_alias_including_ranges(prop) ⇒ Array<Range>
propのエイリアスが含まれる行の範囲を取得.
-
#property_value_type_match?(row, column, prop) ⇒ Boolean
row, columnの値がprop.property_value_typeの型にマッチする値かを判定.
-
#property_value_type_match_ranges(column, prop) ⇒ Array<Range>
column列目の中で、propが取りうる値の範囲を取得.
- #propfile_value_group ⇒ PropFileValueGroup
-
#shaped_lines ⇒ Array
lines_without_commentをstrip_regexpとsplit_regexpで処理した配列を取得 def values.
- #shaped_missing_value_lines ⇒ Array<Array<String>>
-
#type_match?(row, column, type, prop) ⇒ Boolean
row, columnの値がtypeの型にマッチする値かを判定.
-
#unique_column?(column, unique_threshold) ⇒ Boolean
:nocov: 引数の列がユニーク列(行数に対し、記述されている値の割合が閾値以上の列。Nameプロパティなど、それぞれのcodepointが異なる値を取る傾向にあるプロパティが該当)であるかを判定.
-
#value_at(row, column) ⇒ String
引数の行・列の値を取得.
-
#values ⇒ Set<String>
ファイル内に含まれるすべての値(codepointを含む)を取得。.
-
#verbose_property_value_type_match_ranges(column, prop) ⇒ Array<Range<Integer>>
property_value_type_match_rangesの最小値を下限、最大値を上限とする範囲の中で、空行、コメント行、column列目の値がpropの行のいずれかに該当する範囲を取得.
Constructor Details
#initialize(path, version, strip_regexp: /\s+/, split_regexp: /;/) ⇒ PropFile
fileをPathnameで指定する場合、絶対パスでの指定が必要
Returns a new instance of PropFile.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/uniprop/unicode_elements.rb', line 180 def initialize(path, version, strip_regexp: /\s+/, split_regexp: /;/) if path.class==Pathname @cache_path = path @basename_prefix = UniPropUtils::FileManager.prefix(@cache_path) else @basename_prefix = path end # # strip_regexp, split_regexpが引数で指定されていない場合、settings.rbの記述を使用 # file_format = version.prop_data.find_settings_value(version.prop_data.unihan_files_information, "file_format", version.version_name) # strip_regexp ||= file_format[:strip] # split_regexp ||= file_format[:split] @version = version @strip_regexp = strip_regexp @split_regexp = split_regexp end |
Instance Attribute Details
#basename_prefix ⇒ Object
Returns the value of attribute basename_prefix.
174 175 176 |
# File 'lib/uniprop/unicode_elements.rb', line 174 def basename_prefix @basename_prefix end |
#split_regexp ⇒ Object
Returns the value of attribute split_regexp.
174 175 176 |
# File 'lib/uniprop/unicode_elements.rb', line 174 def split_regexp @split_regexp end |
#strip_regexp ⇒ Object
Returns the value of attribute strip_regexp.
174 175 176 |
# File 'lib/uniprop/unicode_elements.rb', line 174 def strip_regexp @strip_regexp end |
#version ⇒ Object
Returns the value of attribute version.
174 175 176 |
# File 'lib/uniprop/unicode_elements.rb', line 174 def version @version end |
Instance Method Details
#==(other) ⇒ Object
249 250 251 252 253 254 255 256 257 258 |
# File 'lib/uniprop/unicode_elements.rb', line 249 def ==(other) if other.class == self.class # cache_pathで判定したほうが簡潔に書けるが、キャッシュにファイルが存在しない場合にも判定を行うため、このような実装にしてある return version==other.version && basename_prefix==other.basename_prefix elsif other.class == Pathname return @cache_path==other else return false end end |
#actual_properties ⇒ Set<Property>
修正済みメタデータを参照し、ファイル内に含まれるプロパティを取得
504 505 506 |
# File 'lib/uniprop/unicode_elements.rb', line 504 def actual_properties @actual_properties ||= version..propfile_to_actual_properties[self] end |
#cache_path ⇒ Pathname
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/uniprop/unicode_elements.rb', line 201 def cache_path return @cache_path if @cache_path # キャッシュの中にbasename_prefixと同名のファイルがある場合、それを使用 if version.has_cache_file?(basename_prefix) @cache_path = version.find_cache_file_path(basename_prefix) return @cache_path end # キャッシュが保存されていない場合、ダウンロードを試みる download_myself if version.has_cache_file?(basename_prefix) @cache_path = version.find_cache_file_path(basename_prefix) return @cache_path else raise FileNotFoundError, "#{basename_prefix} does not exist in cache and download failed." end end |
#column_size(row) ⇒ Integer
row行目の列数を取得
473 474 475 476 |
# File 'lib/uniprop/unicode_elements.rb', line 473 def column_size(row) shaped_line = shaped_lines[row].to_a shaped_line[-1]&.empty? ? shaped_line.size-1 : shaped_line.size end |
#comment?(row) ⇒ Boolean
空行もコメント行とみなす
rowがコメントのみから成る行かを判定
361 362 363 364 365 366 367 |
# File 'lib/uniprop/unicode_elements.rb', line 361 def comment?(row) if 0 <= row && row <= lines.size-1 lines_without_comment[row].match?(/^\s*$/) else false end end |
#comment_ranges ⇒ Array<Range>
コメントのみから成る行の範囲を取得
371 372 373 374 375 376 377 378 379 380 381 |
# File 'lib/uniprop/unicode_elements.rb', line 371 def comment_ranges return @comment_ranges if @comment_ranges comment_rows = [] lines.size.times do |row| comment_rows << row if comment?(row) end @comment_ranges = UniPropUtils::RangeProcessor.array_to_ranges(comment_rows) @comment_ranges end |
#contents ⇒ Array<Set<String>>
返り値の配列のインデックスnは、n列目(最初の列を0列目とする)に含まれるすべての値を含む配列。
各列に含まれる値(codepointを含む)の配列の配列を取得。
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/uniprop/unicode_elements.rb', line 294 def contents return @contents if @contents @contents = [] shaped_lines.each do |shaped_line| shaped_line.each_with_index do |col_value, i| @contents[i] ||= Set.new @contents[i] << Alias.canonical(col_value) end end # valuesでは区切り文字で区切られたそれぞれの部分を列とみなす。(1行に区切り文字がn個あれば、n+1列あるとみなされる) # しかし実際には、最後の区切り文字の右側にコメントしか記述されない事が多いので、その場合は最終列を削除。 # contentsでは、最後の列に実際に値が無い場合(空orコメントのみの場合)には列とみなさない。 if @contents[-1].empty? || @contents[-1] == Set.new([""]) @contents = @contents[...-1] end @contents end |
#download_myself ⇒ Object
:nocov: versionの、basename_prefixに該当するファイル名のファイルをUnicode.orgからダウンロード
222 223 224 |
# File 'lib/uniprop/unicode_elements.rb', line 222 def download_myself version.download_file(basename_prefix) end |
#has_property_alias?(row, prop) ⇒ Boolean
rowの中の1つ以上の列に、propのエイリアスが含まれるかを判定
341 342 343 |
# File 'lib/uniprop/unicode_elements.rb', line 341 def has_property_alias?(row, prop) !!shaped_lines[row]&.any? { prop.has_alias?(_1) } end |
#information_containing_ranges ⇒ Array<Range>
空行・コメントのみ以外の行の範囲を取得
391 392 393 |
# File 'lib/uniprop/unicode_elements.rb', line 391 def information_containing_ranges UniPropUtils::RangeProcessor.sub(Range.new(0, lines.size-1), comment_ranges) end |
#inspect ⇒ Object
5 6 7 |
# File 'lib/uniprop/inspects.rb', line 5 def inspect "#<#{self.class.name} #{basename_prefix}>" end |
#is_derived? ⇒ Boolean
521 522 523 |
# File 'lib/uniprop/unicode_elements.rb', line 521 def is_derived? basename_prefix.start_with?(/Derived/) end |
#is_meta_file? ⇒ Boolean
:nocov:
227 |
# File 'lib/uniprop/unicode_elements.rb', line 227 def () false end |
#is_unihan_file? ⇒ Boolean
229 |
# File 'lib/uniprop/unicode_elements.rb', line 229 def is_unihan_file?() false end |
#lines ⇒ Array
ファイルコンテンツを改行で区切った配列を取得
233 |
# File 'lib/uniprop/unicode_elements.rb', line 233 def lines() @lines ||= cache_path.readlines.map(&:chomp) end |
#lines_without_comment ⇒ Array
コメントのみからなる行は空文字列に変換されるだけであり、要素は削除されない (行数がインデックスと対応)
ファイルコンテンツからコメントを削除したものを改行で区切った配列を取得
238 239 240 |
# File 'lib/uniprop/unicode_elements.rb', line 238 def lines_without_comment @lines_without_comment ||= lines.map { |l| l.gsub(/#.*/,'') } end |
#max_column_size(range) ⇒ Integer
rangeで指定された行の範囲内のうち、最大の列数を取得
481 482 483 |
# File 'lib/uniprop/unicode_elements.rb', line 481 def max_column_size(range) range.map{column_size(_1)}.max end |
#missing_value_lines ⇒ Array<String>
missing valueについて記述された行のみを取得
385 386 387 |
# File 'lib/uniprop/unicode_elements.rb', line 385 def missing_value_lines @missing_value_lines ||= lines.filter { _1.match?(/@missing/) } end |
#netto_lines ⇒ Array
lines_without_commentのうち、空文字列となった要素を削除した配列を取得
244 245 246 |
# File 'lib/uniprop/unicode_elements.rb', line 244 def netto_lines @netto_lines ||= lines_without_comment.reject { |l| l.match(/^\s*$/) } end |
#netto_shaped_lines ⇒ Array
Returns valuesから空の配列を削除したArray.
287 288 289 |
# File 'lib/uniprop/unicode_elements.rb', line 287 def netto_shaped_lines @netto_shaped_lines ||= shaped_lines.reject { _1.empty? } end |
#property_alias_including_ranges(prop) ⇒ Array<Range>
propのエイリアスが含まれる行の範囲を取得
348 349 350 351 352 353 354 355 356 |
# File 'lib/uniprop/unicode_elements.rb', line 348 def property_alias_including_ranges(prop) property_alias_including_rows = [] lines.size.times do |row| property_alias_including_rows << row if has_property_alias?(row, prop) end UniPropUtils::RangeProcessor.array_to_ranges(property_alias_including_rows) end |
#property_value_type_match?(row, column, prop) ⇒ Boolean
Miscellaneousプロパティの判定方法はsettings.rbで指定可能
row, columnの値がprop.property_value_typeの型にマッチする値かを判定
401 402 403 404 405 406 407 |
# File 'lib/uniprop/unicode_elements.rb', line 401 def property_value_type_match?(row, column, prop) if prop.property_value_type == :miscellaneous return type_match?(row, column, prop.miscellaneous_format, prop) else return type_match?(row, column, prop.property_value_type, prop) end end |
#property_value_type_match_ranges(column, prop) ⇒ Array<Range>
column列目の中で、propが取りうる値の範囲を取得
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 |
# File 'lib/uniprop/unicode_elements.rb', line 448 def property_value_type_match_ranges(column, prop) # miscellanesou_format==unqueの場合、ファイル内の全範囲をreturn if prop.property_value_type==:miscellaneous && prop.miscellaneous_format==:unique if unique_column?(column, prop.unique_threshold) return information_containing_ranges else return [] end end # それ以外の場合、property_value_type_match? がtrueとなる行の範囲をreturn property_value_including_rows = [] lines.size.times do |row| if property_value_type_match?(row, column, prop) property_value_including_rows << row end end UniPropUtils::RangeProcessor.array_to_ranges(property_value_including_rows) end |
#propfile_value_group ⇒ PropFileValueGroup
517 518 519 |
# File 'lib/uniprop/unicode_elements.rb', line 517 def propfile_value_group @propfile_value_group ||= PropFileValueGroup.new(self) end |
#shaped_lines ⇒ Array
strip_regexp==/s+/ の場合であっても、各列の最初と最後の空白しか除去されない。「0000; 1111 2222; 3333;」の、1111と2222の間の空白は除去されない。
lines_without_commentをstrip_regexpとsplit_regexpで処理した配列を取得def values
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/uniprop/unicode_elements.rb', line 264 def shaped_lines return @shaped_lines if @shaped_lines @shaped_lines = [] # String#splitはlimit==0(デフォルト)の場合、配列末尾の空文字列が削除される # それを防ぐため、limit==-1としてある。これはlimit<0にする事が目的であり、-1という値に意味は無い if strip_regexp == /\s+/ lines_without_comment.each do |line| @shaped_lines << line.split(sep=split_regexp, limit=-1) .map { _1.gsub(/^\s+/, '') } .map { _1.gsub(/\s+$/, '') } end else lines_without_comment.each do |line| @shaped_lines << line.split(sep=split_regexp, limit=-1) .map { _1.gsub(strip_regexp, '') } end end @shaped_lines end |
#shaped_missing_value_lines ⇒ Array<Array<String>>
509 510 511 512 513 514 |
# File 'lib/uniprop/unicode_elements.rb', line 509 def shaped_missing_value_lines @shaped_missing_value_lines ||= missing_value_lines.map { _1.gsub(/\s/, '') .split(/;/) } end |
#type_match?(row, column, type, prop) ⇒ Boolean
row, columnの値がtypeの型にマッチする値かを判定
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
# File 'lib/uniprop/unicode_elements.rb', line 415 def type_match?(row, column, type, prop) # データファイルには、一番右の;の右側に情報が記述されるフォーマットと、コメントのみが記述されるフォーマットが存在 # row行目だけを取り出し、一番右側の列が値を持たない(value_atがnil)場合、たまたまrow行目に値が記述されていない(値が空文字列)だけか、ファイル全体として一番右の列に値が記述されていないのか、判定不可能 # そのため、ここでは値が存在しない列に対しては、空文字列を値として持つと仮定して判定を行う value = value_at(row, column) || "" case type when :catalog, :enumerated return UniPropUtils::TypeJudgementer.validate_enumerative(value, prop) when :binary return UniPropUtils::TypeJudgementer.validate_binary(value, prop) when :string return UniPropUtils::TypeJudgementer.validate_string(value) when :numeric return UniPropUtils::TypeJudgementer.validate_numeric(value) when :jamo_short_name # Jamo_Short_Nameは、プロパティ値のエイリアス1つか、空文字列(missing)を値として取る(15.0.0でコードポイント110Bの値が空文字列として明示的に記述されている) return prop.property_values.any? { _1.has_alias?(value) } || value.empty? when :script_extensions # Script_Extensionsは1つ以上のScriptプロパティのプロパティ値を取る。2つ以上取る場合、ファイル内では半角スペース区切りで記述される。 return value.split.all? { version.find_property("Script").has_property_value?(_1) } when :text # 任意の文字列(空文字列も含む)である事を表すtextでは常にtrueを返す return true else return false end end |
#unique_column?(column, unique_threshold) ⇒ Boolean
:nocov: 引数の列がユニーク列(行数に対し、記述されている値の割合が閾値以上の列。Nameプロパティなど、それぞれのcodepointが異なる値を取る傾向にあるプロパティが該当)であるかを判定
327 328 329 |
# File 'lib/uniprop/unicode_elements.rb', line 327 def unique_column?(column, unique_threshold) (contents[column].size.to_f / netto_lines.size) > unique_threshold end |
#value_at(row, column) ⇒ String
引数の行・列の値を取得
334 335 336 |
# File 'lib/uniprop/unicode_elements.rb', line 334 def value_at(row, column) shaped_lines.dig(row, column) end |
#values ⇒ Set<String>
ファイル内に含まれるすべての値(codepointを含む)を取得。
318 319 320 |
# File 'lib/uniprop/unicode_elements.rb', line 318 def values @values ||= contents.reduce(Set.new, :merge) end |
#verbose_property_value_type_match_ranges(column, prop) ⇒ Array<Range<Integer>>
property_value_type_match_rangesの最小値を下限、最大値を上限とする範囲の中で、空行、コメント行、column列目の値がpropの行のいずれかに該当する範囲を取得
487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
# File 'lib/uniprop/unicode_elements.rb', line 487 def verbose_property_value_type_match_ranges(column, prop) prop_ranges = property_value_type_match_ranges(column, prop) if prop_ranges.empty? return prop_ranges else prop_begin_col = UniPropUtils::RangeProcessor.min(prop_ranges) prop_end_col = UniPropUtils::RangeProcessor.max(prop_ranges) return UniPropUtils::RangeProcessor.sum_up( comment_ranges.map { UniPropUtils::RangeProcessor.cut_external(_1, prop_begin_col, prop_end_col) }.compact + prop_ranges ) end end |