-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from mauricio/thread-safe-jruby
Thread safety for Java implementation some optimizations
- Loading branch information
Showing
3 changed files
with
112 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 )); | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.