about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2017-03-02 04:08:23 +0000
committerEric Wong <e@80x24.org>2017-03-02 04:08:43 +0000
commitf4c2ac4825f99ec4af529d65ae98abfaf034fb0f (patch)
treebbae58219dc4d158c033b892e0a7da67a969ecdc
parentc2e04a5715d4cfa2b42fa09ba1f641d3ce741685 (diff)
downloaddtas-f4c2ac4825f99ec4af529d65ae98abfaf034fb0f.tar.gz
This is faster than relying on eval() for older Rubies.
https://bugs.ruby-lang.org/issues/13077
Ruby 2.5 is targetted for release in December 2017.
-rw-r--r--lib/dtas.rb13
-rw-r--r--lib/dtas/fadefx.rb2
-rw-r--r--lib/dtas/mlib.rb10
-rw-r--r--lib/dtas/partstats.rb3
-rw-r--r--lib/dtas/player.rb2
-rw-r--r--lib/dtas/player/client_handler.rb5
-rw-r--r--lib/dtas/rg_state.rb2
-rw-r--r--lib/dtas/source/av_ff_common.rb8
-rw-r--r--lib/dtas/source/sox.rb7
9 files changed, 34 insertions, 18 deletions
diff --git a/lib/dtas.rb b/lib/dtas.rb
index 1a1a882..ac416d7 100644
--- a/lib/dtas.rb
+++ b/lib/dtas.rb
@@ -24,6 +24,19 @@ module DTAS
   def self.null # :nodoc:
     @null ||= File.open('/dev/null', 'r+')
   end
+
+  # String#-@ will deduplicate strings when Ruby 2.5 is released (Dec 2017)
+  # https://bugs.ruby-lang.org/issues/13077
+  if RUBY_VERSION.to_f >= 2.5
+    def self.dedupe_str(str)
+      -str
+    end
+  else
+    # Ruby 2.1 - 2.4, noop for older Rubies
+    def self.dedupe_str(str)
+      eval "#{str.inspect}.freeze"
+    end
+  end
   # :startdoc:
 end
 
diff --git a/lib/dtas/fadefx.rb b/lib/dtas/fadefx.rb
index aca6c68..1a00653 100644
--- a/lib/dtas/fadefx.rb
+++ b/lib/dtas/fadefx.rb
@@ -95,7 +95,7 @@ class DTAS::FadeFX # :nodoc:
   def parse!(str)
     return nil if str.empty?
     type = "t"
-    str.sub!(/\A([a-z])/, "") and type = $1.freeze
+    str.sub!(/\A([a-z])/, "") and type = DTAS.dedupe_str($1)
     F.new(type, parse_time(str))
   end
 end
diff --git a/lib/dtas/mlib.rb b/lib/dtas/mlib.rb
index dbd46da..0945153 100644
--- a/lib/dtas/mlib.rb
+++ b/lib/dtas/mlib.rb
@@ -190,7 +190,9 @@ class DTAS::Mlib # :nodoc:
       tag_id = tag_map[x] and tag_map["#{x}number"] = tag_id
     end
     @tag_rmap = tag_map.invert.freeze
-    tag_map.merge!(Hash[*(tag_map.map { |k,v| [k.upcase.freeze, v] }.flatten!)])
+    tag_map.merge!(Hash[*(tag_map.map { |k,v|
+      [DTAS.dedupe_str(k.upcase), v]
+    }.flatten!)])
     @tag_map = tag_map.freeze
   end
 
@@ -400,7 +402,7 @@ class DTAS::Mlib # :nodoc:
     return '/' if base == '' # root_node
     parent_id = node[:parent_id]
     base += '/' unless node[:tlen] >= 0
-    ppath = cache[parent_id] and return "#{ppath}/#{base}"
+    ppath = cache[parent_id] and return DTAS.dedupe_str("#{ppath}/#{base}")
     parts = []
     begin
       node = @db[:nodes][id: node[:parent_id]]
@@ -408,9 +410,9 @@ class DTAS::Mlib # :nodoc:
       parts.unshift node[:name]
     end while true
     parts.unshift('')
-    cache[parent_id] = parts.join('/')
+    cache[parent_id] = DTAS.dedupe_str(parts.join('/'))
     parts << base
-    parts.join('/').freeze
+    DTAS.dedupe_str(parts.join('/'))
   end
 
   def emit_recurse(node, cache, cb)
diff --git a/lib/dtas/partstats.rb b/lib/dtas/partstats.rb
index f9f2116..1037c87 100644
--- a/lib/dtas/partstats.rb
+++ b/lib/dtas/partstats.rb
@@ -173,8 +173,7 @@ becomes:
       else
         next
       end
-      key = $1
-      key.freeze
+      key = DTAS.dedupe_str($1)
       key_idx = @key_idx[key]
       parts = line.split(/\s+/)
       nshift.times { parts.shift } # remove stuff we don't need
diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb
index 45a1da8..37f2c96 100644
--- a/lib/dtas/player.rb
+++ b/lib/dtas/player.rb
@@ -168,7 +168,7 @@ class DTAS::Player # :nodoc:
 
       if sinks = hash["sinks"]
         sinks.each do |sink_hsh|
-          sink_hsh['name'].freeze
+          sink_hsh['name'] = DTAS.dedupe_str(sink_hsh['name'])
           sink = DTAS::Sink.load(sink_hsh)
           sink.env = to_omap(sink.env)
           @sinks[sink.name] = sink
diff --git a/lib/dtas/player/client_handler.rb b/lib/dtas/player/client_handler.rb
index b17e90b..1e4ac96 100644
--- a/lib/dtas/player/client_handler.rb
+++ b/lib/dtas/player/client_handler.rb
@@ -3,6 +3,7 @@
 # frozen_string_literal: true
 require_relative '../xs'
 require_relative '../parse_time'
+require_relative '../../dtas'
 
 # client protocol handling for -player
 module DTAS::Player::ClientHandler # :nodoc:
@@ -134,7 +135,7 @@ module DTAS::Player::ClientHandler # :nodoc:
       # or variable names.
       sink.valid_name?(name) or return io.emit("ERR sink name invalid")
 
-      sink.name = name.freeze
+      sink.name = DTAS.dedupe_str(name)
       active_before = sink.active
       before = __sink_snapshot(sink)
 
@@ -143,7 +144,7 @@ module DTAS::Player::ClientHandler # :nodoc:
         k, v = kv.split('=', 2)
         case k
         when %r{\Aenv\.([^=]+)\z}
-          sink.env[$1] = v
+          sink.env[DTAS.dedupe_str($1)] = v
         when %r{\Aenv#([^=]+)\z}
           v == nil or return io.emit("ERR unset env has no value")
           sink.env.delete($1)
diff --git a/lib/dtas/rg_state.rb b/lib/dtas/rg_state.rb
index 7af67e1..6b2c718 100644
--- a/lib/dtas/rg_state.rb
+++ b/lib/dtas/rg_state.rb
@@ -72,7 +72,7 @@ class DTAS::RGState # :nodoc:
     when 1 then return 'gain 192'
     else
       val.abs <= 0.00000001 and return
-      sprintf('gain %0.8f', val).freeze
+      DTAS.dedupe_str(sprintf('gain %0.8f', val))
     end
   end
 
diff --git a/lib/dtas/source/av_ff_common.rb b/lib/dtas/source/av_ff_common.rb
index d89ea17..ae654ba 100644
--- a/lib/dtas/source/av_ff_common.rb
+++ b/lib/dtas/source/av_ff_common.rb
@@ -109,13 +109,17 @@ module DTAS::Source::AvFfCommon # :nodoc:
       f = $1.dup
       f =~ /^duration=([\d\.]+)\s*$/nm and @duration = $1.to_f
       # TODO: multi-line/multi-value/repeated tags
-      f.gsub!(/^TAG:([^=]+)=(.*)$/ni) { |_| @comments[$1.upcase.freeze] = $2 }
+      f.gsub!(/^TAG:([^=]+)=(.*)$/ni) { |_|
+        @comments[DTAS.dedupe_str($1.upcase)] = DTAS.dedupe_str($2)
+      }
     end
 
     # new avprobe
     s.scan(%r{^\[format\.tags\]\n(.*?)\n\n}m) do |_|
       f = $1.dup
-      f.gsub!(/^([^=]+)=(.*)$/ni) { |_| @comments[$1.upcase.freeze] = $2 }
+      f.gsub!(/^([^=]+)=(.*)$/ni) { |_|
+        @comments[DTAS.dedupe_str($1.upcase)] = DTAS.dedupe_str($2)
+      }
     end
     s.scan(%r{^\[format\]\n(.*?)\n\n}m) do |_|
       f = $1.dup
diff --git a/lib/dtas/source/sox.rb b/lib/dtas/source/sox.rb
index 7f55c5d..f702b41 100644
--- a/lib/dtas/source/sox.rb
+++ b/lib/dtas/source/sox.rb
@@ -52,19 +52,16 @@ class DTAS::Source::Sox # :nodoc:
 
       if out =~ /\nComments\s*:[ \t]*\n?(.*)\z/mn
         comments = dst['comments'] = {}
-        # we use eval "#{str.inspect}".freeze
-        # take advantage of the VM-wide dedupe in MRI (rb_fstring):
         key = nil
         $1.split(/\n/n).each do |line|
           if line.sub!(/^([^=]+)=/ni, '')
-            key = $1.upcase
-            key = eval "#{key.inspect}.freeze"
+            key = DTAS.dedupe_str($1.upcase)
           end
           (comments[key] ||= ''.b) << "#{line}\n" unless line.empty?
         end
         comments.each do |k,v|
           v.chomp!
-          comments[k] = eval "#{v.inspect}.freeze"
+          comments[k] = DTAS.dedupe_str(v)
         end
       end
       dst