Butterfly in Perl command line "}{"

I recently came to know about this and I thought its worth sharing. I will try to keep it very simple.
Lets say I have a file as below:
1
2
3
4
5
I need to join all the lines with a pipe so that my output should look like below:
1|2|3|4|5
Normally I use the below command to achieve the same:
perl -lne 'push @a,$_;END{print join "|",@a}' File
Now, here's another option for you below:
perl -lne 'push @a,$_;}{ print join "|",@a' File
The change here is:
}{
This is called butterfly option in perl. Basically it closes while loop imposed by -n switch, and what follows }{ is block executed after while loop.

Restrict a java text field length

There are many different way to do this. You might write your own once you figure out what has to be done exactly. But I came up with this. Additionally I wanted the input to be numeric as well. So below is what I came up with.
private class NumericAndLengthFilter extends DocumentFilter {

        /**
         * Number of characters allowed.
         */
        private int length = 0;

        /**
         * Restricts the number of charcacters can be entered by given length.
         * @param length Number of characters allowed.
         */
        public NumericAndLengthFilter(int length) {
            this.length = length;
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String string,
                AttributeSet attr) throws
                BadLocationException {
            if (isNumeric(string)) {
                if (this.length > 0 && fb.getDocument().getLength() + string.
                        length()
                        > this.length) {
                    return;
                }
                super.insertString(fb, offset, string, attr);
            }
        }

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text,
                AttributeSet attrs) throws
                BadLocationException {
            if (isNumeric(text)) {
                if (this.length > 0 && fb.getDocument().getLength() + text.
                        length()
                        > this.length) {
                    return;
                }
                super.insertString(fb, offset, text, attrs);
            }
        }

        /**
         * This method tests whether given text can be represented as number.
         * This method can be enhanced further for specific needs.
         * @param text Input text.
         * @return {@code true} if given string can be converted to number; otherwise returns {@code false}.
         */
        private boolean isNumeric(String text) {
            if (text == null || text.trim().equals("")) {
                return false;
            }
            for (int iCount = 0; iCount < text.length(); iCount++) {
                if (!Character.isDigit(text.charAt(iCount))) {
                    return false;
                }
            }
            return true;
        }
    }
}

Restricting a Java Text field to just a range of integers

This time I came across a slightly different way than extending the documentfilter. That is I will write my own plain document here.
class IntegerRangeDocument extends PlainDocument {

  int minimum, maximum;

  int currentValue = 0;

  public IntegerRangeDocument(int minimum, int maximum) {
    this.minimum = minimum;
    this.maximum = maximum;
  }

  public int getValue() {
    return currentValue;
  }

  public void insertString(int offset, String string, AttributeSet attributes)
      throws BadLocationException {

    if (string == null) {
      return;
    } else {
      String newValue;
      int length = getLength();
      if (length == 0) {
        newValue = string;
      } else {
        String currentContent = getText(0, length);
        StringBuffer currentBuffer = new StringBuffer(currentContent);
        currentBuffer.insert(offset, string);
        newValue = currentBuffer.toString();
      }
      try {
        currentValue = checkInput(newValue);
        super.insertString(offset, string, attributes);
      } catch (Exception exception) {
        Toolkit.getDefaultToolkit().beep();
      }
    }
  }

  public void remove(int offset, int length) throws BadLocationException {
    int currentLength = getLength();
    String currentContent = getText(0, currentLength);
    String before = currentContent.substring(0, offset);
    String after = currentContent.substring(length + offset, currentLength);
    String newValue = before + after;
    try {
      currentValue = checkInput(newValue);
      super.remove(offset, length);
    } catch (Exception exception) {
      Toolkit.getDefaultToolkit().beep();
    }
  }

  public int checkInput(String proposedValue) throws NumberFormatException {
    int newValue = 0;
    if (proposedValue.length() > 0) {
      newValue = Integer.parseInt(proposedValue);
    }
    if ((minimum <= newValue) && (newValue <= maximum)) {
      return newValue;
    } else {
      throw new NumberFormatException();
    }
  }
}
Now you can attach your text field with this plain document as below to achieve our requirement.

Document rangeOne = new IntegerRangeDocument(0, 255);
JTextField textFieldOne = new JTextField();
textFieldOne.setDocument(rangeOne);
    

Restricting a Java Text field to alphabet

This is slightly opposite to what we have seen  in one of the previous posts
Please use the below DocumentFilter for the same.


class MyDocFilter extends DocumentFilter {
   private static final String REMOVE_REGEX = "\\d";
   private boolean filter = true;

   public boolean isFilter() {
      return filter;
   }

   public void setFilter(boolean filter) {
      this.filter = filter;
   }

   @Override
   public void insertString(FilterBypass fb, int offset, String text,
         AttributeSet attr) throws BadLocationException {
      if (filter) {
         text = text.replaceAll(REMOVE_REGEX, "");
      }
      super.insertString(fb, offset, text, attr);

   }

   @Override
   public void replace(FilterBypass fb, int offset, int length, String text,
         AttributeSet attrs) throws BadLocationException {
      if (filter) {
         text = text.replaceAll(REMOVE_REGEX, "");
      }
      super.replace(fb, offset, length, text, attrs);

   }
}

Restricting a Java Text field to Integers

I have read a lot for this and the best way I found to do this is by extending the DocumentFilter class and using this new DocumentFilter
class MyIntFilter extends DocumentFilter {
   @Override
   public void insertString(FilterBypass fb, int offset, String string,
         AttributeSet attr) throws BadLocationException {

      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.insert(offset, string);

      if (test(sb.toString())) {
         super.insertString(fb, offset, string, attr);
      } else {
         // warn the user and don't allow the insert
      }
   }

   private boolean test(String text) {
      try {
         Integer.parseInt(text);
         return true;
      } catch (NumberFormatException e) {
         return false;
      }
   }

   @Override
   public void replace(FilterBypass fb, int offset, int length, String text,
         AttributeSet attrs) throws BadLocationException {

      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.replace(offset, offset + length, text);

      if (test(sb.toString())) {
         super.replace(fb, offset, length, text, attrs);
      } else {
         // warn the user and don't allow the insert
      }

   }

   @Override
   public void remove(FilterBypass fb, int offset, int length)
         throws BadLocationException {
      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.delete(offset, offset + length);

      if (test(sb.toString())) {
         super.remove(fb, offset, length);
      } else {
         // warn the user and don't allow the insert
      }

   }
}
Now after this use this filter with your JtextField like below:
PlainDocument doc = (PlainDocument) textField.getDocument();
doc.setDocumentFilter(new MyIntFilter());

A new addition to this blog - Java

I recently started working on Java and so from now on I would like to share all the interesting things that I have come across about this beautiful programming language. So I am starting a new tag by name JAVA in this blog which will direct all the posts related to java. Happy coding to myself and all.

Searching multiple strings in multiple files in a directory

I have a list of strings in a file separated by a new line.
for example:
input.txt
temp1
temp2
temp3
Now I have a directory with multiple dat files like:
>ls -1 *.dat
one.dat
two.dat
three.dat
And many more dat like like above with random names. Now I want to search for all the strings in input.txt in all the dat files present in  directory(let's say current working directory).This is what I came up with:
create a perl script given below and name it as anything you wish(I named here as temp.pl).place the file input.txt in the current working directory.
#!/usr/bin/perl -w

open (INP,"input.txt") or die $!;
while(<INP>)
{
my $cmd="find . -name \"*.dat\"|xargs grep -w -i $_";
my $output=`$cmd`;
 if($output!~/^\s*$/)
 {
 print $_."\n";
 print "------------------\n";
 print $output."\n";
 print "-------------------\n";
 }
}
exit;
Run this script as :
>./temp.pl
This solved my need.I hope it solves yours too :)

Creating a graph using STL's in C++

Below is a implementation of Graph Data Structure in C++ as Adjacency List.

I have used STL vector for representation of vertices and STL pair for denoting edge and destination vertex.



struct vertex{
 typedef pair ve;
 vector adj; //cost of edge, destination vertex
 string name;
 vertex(string s)
 {
  name=s;
 }
};

class graph
{
 public:
  typedef map vmap;
  vmap work;
  void addvertex(const string&);
  void addedge(const string& from, const string& to, double cost);
};

void graph::addvertex(const string &name)
{
 vmap::iterator itr=work.begin();
 itr=work.find(name);
 if(itr==work.end())
 {
  vertex *v;
  v= new vertex(name);
  work[name]=v;
  return;
 }
  cout<<"\nVertex already exists!";
}

void graph::addedge(const string& from, const string& to, double cost)
{
 vertex *f=(work.find(from)->second);
 vertex *t=(work.find(to)->second);
 pair edge = make_pair(cost,t);
 f->adj.push_back(edge);
}

Finding Memory leaks in C++ on solaris Unix

There are lot of ways where one can identify memory leaks and lots of blogs and materieals
are available to help a designer to identify the same.

Some say using dbx and others say use mdb or gdb. I agree that all those tools will be useful, but it takes a lot of effort for understanding as well as putting it to work takes some time.

I have thought to break the legacy rules and do something new with the knowledge that
I have on various tools of solaris. So I thought of giving it a try to use tools like
dtrace, perl, ps command etc along with c++.

Putting this toll to action is an effort less job.

I am happy to have created a tool which I think would be very use for any solaris unix programmer.
This tool will give the list of all memory leaks of a process running in the background.

It uses dtrace to identify the memory allocations,
It uses the ps command to identify the memory used by a process.
It uses perl to filter and generate reports of meory leaks.

Main functionalities of this tool are:

  • Generate a report which contains actual physical memory used by the process, Virtual memory used, % of cpu used and %memory used.
  • Generate a report which contains all the memory leaks of the process due to inefficient coding techniques.
  • Generate a separate report for each and every process.

I have tested this on:
SunOS 5.10 Generic_147440-27 sun4u sparc SUNW,SPARC-Enterprise

Thanks to Frederic, I have taken part of his logic written in his blog:

You can download the zip file from the link here:

The file name is cpuleaks.gz.
Unzip this file using gzip -d cpuleaks.gz and you can place it on any server and give the execute permissions and run this process as a root user(dtrace can be run only using root access on my server. If dtrace can be used by a user other than root, well and fine).

Execution of the process should be as below:
 

cpuleaks <comma separated pid list> -st <time interval for mem usage>
 
ex: cpuleaks 1234,2341 -st 2

This above command will give 4 files as output after either the processes 1234,2341 complete or if you press CTRL +C(an interrupt signal).
1234.cpumem
1234.leaks
2341.cpumem
2341.leaks

 
where
  • .leaks report will have the list of all memory leaks
  • .cpumem report will have the memory usage of the process for every interval passed as an argument to the cpuleaks binary.

Search Multiple strings and print them in the order of search strings

One of my colleagues asked this query to me. And I liked the query very much.
So I started thinking about that.
For example i have a below file:
1 name1
2 name2
3 name3
4 name1
5 name4
6 name2
7 name1
Now i want to find strings in the file , lets say in the order name1, name2, name3, name4.
And i also want the output to be in the same order in the way i searched as below:
1 name1
4 name1
7 name1
2 name2
6 name2
3 name3
5 name4
Obviously we cannot do this with a single grep command without any temporary files being created.
So I thought perl would be a better option for this. So I came up with a simple perl solution.
perl -lne '/name1/?push @a,$_:
          (/name2/?push @b,$_:
          (/name3/?push @c,$_:
           /name4/?push @d,$_:next));
          END{print join "\n",@a,@b,@c,@d}' your_file

And this worked like a a charm.