Skip to content

Commit

Permalink
Making Java implementation thread safe, avoding creating unecessary s…
Browse files Browse the repository at this point in the history
…trings, change form ifs to switches on char variables
  • Loading branch information
mauricio committed Sep 4, 2012
1 parent a635459 commit b163938
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 113 deletions.
193 changes: 99 additions & 94 deletions ext/pg_array_parser/PgArrayParserEngine.java
Original file line number Diff line number Diff line change
@@ -1,113 +1,118 @@
package pgarrayparser;

import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyString;
import org.jruby.RubyNil;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyMethod;
import org.jruby.*;
import org.jruby.anno.JRubyClass;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.BasicLibraryService;

@JRubyClass(name = "PgArrayParser::PgArrayParserEngine")
public class PgArrayParserEngine extends RubyObject {
@JRubyClass(name = "PgArrayParser::PgArrayParserEngine")
public class PgArrayParserEngine extends RubyObject {

public PgArrayParserEngine(final Ruby runtime, RubyClass rubyClass) {
super(runtime, rubyClass);
super(runtime, rubyClass);
}

private Ruby runtime;
private int index;
private String arrayString;
@JRubyMethod(name = "parse_pg_array")
public IRubyObject parse_pg_array(ThreadContext context, IRubyObject value) {
runtime = context.getRuntime();
index = 1;
arrayString = value.asJavaString();
IRubyObject returnValue = readArray();
return returnValue;

public RubyArray parse_pg_array( ThreadContext context, IRubyObject value) {
String content = value.asJavaString();
return parseData(context, content, 0);
}

private RubyArray readArray()
private static RubyArray parseData( ThreadContext context, String content, int index)
{
RubyArray array = RubyArray.newArray(runtime, 1);

int openQuote = 0;
boolean escapeNext = false;
char currentChar;
StringBuilder word = new StringBuilder();

if(index < arrayString.length() && arrayString.charAt(index) == '}')
{
return array;
}

for(;index < arrayString.length(); ++index)
{
currentChar = arrayString.charAt(index);
if(openQuote < 1)
{
if(currentChar == ',' || currentChar == '}')
{
if(!escapeNext)
{
if(openQuote == 0 && word.length() == 4 && word.toString().equals("NULL"))
{
array.append(runtime.getNil());
}
else
{
array.append(RubyString.newString(runtime, word.toString()));
}
}
if(currentChar == '}')
{
return array;
RubyArray items = RubyArray.newArray(context.getRuntime());

for( int x = index; x < content.length(); x++ ) {

char token = content.charAt(x);

switch (token) {
case '{':
x = parseArrayContents( context, items, content, x + 1 );
break;
case '}':
return items;
}
escapeNext = false;
openQuote = 0;
word = new StringBuilder();
}
else if(currentChar == '"')
{
openQuote = 1;
}
else if(currentChar == '{')
{
index++;
array.append(readArray());
escapeNext = true;
}
else
{
word.append(String.valueOf(currentChar));
}
}
else if(escapeNext)
{
word.append(String.valueOf(currentChar));
escapeNext = false;
}
else if(currentChar == '\\')
{
escapeNext = true;

}
else if(currentChar == '"')
{
openQuote = -1;

return items;
}

private static int parseArrayContents( ThreadContext context, RubyArray items, String content, int index ) {

StringBuilder currentItem = new StringBuilder();
boolean isEscaping = false;
boolean isQuoted = false;
boolean wasQuoted = false;

int x = index;

for(; x < content.length(); x++ ) {

char token = content.charAt(x);

if ( isEscaping ) {
currentItem.append( token );
isEscaping = false;
} else {
if ( isQuoted ) {
switch (token) {
case '"':
isQuoted = false;
wasQuoted = true;
break;
case '\\':
isEscaping = true;
break;
default:
currentItem.append(token);
}
} else {
switch (token) {
case '\\':
isEscaping = true;
break;
case ',':
addItem(context, items, currentItem, wasQuoted);
currentItem = new StringBuilder();
wasQuoted = false;
break;
case '"':
isQuoted = true;
break;
case '{':
RubyArray internalItems = RubyArray.newArray(context.getRuntime());
x = parseArrayContents( context, internalItems, content, x + 1 );
items.add(internalItems);
break;
case '}':
addItem(context, items, currentItem, wasQuoted);
return x;
default:
currentItem.append(token);
}
}
}

}
else
{
word.append(String.valueOf(currentChar));

return x;
}

private static void addItem( ThreadContext context, RubyArray items, StringBuilder builder, boolean quoted ) {
String value = builder.toString();

if ( value.length() == 0 ) {
return;
}
}

return array;
if ( !quoted && "NULL".equalsIgnoreCase( value ) ) {
items.add(context.getRuntime().getNil());
} else {
items.add(RubyString.newString( context.getRuntime(), value ));
}
}
}

}
32 changes: 13 additions & 19 deletions ext/pg_array_parser/PgArrayParserEngineService.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
package pgarrayparser;

import java.lang.Long;
import java.io.IOException;

import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.BasicLibraryService;

import java.io.IOException;

public class PgArrayParserEngineService implements BasicLibraryService {

public boolean basicLoad(Ruby runtime) throws IOException {
public boolean basicLoad(Ruby runtime) throws IOException {

RubyModule pgArrayParser = runtime.defineModule("PgArrayParser");
RubyClass pgArrayParserEngine = pgArrayParser.defineClassUnder("PgArrayParserEngine", runtime.getObject(), new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
return new PgArrayParserEngine(runtime, rubyClass);
}
});
RubyModule pgArrayParser = runtime.defineModule("PgArrayParser");
RubyClass pgArrayParserEngine = pgArrayParser.defineClassUnder("PgArrayParserEngine", runtime.getObject(), new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
return new PgArrayParserEngine(runtime, rubyClass);
}
});

pgArrayParserEngine.defineAnnotatedMethods(PgArrayParserEngine.class);
return true;
}
}
pgArrayParserEngine.defineAnnotatedMethods(PgArrayParserEngine.class);
return true;
}
}
Binary file modified lib/pg_array_parser.jar
Binary file not shown.

0 comments on commit b163938

Please sign in to comment.