On Feb 16, 2013, at 07:48, David Heller wrote:

> Here is the actual php code I'm trying to convert to nodejs:

Sorry for not responding sooner. I've looked at this code a couple times over 
the past two weeks and it was somewhat hard to understand given the use of 
$GLOBALS and eval(), and also because it's incomplete.

The closing curly brace on line 19 doesn't match anything. I'm guessing that 
there were lines omitted at the beginning of this listing that define a 
function -- or rather a method, since the use of $this suggests we're in a 
class definition.

Not sure what its arguments are, but there are several variables being used 
here that I've not seen defined, including $name, $rule, $dat_file, $server and 
$port. Sounds like this makes a connection to some server -- or returns an 
object for an existing connection. So let's say:

function connect($name, $rule, $dat_file, $server, $port) {

> if(in_array($name, $this->m_names))
>         {
>             $this->m_rules[$name][] = $rule;
>             return $GLOBALS[$name];
>         }

m_names is a member of the current object. It's a numerically-indexed array of 
strings, where each string is the name of a global variable containing a 
GTCM_GNP object. The purpose of the array seems to be to indicate whether an 
object has already been created with this name. If the string $name is in the 
m_names array, then it is assumed that there is an element $name in the m_rules 
array, and that there is a global variable whose name is the contents of the 
$name variable. In other words, if $name is the string "foo", then we assume 
there is a global variable $foo. The regular expression $rule is appended to 
the list of rules for this name in the m_rules array, then the object in the 
global variable is returned. 

If the name was not in the m_names array, then the object hasn't been created 
yet and needs to be created:

>         $cmd = "\$$name = new GTCM_GNP(\$dat_file, \$server, \$port);";
>         eval($cmd);

This creates a new GTCM_GNP object and assigns it to the variable whose name is 
the contents of the $name variable.

I don't see why this trickery with the variable name is being done. According 
to the documentation for eval, this should just be creating a local variable 
with this name -- a local variable which is returned at the end of this method. 
Therefore any arbitrary temporary variable name could have been used.

Furthermore it is completely unclear to me why eval() is being used here. It 
doesn't appear to me to be necessary at all or to add anything of value.

But there's no other place in the code you've shown where this variable gets 
promoted to a global. So perhaps this code actually makes a global variable, 
despite what the documentation says. If so, there's still no need for eval; you 
can just assign to $GLOBALS[$name] directly.

In nodejs JavaScript, you wouldn't want to use globals at all; you could just 
define a private object in your module and store the objects in there as you 
make them.

>         if(!$$name)
>         {
>             $err_msg = "Cannot register, GTCM_GNP constructor failure.";
>             catch(throw(__FILE__, __LINE__, "register", 1, $err_msg));
>             return FALSE;
>         }

If the new variable is empty, meaning the object could not be created, an error 
is thrown.

>         $this->m_cnt++;

This counter is incremented, presumably a count of how many objects have been 
created.

>         $this->m_names[] = $name;

The string $name is appended to the m_names array, as an indicator that this 
global variable now exists.

>         $this->m_rules[$name] = array($rule);

The array of rules for $name is created with a single element: the regular 
expression $rule.

>         return $$name;

The new object is returned.

>     }

It's unclear why $GLOBALS or eval() were needed at all. It seems as though 
using a string-indexed array -- as was done for the m_rules array -- would have 
worked just as well. In JavaScript, this would be called an object instead of 
an array.


>     function lookUp($gvn_name)
>     {
>         foreach($this->m_rules as $name => $rule)
>             foreach($rule as $r)
>                 if(ereg($r, $gvn_name))
>                     return $name;        
>         return null;
>     }

This looks through all the rules for all the objects, and returns the name of 
the object that has a rule matching the $gvn_name variable. This uses the old 
deprecated ereg regular expression syntax: http://php.net/ereg ; Use of the 
newer PCRE regular expression syntax is recommended in PHP. JavaScript regular 
expressions are also PCRE-based.


>     /* Usage: $dir->unregister("db1"); */
>     function unregister($name)
>     {
>         if(!in_array($name, $this->m_names))
>             return;
>         $rule = $this->m_rules[$name];
>         $this->m_rules = array_diff($this->m_rules, array($rule));
>         $this->m_names = array_diff($this->m_names, array($name));
>         $this->m_cnt--;
> }

It looks like this removes all the rules associated with the $name object, and 
removes it from the m_names array and decrements the count of objects -- but 
does not actually delete the global variable containing the object itself.


So it seems to be a bad / incomplete attempt at object orientation. What you 
really want is a single container to hold all your connections. Inside that 
container you'd have objects which contain each connection's connection object 
and its rules. Here's some code that seems to work, which I saved as 
connectionManager.js:


var GTCM_GNP = require('./GTCM_GNP');

var connections = {};
var count = 0;

exports.connect = function (name, rule, dat_file, server, port) {
  if (connections[name]) {
    connections[name].rules.push(rule);
    return connections[name].connection;
  }
  var newConnection = new GTCM_GNP(dat_file, server, port);
  count++;
  connections[name] = {
    connection: newConnection,
    rules: [rule]
  };
  return newConnection;
};

exports.lookUp = function (gvn_name) {
  var names = Object.keys(connections);
  for (var i = 0; i < count; i++) {
    var name = names[i];
    if (connections[name].rules.some(function(rule) {
      return rule.test(gvn_name);
    })) return name;
  }
  return null;
};

exports.unregister = function (name) {
  if (!connections[name]) return;
  delete connections[name];
  count--;
};


To test it out I made an index.js like this:


var cm = require('./connectionManager.js');

var conn1 = cm.connect('example', /hello/, 'foo.txt', 'localhost', 5555);
var conn2 = cm.connect('example', /world/, 'foo.txt', 'localhost', 5555);
var conn3 = cm.connect('something', /another/, 'bar.txt', '192.168.99.999', 
6666);

console.log(cm.lookUp("I say hello"));
console.log(cm.lookUp("You say goodbye"));
console.log(cm.lookUp('This is another one'));

cm.unregister('example');

console.log(cm.lookUp("I say hello"));
console.log(cm.lookUp("You say goodbye"));
console.log(cm.lookUp('This is another one'));

cm.unregister('something');

console.log(cm.lookUp("I say hello"));
console.log(cm.lookUp("You say goodbye"));
console.log(cm.lookUp('This is another one'));


And a GTCM_GNP.js like this:


function GTCM_GNP(dat_file, server, port) {
  this.dat_file = dat_file;
  this.server = server;
  this.port = port;
  console.log('made a new GTCM_GNP object, dat_file ' + dat_file + ', server ' 
+ server + ', port ' + port);
}

module.exports = GTCM_GNP;

-- 
-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

--- 
You received this message because you are subscribed to the Google Groups 
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to