Port PHP’s str_pad to JavaScript

September 3, 2009 – 11:11 pm

Today I needed a function that pads a string to a certain length with another string. In PHP this function is called str_pad. Unfortunately JavaScript doesn’t have such function and I decided to write it myself.

Much to my surpise that was interesting becuase in so short and simple function it is possible  to make a lot of performance mistakes.

The requirements for this function is the same as for PHP’s function, so it is an analog.

So, how was it ?

When I developed my first version of this function I decided to test it for performance. I’ve developed a small test script that executes this function 3000 times with different parameters. For all tests I used Firefox with Firebug’s Profiler. First test was taking about 1.1 seconds.

I decided to look around for similar solutions. I looked at PHP’s sources and founded there few good ideas. Then I’ve found a very nice site with already ported analog and I tried to test it too :)

Wow the result was much better than mine. This task was taking about 600ms.

Eventually I merged 3 ideas and I’ve added some tricks about string’s concatenation. I run a test again and now it takes only 147ms.

This function was improved significantly comparing with 1st time. Almost in 10 times.

Here is the source code:

01
String.PAD_LEFT  = 0;
02
String.PAD_RIGHT = 1;
03
String.PAD_BOTH  = 2;
04
 
05
String.prototype.str_pad = function(length, string, type)
06
{
07
    if (undefined == type)
08
    {
09
        type = String.PAD_RIGHT;
10
    }
11
    else if (type < String.PAD_LEFT || type > String.PAD_BOTH)
12
    {
13
        return false;
14
    }
15
 
16
    if (undefined == string)
17
    {
18
        string = " ";
19
    }
20
 
21
    if (length <= 0 || (this.length - length) >= 0)
22
    {
23
        return false;
24
    }
25
 
26
    if ("string" != typeof(string))
27
    {
28
        string = new String(string);
29
    }
30
 
31
    var num_pad_chars = length - this.length,
32
        pad_left  = 0,
33
        pad_right = 0;
34
 
35
    switch(type)
36
    {
37
        case String.PAD_LEFT:
38
            pad_left  = num_pad_chars;
39
            pad_right = 0;
40
            break;
41
 
42
        case String.PAD_RIGHT:
43
            pad_left  = 0;
44
            pad_right = num_pad_chars;
45
            break;
46
 
47
        case String.PAD_BOTH:
48
            pad_left  = Math.floor(num_pad_chars / 2);
49
            pad_right = num_pad_chars - pad_left;
50
            break;
51
    }
52
 
53
    var left_mu = Math.ceil(pad_left/string.length);
54
    var left = [];
55
    while(left_mu)
56
    {
57
        left.push(string);
58
        left_mu--;
59
    }
60
    left = left.join("").substr(0, pad_left);
61
 
62
    var right_mu = Math.ceil(pad_right/string.length);
63
    var right = [];
64
    while(right_mu)
65
    {
66
        right.push(string);
67
        right_mu--;
68
    }
69
    right = right.join("").substr(0, pad_right);
70
 
71
 
72
    return left + this + right;
73
}

and some tests:

01
var a = "123456";
02
var b = "0";
03
 
04
print(a.str_pad(10, b));
05
print(a.str_pad(10, b, String.PAD_LEFT));
06
print(a.str_pad(10, b, String.PAD_RIGHT));
07
print(a.str_pad(10, b, String.PAD_BOTH));
08
 
09
print("---------------------");
10
 
11
print(a.str_pad(9, b));
12
print(a.str_pad(9, b, String.PAD_LEFT));
13
print(a.str_pad(9, b, String.PAD_RIGHT));
14
print(a.str_pad(9, b, String.PAD_BOTH));
15
 
16
print("--------------------");
17
 
18
var b = "0A";
19
print(a.str_pad(9, b));
20
print(a.str_pad(9, b, String.PAD_LEFT));
21
print(a.str_pad(9, b, String.PAD_RIGHT));
22
print(a.str_pad(9, b, String.PAD_BOTH));
23
 
24
print("----------------------");
25
 
26
print(a.str_pad(9, b, 10));
27
 
28
print("----------------------");
29
var a = "3";
30
var b = 0x18;
31
 
32
print(a.str_pad(9, b));
33
 
34
print("----------------------");
35
 
36
var a = 3; //error, unknown method
37
var b = 0x18;
38
 
39
print(a.str_pad(9, b));
40
print(a.str_pad(9, b, String.PAD_LEFT));
41
print(a.str_pad(9, b, String.PAD_RIGHT));
42
print(a.str_pad(9, b, String.PAD_BOTH));

Small JavaScript’s trick about Date object.

June 18, 2009 – 4:08 pm

Today I’ve found one more trick about JavaScript and I think it will be interesting for someone else.

So, how do you usually get timestamp value with JavaScript?
I used the following code:

1
2
var timestamp = Math.round(new Date().getTime()/1000);
3

As you might know Firefox has its own function to get timestamp named now, so you can do static call like this:

1
2
var timestamp = Math.round(Date.now()/1000);
3

In this case you aren’t creating a new Date object. That is a good point.

But, what can we do for the rest browsers? Of course we can use known construction (see above). However there is one more possible construction:

1
2
var timestamp = Math.round(+new Date/1000);
3

As we see this construction is shorter. How does it work?
When script calls +new Date the script creates new Date object and makes a call to valueOf method of Date object.
In turn the valueOf method returns the number of milliseconds since midnight 01 January, 1970 UTC, so it is an equivalent to the getTime method.

I’ve check it with performance and they work identical.

Here is updated variant:

1
2
function timestamp()
3
{
4
    return Math.round((Date.now &&Date.now() || +new Date)/1000);
5
}
6

Enjoy it!

PHP TestFest 2009

June 11, 2009 – 11:14 pm

You might know that PHP TestFest 2009 is still continuing.

I want to participate in this event as it is one of my favorite programming languages. I tried to find user group from Ukraine but I didn’t. It looks like nobody from Ukraine wants to improve it and its a pity.

elePHPants

Actually you don’t need to know C++ and it is enough to have your PHP knowledges. Of course you have to be an expert in PHP.

If you are interested you can start reading this page which explains how to write tests.

As a result if your test cases will be approved by mentor your tests will be committed to PHP CVS and you might get official PHP.net accounts with direct commit access to cvs.php.net and an @php.net email address. Yep! That’s not all - you will get elePHPant as a small present :)

Please contact me if you are interested and we can make a UA user group!

Where do we go?

June 8, 2009 – 11:05 am

Today I’ve seen a new movie called HOME.

I am so affected by this movie and all people have to watch it. It explains in which situation the people live now and how we’ve been killing ourself for over 50 years.

Yes, for the last 50 years we’ve changed the Earth and we are about to destroy the nature, animals, everything that has been built for thousands years.

Here is a home page of that movie and here is a russian version.

This movie is going to be online till 14 June, so don’t postpone and watch it right now.

How to build patch for Pidgin by yourself

July 3, 2008 – 8:52 pm

As you may know the company AOL has raised the protocol version from ICQ5 to ICQ6 and this caused connection problems for some ICQ clients. In this article I am explaining how to patch your pidgin by yourself.

  • First of all we need to install the following packages: build-essential, fakeroot and devscripts

 sudo apt-get install devscripts build-essential fakeroot

  • Download the sources of libpurple0 because we need to patch this library

 apt-get source libpurple0

  • Download the patch and get patched the library

 wget http://launchpadlibrarian.net/15741199/pidgin-2.4.2-icq.patch

 tar xzf pidgin_2.4.1.orig.tar.gz

 cd pidgin-2.4.1/

 patch -p0 < ../pidgin-2.4.2-icq.patch

  • Set the dependences

 sudo apt-get build-dep libpurple0

  • Rebuild the package

 debuild -us -uc

  • Install patched package

 cd ..

sudo dpkg -i libpurple0_2.4.1-1ubuntu2_i386.deb

You can get an amd version instead of i386 depending of your platform

  • Reload your pidgin and be happy

php/simplexml and namespace in rdf

April 4, 2007 – 12:07 pm

Using simplexml ext to parse rdf file.

The problem:
For example we have next rdf file:

<?xml version="1.0" encoding="utf-8"?>

<item rdf:about="http://someurl">
<title>my title </title>

<rdf:RDF>

<description>my desc </description>

<dc:date>March, 10 </dc:date>

</item>

</rdf:RDF>


some.php :


<?php

$rdf = simplexml_load_file($path2Rdf);

foreach ($rdf->item as $item)

echo $item->date;

?>



But this code doesn’t work, because element “date” has a namespace prefix of “dc”, so the script doesn’t have access to this namespace.


Solution:

Firstly, we should define the namespace in rdf file:

<rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”

xmlns=”http://purl.org/rss/1.0/” xmlns:dc=”http://purl.org/dc/elements/1.1/”>



and secondly, we should use "children" method to get a collection of elements which belong to "dc" namespace:

<?php

$dc = $item->children('http://purl.org/dc/elements/1.1/');

echo $dc->date;

?>

Professional programmer

March 29, 2007 – 10:43 am

I found a good article about programmer levels. This article shows the points what a professional programmer should have.

Project management

March 22, 2007 – 2:49 am

The other day i have read a fascinating novel about project management. I suppose any manager and developer should read this book independently of specialization and experience.
This book tells about people and their relations, phases of development and ordering, rules of staff recruitment, problems during developing and methods to solve them and a lot of other helpful advices.

php interface

March 21, 2007 – 11:26 pm

Today i was writing next code:

interface iTest 
{ 
    function testMe($x); 
}

class Test implements iTest  
{    
    public function testMe($x, $y="World")
    {          
        print $x . $y;      
    }
}

$test = new Test();
$test->testMe("Hello ");

The declaration of method in class differs from interface.
I was surprised at this situation because php doesn’t generate any errors.