# frozen_string_literal: falserequire'strscan'modulePsych#### Scan scalars for built in typesclassScalarScanner# Taken from http://yaml.org/type/timestamp.htmlTIME=/^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/# Taken from http://yaml.org/type/float.htmlFLOAT=/^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
|[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60)
|[-+]?\.(inf|Inf|INF)(?# infinity)
|\.(nan|NaN|NAN)(?# not a number))$/x# Taken from http://yaml.org/type/int.htmlINTEGER=/^(?:[-+]?0b[0-1_]+ (?# base 2)
|[-+]?0[0-7_]+ (?# base 8)
|[-+]?(?:0|[1-9][0-9_]*) (?# base 10)
|[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/xattr_reader:class_loader# Create a new scannerdefinitializeclass_loader@string_cache={}@symbol_cache={}@class_loader=class_loaderend# Tokenize +string+ returning the Ruby objectdeftokenizestringreturnnilifstring.empty?returnstringif@string_cache.key?(string)return@symbol_cache[string]if@symbol_cache.key?(string)casestring# Check for a String type, being careful not to get caught by hash keys, hex values, and# special floats (e.g., -.inf).when/^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/,/\n/ifstring.length>5@string_cache[string]=truereturnstringendcasestringwhen/^[^ytonf~]/i@string_cache[string]=truestringwhen'~',/^null$/inilwhen/^(yes|true|on)$/itruewhen/^(no|false|off)$/ifalseelse@string_cache[string]=truestringendwhenTIMEbeginparse_timestringrescueArgumentErrorstringendwhen/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/require'date'beginclass_loader.date.strptime(string,'%Y-%m-%d')rescueArgumentErrorstringendwhen/^\.inf$/iFloat::INFINITYwhen/^-\.inf$/i-Float::INFINITYwhen/^\.nan$/iFloat::NANwhen/^:./ifstring=~/^:(["'])(.*)\1/@symbol_cache[string]=class_loader.symbolize($2.sub(/^:/,''))else@symbol_cache[string]=class_loader.symbolize(string.sub(/^:/,''))endwhen/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/i=0string.split(':').each_with_indexdo|n,e|i+=(n.to_i*60**(e-2).abs)endiwhen/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/i=0string.split(':').each_with_indexdo|n,e|i+=(n.to_f*60**(e-2).abs)endiwhenFLOATifstring=~/\A[-+]?\.\Z/@string_cache[string]=truestringelseFloat(string.gsub(/[,_]|\.([Ee]|$)/,'\1'))endelseint=parse_intstring.gsub(/[,_]/,'')returnintifint@string_cache[string]=truestringendend#### Parse and return an int from +string+defparse_intstringreturnunlessINTEGER===stringInteger(string)end#### Parse and return a Time from +string+defparse_timestringklass=class_loader.load'Time'date,time=*(string.split(/[ tT]/,2))(yy,m,dd)=date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map{|x|x.to_i}md=time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)(hh,mm,ss)=md[1].split(':').map{|x|x.to_i}us=(md[2]?Rational("0.#{md[2]}"):0)*1000000time=klass.utc(yy,m,dd,hh,mm,ss,us)returntimeif'Z'==md[3]returnklass.at(time.to_i,us)unlessmd[3]tz=md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map{|digit|Integer(digit,10)}offset=tz.first*3600ifoffset<0offset-=((tz[1]||0)*60)elseoffset+=((tz[1]||0)*60)endklass.at((time-offset).to_i,us)endendend