Wednesday, September 30, 2009

Select unread mails in gmail.com

There were dozens of emails in my gmail inbox that I didn't bother to read. As time went by, they were immersed into the other thousands of emails. It was time to take some actions. Not that I wanted to read them this time, I just didn't want a number shown beside my inbox.

It was weird that gmail.com didn't have a button or link to select all the unread mails. Oh, wait, there was something right above all the listed mails -- "Select: All, None, Read, Unread, Starred, Unstarred". But I clicked the Unread link and nothing happened. That was because all those unread mails were too old to appear on the first page and the Unread link could only select mails on the first page.

To select those mails I wanted, there was an indirect way. Beside the gmail Search the Web button, there was a link in a tiny little font saying Show search options -- What did Google try to hide? LOL.

Clicked that link and a Search Options box showed up. Clicked the Search drop down list and select Unread Mail. Then clicked the Search Mail button and got all my unread mails listed. Then I could select all the Unread mails and mark them as read.

Tuesday, September 29, 2009

Source code conversion/formatting online tool for Blogger



If you want to post your source code in blogger.com, you may find out that some of the source code is not displayed correctly. That is because when you input a <, anything following it was treated as a tag untill a > was met. So before you post any text with &, < or >, you should convert them to &amp;, &lt; or &gt; respectively.

Here is a little tool written in Javascript to do the conversion for you:

Input:

Add <pre> tag     
Output:


I intended to make a tool for a reverse conversion as well. Then I realized that nobody would need it because the browser was already doing it. :D

Monday, September 28, 2009

Show/hide text on web page



+ What will we discuss today? (Click me.)


You want to make your web page neat and concise but you have too much information to share? You can achieve both by using the drop down text on your web page. Just write down several outlines and when the readers click on any of them, a hidden text block would be dropped down to shown the details.

To implement it, you need to use Javascript. Of course, your readers must enable Javascript in their browsers.

You can do it in simple three steps:

1. Add a Javascript function in your <head> block.
<script type="text/javascript">
function toggleShowHide(elementId) {
    var element = document.getElementById(elementId);
    if (element) {
        if (element.style.display == "none")
            element.style.display = "inline";
        else
            element.style.display = "none";
    }
}
</script>

This function accepts on argument elementId which is the unique id of the HTML element you want to toggle.

When the style.display attribute is set as inline, the HTML element is shown on the web page. When the attribute is set as none, the HTML element is hidden and it doesn't take up any space just like it doesn't exist.

2. Assign an id to the text block you want to hide initially. And hide it.
    <div id="hiddenText" style="display:none">The trick to include a drop down text in your web page.</div>

We assign hiddenText as the id of our hidden text block. We hide it by setting its style.display attribute as none.

3. Define the text the readers can click on to show the hidden text block.
    <p onClick="toggleShowHide('hiddenText')">+ What will we discuss today? (Click me.)</p>

Function toggleShowHide() will be called when this paragraph is clicked. By passing in the element id of hiddenText, which we assigned in step 2, the hidden text block can be dropped down or removed by clicking this paragraph.

Sunday, September 27, 2009

MySQL Connector/J exception on timestamp

If you are using MySQL JDBC driver in your Java program and the version is MySQL Connector/J 3.1, you might see this exception sometimes:

    Exception: Cannot convert value '0000-00-00 00:00:00' from column ... to TIMESTAMP.

The exception is thrown from mysql.jdbc.ResultSet and is caused by the datetime field with an all zero value '0000-00-00 00:00:00'.

Sometimes, you don't want to manually update all those datetime fields to actual time values. You just want your program to continue. The trick would be to set the zeroDateTimeBehavior property to round, which rounds the value to "0001-01-01 00:00:00":

    jdbc:mysql://localhost:3306/mydb?zeroDateTimeBehavior=round

Reference: http://dev.mysql.com/doc/refman/5.0/en/connector-j-installing-upgrading.html (search section Datetimes)

Saturday, September 26, 2009

A beautiful ...

Even Parity -- comparison of two algorithms

To set a ASCII character to even parity, we first count the number of bits with the value of 1. If the number is even, the ASCII character is already of even parity. Otherwise, we set the most significant bit of the ASCII character to 1 to make it even parity. The follow code (in Java) demonstrates that:

public static byte setEvenParity(byte b)
{
short countOne = 0;

if (0 != (b & 0x01)) ++countOne;
if (0 != (b & 0x02)) ++countOne;
if (0 != (b & 0x04)) ++countOne;
if (0 != (b & 0x08)) ++countOne;
if (0 != (b & 0x10)) ++countOne;
if (0 != (b & 0x20)) ++countOne;
if (0 != (b & 0x40)) ++countOne;

byte evenB = (1 == (countOne % 2)) ? (byte)(b | 0x80) : b;

return evenB;
}


Can we do a little improvement to it?

As we can see, when we convert the same byte twice, the same processes of checking and setting the most significant bit are repeated. What if we remember what we have done in the first time and apply the result to the second time. For example, the first time we see character 'T' whose binary form is "0101 0100", we check and find out that it has 3 bits with the value of 1. We then set its most significant bit as 1 to make it as "1101 0100". When we see 'T' again, we should know immediately that the output should be "1101 0100" without doing the checking again.

Or even better, if we already know who need setting even parity bit and who need not before we process any string. After all, there are only 128 ASCII characters. So all we need is a preset table. When we see character 'T', we check the table and get "1101 0111".

private static int[] withEvenParity = {
0x00,0x81,0x82,0x03,0x84,0x05,0x06,0x87,0x88,0x09,0x0A,0x8B,0x0C,0x8D,0x8E,0x0F,
0x90,0x11,0x12,0x93,0x14,0x95,0x96,0x17,0x18,0x99,0x9A,0x1B,0x9C,0x1D,0x1E,0x9F,
0xA0,0x21,0x22,0xA3,0x24,0xA5,0xA6,0x27,0x28,0xA9,0xAA,0x2B,0xAC,0x2D,0x2E,0xAF,
0x30,0xB1,0xB2,0x33,0xB4,0x35,0x36,0xB7,0xB8,0x39,0x3A,0xBB,0x3C,0xBD,0xBE,0x3F,
0xC0,0x41,0x42,0xC3,0x44,0xC5,0xC6,0x47,0x48,0xC9,0xCA,0x4B,0xCC,0x4D,0x4E,0xCF,
0x50,0xD1,0xD2,0x53,0xD4,0x55,0x56,0xD7,0xD8,0x59,0x5A,0xDB,0x5C,0xDD,0xDE,0x5F,
0x60,0xE1,0xE2,0x63,0xE4,0x65,0x66,0xE7,0xE8,0x69,0x6A,0xEB,0x6C,0xED,0xEE,0x6F,
0xF0,0x71,0x72,0xF3,0x74,0xF5,0xF6,0x77,0x78,0xF9,0xFA,0x7B,0xFC,0x7D,0x7E,0xFF,
};

public static byte fasterSetEvenParity(byte b)
{
int i = b & 0x7f;

byte evenB = (byte)withEvenParity[i];

return evenB;
}


Note: we can use the first algorithm to generate the withEvenParity[] array.

Is the second algorithm really faster? I ran a little test with this program and the result below.

public static void main(String arg[])
{
String s = "This is a test string.";

byte[] bytes = s.getBytes();

for (int i = 0; i < 100000000; ++i)
{
for (int j = 0; j < bytes.length; ++j)
{
byte result =
setEvenParity(bytes[j]);
//fasterSetEvenParity(bytes[j]);

if (0 == i)
System.out.print(Integer.toHexString(bytes[j] & 0xff)
+ ":" + Integer.toHexString(result & 0xff) + " ");
}
}

System.out.println();
}


Using the first algorithm, the running time of the program is:

real 0m23.156s
user 0m22.863s
sys 0m0.015s


Using the second algorithm, the running time of the program is:

real 0m6.838s
user 0m6.692s
sys 0m0.026s


Yeah! The faster one is really faster.

Read my other post of Print byte in hex with the similar idea to speed things up.

Friday, September 25, 2009

Print byte in hex -- comparison of two algorithms

One byte contains 8 bits, or two nibbles. To represents a byte in hex, each nibble is given a hexadecimal digit in 0-9 and A-F. For example, character 'Z' whose binary value is "0101 1010" is presented as "5A".

The most obvious way to print a byte in hex format is to first grab the most significant nibble and print it as the corresponding hexadecimal digit. And then do the same thing to the least significant nibble. This will lead to the following piece of code (in Java):


static String[] hexChar = {
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "A", "B", "C", "D", "E", "F"};

public static String byteToHex(byte b)
{
String result = hexChar[(b >> 4) & 0x0f] + hexChar[b & 0x0f];

return result;
}


It looks so simple and straightforward, who would want to improve it? Well, there is something we can play with.

You may realize that there are totally 256 bytes. After we call the byteToHex() function 256 times, we know we would do some repeated work to split the byte into nibbles and find out the value of each nibble. If we can remember what we have done before, we can tell immediately that character 'Z' will be represent as "5A" without splitting the byte into two nibble to find out that the most significant nibble can be printed as '5' and the least significant nibble can be printed as 'A'. Based on the idea, we have another piece of code:

static String[] hexStr = {
"00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
"10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
"20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
"30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
"40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
"60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
"70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
"80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
"90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
"B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
"C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
"D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
"E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF",
};

public static String fasterByteToHex(byte b)
{
String result = hexStr[(short)b & 0x00ff];

return result;
}


The hexStr[] array is big so I use a small program to generate it. Once it has been generated, it is there. We also want to declare it as static because if it were temparory inside the fasterByteToHex() function, it would be built each time the function is called. That would give out worse performance.

Now, let's test whether the so call faster something is really faster with the program below:

public static void main(String arg[])
{
String s = "This is a test string.";

byte[] bytes = s.getBytes();

for (int i = 0; i < 10000000; i++)
{
String res = "";

for (int j = 0; j < bytes.length; j++)
{
String inHex =
byteToHex(bytes[j]);
//fasterByteToHex(bytes[j]);

if (0 == i)
res += inHex;
}

if (0 == i)
System.out.println(res);
}
}


It turned out that with the first straightforward solution, the running time was:

real 0m25.696s
user 0m25.339s
sys 0m0.170s


And the "faster" algorithm had the running time of:

real 0m0.691s
user 0m0.664s
sys 0m0.025s


The so called faster something is really much faster.

Read my other post of Even parity with the similar idea to speed things up.

Thursday, September 24, 2009

Run GUI applications as another user in Linux

Supposed user1 wants to run a gnome-terminal as user2. He needs to do these:

1. Login as root (or ask root to help) to setup the sudoers. Run visudo and add these:
user1 ALL = (user2) NOPASSWD:ALL
Note: This grants user1 to do any good or harm to user2's account. You may want to limit the commands user1 can run.

2. Create a shell script with these lines:
xhost +SI:localuser:user2
sudo -u user2 -H gnome-terminal
xhost -SI:localuser:user2


3. Run the script and you will get a gnome-terminal popped up, which is owned by user2.

Some notes:
  • The manpage of xhost implies that you can add a user name by typing "xhost +user2". That is not true. You must use ServerInterpreted to add a user. Otherwise you will get an error of "xhost: bad hostname user2".
  • If you are getting "cannot open display" error, it may be that your environmental variables are reset by sudo. If that is the case, you need to add this to the sudoers:
Defaults env_keep="DISPLAY XAUTHORITY"