class Boss::Formatter
Formats ruby object hierarchies with BOSS notation
Public Class Methods
Construct formatter for a given IO-like object or create StringIO one as output
# File lib/boss-protocol.rb, line 122 def initialize(dst=nil) @io = dst ? dst : StringIO.new('', 'wb') @io.set_encoding Encoding::BINARY if @io.respond_to? :set_encoding @cache = { nil => 0 } @stream_mode = false end
Public Instance Methods
# File lib/boss-protocol.rb, line 129 def get_stream @io end
Put object tree routed as ob to the output. Alias: <<. It is possible to put more than one object to the same Formatter
. Not that formatter has per-instance cache so put(x) put(x) put(x) will store one object and 2 more refs to it, so on load time only one object will be constructed and 2 more refs will be created.
# File lib/boss-protocol.rb, line 177 def put(ob) case ob when Fixnum, Bignum if ob < 0 whdr TYPE_NINT, -ob else whdr TYPE_INT, ob end when String, Symbol ob = ob.to_s unless ob.is_a?(String) if notCached(ob) if ob.encoding == Encoding::BINARY whdr TYPE_BIN, ob.length wbin ob else whdr TYPE_TEXT, ob.bytesize wbin ob.dup.encode(Encoding::UTF_8) end end when Array if notCached(ob) whdr TYPE_LIST, ob.length ob.each { |x| put(x) } end when Hash if notCached(ob) whdr TYPE_DICT, ob.length ob.each { |k, v| self << k << v } end when Float case ob when 0 whdr TYPE_EXTRA, DZERO when -1.0 whdr TYPE_EXTRA, DMINUSONE when +1.0 whdr TYPE_EXTRA, DONE else whdr TYPE_EXTRA, TDOUBLE wdouble ob end when TrueClass, FalseClass whdr TYPE_EXTRA, ob ? TTRUE : TFALSE when nil whdr TYPE_CREF, 0 when Time whdr TYPE_EXTRA, TTIME wrenc ob.to_i else error = "error: not supported object: #{ob}, #{ob.class}" raise NotSupportedException, error end self end
same as put but automatically select and use proper compression. Parser.get
will automatically decompress.
# File lib/boss-protocol.rb, line 150 def put_compressed ob data = Boss.dump(ob) whdr TYPE_EXTRA, TCOMPRESSED type = case data.length when 0..160 0 when 161..8192 data = Zlib::Deflate.new.deflate(data, Zlib::FINISH) 1 else data = Zlib::Deflate.new.deflate(data, Zlib::FINISH) 1 #data = Bzip2.compress data #2 end whdr type, data.length wbin data end
Switch to stream mode. Stream mode turns off caching.
# File lib/boss-protocol.rb, line 140 def set_stream_mode @stream_mode = true whdr TYPE_EXTRA, XT_STREAM_MODE @cache = { nil => 0 } end
Switch to stream mode. Stream mode turns off caching.
# File lib/boss-protocol.rb, line 135 def stream_mode set_stream_mode end
Get the result as string, may not work if some specific IO instance is passed to constructor. works well with default constructor or StringIO
# File lib/boss-protocol.rb, line 238 def string @io.string end
Private Instance Methods
Write cache ref if the object is cached, and return true otherwise store object in the cache. Caller should write object to @io if notCached return true, and skip writing otherwise
# File lib/boss-protocol.rb, line 249 def notCached(obj) n = @cache[obj] if n whdr TYPE_CREF, n false else # Check stream mode, bin and strings only unless @stream_mode @cache[obj] = @cache.length end true end end
Determine minimum amount of bytes needed to store value (should be positive integer)
# File lib/boss-protocol.rb, line 298 def sizeBytes(value) checkArg value >= 0 mval = 0x100 cnt = 1 while value >= mval cnt += 1 mval <<= 8 end cnt end
write binary value
# File lib/boss-protocol.rb, line 312 def wbin(bb) @io.write bb end
write single byte
# File lib/boss-protocol.rb, line 318 def wbyte(b) @io << b.chr end
# File lib/boss-protocol.rb, line 322 def wdouble val wbin [val].pack('E') end
write standard record header with code and value
# File lib/boss-protocol.rb, line 277 def whdr(code, value) checkArg code.between?(0, 7) checkArg value >= 0 # p "WHDR #{code}, #{value}" if value < 23 wbyte code | value<<3 else # Get the size of the value (0..9) if (n=sizeBytes(value)) < 9 wbyte code | (n+22) << 3 else wbyte code | 0xF8 wrenc n end n.times { wbyte value & 0xff; value >>=8 } end end
Write variable-length positive integer
# File lib/boss-protocol.rb, line 265 def wrenc(value) checkArg value >= 0 while value > 0x7f wbyte value & 0x7f value >>= 7 end wbyte value | 0x80 end