Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.ruby > #3011

Re: Get the real object in a Hash key

Path csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!news.albasani.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail
From Robert Klemme <shortcutter@googlemail.com>
Newsgroups comp.lang.ruby
Subject Re: Get the real object in a Hash key
Date Sat, 16 Apr 2011 18:15:03 +0200
Lines 154
Message-ID <90ttlnFn21U1@mid.individual.net> (permalink)
References <BANLkTin0FvFkx+kfvXuMxp3_7XkhqkiA_w@mail.gmail.com> <BANLkTi=dvQxGfycrsoyWUKchPQBMcybS0w@mail.gmail.com> <BANLkTikWQQfzFCjYx8SXtX2WREZ70AAodg@mail.gmail.com> <BANLkTi=0Xt-DpOzu9pK_3Ac4JoGD3cmNtA@mail.gmail.com> <de78d150786e2caeed0186e184fd2ae9@ruby-forum.com> <BANLkTikGRjioxL7M=jAt1-ZdNwNRCS6j+w@mail.gmail.com> <f1af2839cc53f0380580fd3e8b3bfa5b@ruby-forum.com> <BANLkTim3bC6sDr9rW40XyarPT50HoX6GKw@mail.gmail.com>
Mime-Version 1.0
Content-Type text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding quoted-printable
X-Trace individual.net gj1ocxBUuezOYYS4S+coSQdGa0/aPoCPYjXAy7hRXMXkAoHDM=
Cancel-Lock sha1:zcu8X6uk92rtFdsPoBeDmg7X3+k=
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.15) Gecko/20110303 Lightning/1.0b2 Thunderbird/3.1.9
In-Reply-To <BANLkTim3bC6sDr9rW40XyarPT50HoX6GKw@mail.gmail.com>
X-Antivirus avast! (VPS 110416-0, 16.04.2011), Outbound message
X-Antivirus-Status Clean
Xref x330-a1.tempe.blueboxinc.net comp.lang.ruby:3011

Show key headers only | View raw


On 16.04.2011 16:51, Iñaki Baz Castillo wrote:
> 2011/4/15 Kevin Mahler<kevin.mahler@yahoo.com>:
>> He has a key. It contains some
>> data. It's not necessarily true that he should duplicate that data in
>> the mapped-to values.
>
> To clarify, my exact case is the following:

Now it gets interesting. :-)

> I've coded a parser for SIP (similar to HTTP). The parser generates a
> Request object which inherits from Hash,

Usually it's better to use composition instead of inheritance to achieve 
this.  Now your SipRequest inherits *all* methods from Hash including 
some that you might not want users to be able to invoke.

> and each SIP request header
> (i.e. "From: sip:alice@example.org") becomes an entry of the hash
> (Request object) as follows:
>
> - The key is "FROM" (capitalized).
> - The value is an Array of strings (a s header can have multiple values).
>
> I need to store the key capitalized for fastest lookup, but I also
> want to store the original header name (which could be "from", "From",
> "frOM" and so).

So, to sum it up: you want to have a class for SIP request which allows 
(efficient) header field access through [] using header name in any case 
spelling.

> So my parser adds an instance variable @real_name within the header
> name string ("FROM").
>
> When I do the lookup of a header in the Request object, I would like
> also to retrieve the key's @real_name, but I've already understood
> that this is only possible if taint the key string before inserting it
> in the hash and use Hash#assoc. This solution is not good for
> performance.
>
> The solution suggested by Robert is adding such information (the
> header original name) as a field in the hash entry value, so instead
> of having:
>
>    request["FROM"]
>    =>  [ "sip:alice@xample.org ]
>
> I would end with something like:
>
>    request["FROM"]
>    =>  Struct ( "From", [ "sip:alice@xample.org ] )
>
> The problem this last suggestion introduces is that it breaks the
> existing API and makes more complext for a developer to handle the
> Request class (which should be as easy as handling a Hash).

Here's how I'd do it.  First, I would start with the interface, maybe 
something like this

module SIP
   class Request
     def self.parse(io)
       # ...
     end

     # get a header field by symbol
     def [](header_name_sym)
     end

     # return the real name used
     def header_name(header_name_sym)
     end
   end
end

Then I'd think how I could make that API work properly.  For example two 
variants, error and default value:

module SIP
   class Request
     HdrInfo = Struct.new name, values
     DUMMY = HdrInfo[nil, [].freeze].freeze
     LT = "\r\n".freeze

     def self.parse(io)
       hdr = {}

       io.each_line LT do |l|
         case l
         when /^([^:]+:\s*(.*)$/
           # too simplistic parsing!
           hdr[$1] = $2.split(/,/).each(&:strip!)
         when /^$/
           break
         else
           raise "Not a header line: %p" % l
         end
       end

       new(hdr)
     end

     def initialize(headers)
       @hdr = {}

       # assume hdr is String and values is parsed
       headers.each do |hdr, values|
         @hdr[normalize(hdr)] = HdrInfo[hdr, values]
       end
     end

     # get a header field by symbol
     def [](header_name_sym)
       @hdr.fetch(normalize(header_name_sym)) do |k|
         DUMMY
       end.values
     end

     # return the real name used
     def header_name(header_name_sym)
       @hdr.fetch(normalize(header_name_sym)).do |k|
         raise ArgumentError,
           "Header not found %p" % header_name_sym
       end.name
     end

   private
     def normalize(h)
       /[A-Z]/ =~ h ? h.downcase : h).to_sym
     end
   end
end

Of course we could build the internal hash straight away during parsing. 
  The main focus of the example was how to use the header once parsed.

> Thanks to both for your comments.

You're welcome.

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Back to comp.lang.ruby | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Get the real object in a Hash key Iñaki Baz Castillo <ibc@aliax.net> - 2011-04-15 07:50 -0500
  Re: Get the real object in a Hash key Robert Klemme <shortcutter@googlemail.com> - 2011-04-15 08:00 -0500
    Re: Get the real object in a Hash key Iñaki Baz Castillo <ibc@aliax.net> - 2011-04-15 08:14 -0500
      Re: Get the real object in a Hash key Robert Klemme <shortcutter@googlemail.com> - 2011-04-15 08:48 -0500
        Re: Get the real object in a Hash key Iñaki Baz Castillo <ibc@aliax.net> - 2011-04-15 09:46 -0500
        Re: Get the real object in a Hash key Kevin Mahler <kevin.mahler@yahoo.com> - 2011-04-15 09:47 -0500
          Re: Get the real object in a Hash key Robert Klemme <shortcutter@googlemail.com> - 2011-04-15 11:08 -0500
            Re: Get the real object in a Hash key Kevin Mahler <kevin.mahler@yahoo.com> - 2011-04-15 12:39 -0500
              Re: Get the real object in a Hash key Robert Klemme <shortcutter@googlemail.com> - 2011-04-16 15:20 +0200
              Re: Get the real object in a Hash key Iñaki Baz Castillo <ibc@aliax.net> - 2011-04-16 09:51 -0500
                Re: Get the real object in a Hash key Robert Klemme <shortcutter@googlemail.com> - 2011-04-16 18:15 +0200
                Re: Get the real object in a Hash key Iñaki Baz Castillo <ibc@aliax.net> - 2011-04-16 11:55 -0500
                Re: Get the real object in a Hash key Josh Cheek <josh.cheek@gmail.com> - 2011-04-16 11:17 -0500
  Re: Get the real object in a Hash key jake kaiden <jakekaiden@yahoo.com> - 2011-04-16 10:28 -0500

csiph-web