module Sprockets::Utils

def benchmark_end(start_time)

def benchmark_end(start_time)
  ((Time.now.to_f - start_time) * 1000).to_i
end

def benchmark_start

def benchmark_start
  Time.now.to_f
end

def concat_javascript_sources(buf, source)

Returns appended buffer String.

asset - Asset
buf - String memo

semicolon if necessary.
Internal: Accumulate asset source to buffer and append a trailing
def concat_javascript_sources(buf, source)
  if string_end_with_semicolon?(buf)
    buf + source
  else
    buf + ";\n" + source
  end
end

def dfs(initial)

Returns a Set of nodes.

node - Current node to get children of
block -
initial - Initial Array of nodes to traverse.

Used for resolving asset dependencies.

Internal: Post-order Depth-First search algorithm.
def dfs(initial)
  nodes, seen = Set.new, Set.new
  stack = Array(initial).reverse
  while node = stack.pop
    if seen.include?(node)
      nodes.add(node)
    else
      seen.add(node)
      stack.push(node)
      stack.concat(Array(yield node).reverse)
    end
  end
  nodes
end

def hexdigest(obj)

Returns a String SHA1 digest of the object.

obj - A JSON serializable object.

Internal: Generate a hexdigest for a nested JSON serializable object.
def hexdigest(obj)
  digest = Digest::SHA1.new
  queue  = [obj]
  while queue.length > 0
    obj = queue.shift
    klass = obj.class
    if klass == String
      digest << 'String'
      digest << obj
    elsif klass == Symbol
      digest << 'Symbol'
      digest << obj.to_s
    elsif klass == Fixnum
      digest << 'Fixnum'
      digest << obj.to_s
    elsif klass == TrueClass
      digest << 'TrueClass'
    elsif klass == FalseClass
      digest << 'FalseClass'
    elsif klass == NilClass
      digest << 'NilClass'
    elsif klass == Array
      digest << 'Array'
      queue.concat(obj)
    elsif klass == Hash
      digest << 'Hash'
      queue.concat(obj.sort)
    elsif klass == Set
      digest << 'Set'
      queue.concat(obj.to_a)
    elsif klass == Encoding
      digest << 'Encoding'
      digest << obj.name
    else
      raise TypeError, "couldn't digest #{klass}"
    end
  end
  digest.hexdigest
end

def module_include(base, mod)

Returns result of block.

mod - Module

Internal: Inject into target module for the duration of the block.
def module_include(base, mod)
  old_methods = {}
  mod.instance_methods.each do |sym|
    old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym)
  end
  unless UNBOUND_METHODS_BIND_TO_ANY_OBJECT
    base.send(:include, mod) unless base < mod
  end
  mod.instance_methods.each do |sym|
    method = mod.instance_method(sym)
    base.send(:define_method, sym, method)
  end
  yield
ensure
  mod.instance_methods.each do |sym|
    base.send(:undef_method, sym) if base.method_defined?(sym)
  end
  old_methods.each do |sym, method|
    base.send(:define_method, sym, method)
  end
end

def normalize_extension(extension)


# => ".css"
normalize_extension(".css")

# => ".js"
normalize_extension("js")

Internal: Prepends a leading "." to an extension if its missing.
def normalize_extension(extension)
  extension = extension.to_s
  if extension[/^\./]
    extension
  else
    ".#{extension}"
  end
end

def string_end_with_semicolon?(str)

Returns true or false.

str - String

Internal: Check if string has a trailing semicolon.
def string_end_with_semicolon?(str)
  i = str.size - 1
  while i >= 0
    c = str[i]
    i -= 1
    if c == "\n" || c == " " || c == "\t"
      next
    elsif c != ";"
      return false
    else
      return true
    end
  end
  true
end