Skip to content

Commit

Permalink
Don't call length from substring
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed Nov 2, 2017
1 parent 24f8667 commit e80ac45
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 24 deletions.
Expand Up @@ -158,21 +158,21 @@ public int computeHash()
@Override @Override
public TextValue substring( int start, int length ) public TextValue substring( int start, int length )
{ {
int s = Math.min( start, length() ); if ( start < 0 || length < 0 )
int e = Math.min( s + length, length() );
byte[] values = bytes;
if ( s >= e )
{ {
return StringValue.EMTPY; throw new IndexOutOfBoundsException( "Cannot handle negative start index nor negative length" );
} }

int end = start + length;
byte[] values = bytes;
int count = 0, byteStart = -1, byteEnd = -1, i = offset, len = offset + byteLength; int count = 0, byteStart = -1, byteEnd = -1, i = offset, len = offset + byteLength;
while ( i < len ) while ( i < len )
{ {
if ( count == s ) if ( count == start )
{ {
byteStart = i; byteStart = i;
} }
if ( count == e ) if ( count == end )
{ {
byteEnd = i; byteEnd = i;
break; break;
Expand All @@ -196,9 +196,10 @@ public TextValue substring( int start, int length )
{ {
byteEnd = len; byteEnd = len;
} }

if ( byteStart < 0 )
assert byteStart >= 0; {
assert byteEnd >= byteStart; return StringValue.EMTPY;
}
return new UTF8StringValue( values, byteStart, byteEnd - byteStart ); return new UTF8StringValue( values, byteStart, byteEnd - byteStart );
} }


Expand Down
Expand Up @@ -48,7 +48,7 @@ public final class Values
public static final Value MAX_STRING = Values.booleanValue( false ); public static final Value MAX_STRING = Values.booleanValue( false );
public static final BooleanValue TRUE = Values.booleanValue( true ); public static final BooleanValue TRUE = Values.booleanValue( true );
public static final BooleanValue FALSE = Values.booleanValue( false ); public static final BooleanValue FALSE = Values.booleanValue( false );
public static final TextValue EMPTY_STRING = Values.stringValue( "" ); public static final TextValue EMPTY_STRING = StringValue.EMTPY;
public static final DoubleValue E = Values.doubleValue( Math.E ); public static final DoubleValue E = Values.doubleValue( Math.E );
public static final DoubleValue PI = Values.doubleValue( Math.PI ); public static final DoubleValue PI = Values.doubleValue( Math.PI );
public static final ArrayValue EMPTY_SHORT_ARRAY = Values.shortArray( new short[0] ); public static final ArrayValue EMPTY_SHORT_ARRAY = Values.shortArray( new short[0] );
Expand Down
Expand Up @@ -19,18 +19,22 @@
*/ */
package org.neo4j.values.storable; package org.neo4j.values.storable;


import org.junit.Rule;
import org.junit.Test; import org.junit.Test;

import org.junit.rules.ExpectedException;
import java.nio.charset.StandardCharsets;


import static java.lang.String.format; import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.neo4j.values.storable.Values.stringValue; import static org.neo4j.values.storable.Values.stringValue;
import static org.neo4j.values.storable.Values.utf8Value; import static org.neo4j.values.storable.Values.utf8Value;


public class UTF8StringValueTest public class UTF8StringValueTest
{ {
@Rule
public ExpectedException exception = ExpectedException.none();

private String[] strings = {"", "1337", " ", "普通话/普通話", "\uD83D\uDE21", " a b c ", "䤹᳽", "熨", "ۼ", private String[] strings = {"", "1337", " ", "普通话/普通話", "\uD83D\uDE21", " a b c ", "䤹᳽", "熨", "ۼ",
"ⲹ楡톜ഷۢ⼈늉₭샺ጚ砧攡跿家䯶鲏⬖돛犽ۼ", "ⲹ楡톜ഷۢ⼈늉₭샺ጚ砧攡跿家䯶鲏⬖돛犽ۼ",
" 㺂࿝鋦毠",//first character is a thin space, " 㺂࿝鋦毠",//first character is a thin space,
Expand All @@ -43,7 +47,7 @@ public void shouldHandleDifferentTypesOfStrings()
for ( String string : strings ) for ( String string : strings )
{ {
TextValue stringValue = stringValue( string ); TextValue stringValue = stringValue( string );
byte[] bytes = string.getBytes( StandardCharsets.UTF_8 ); byte[] bytes = string.getBytes( UTF_8 );
TextValue utf8 = utf8Value( bytes ); TextValue utf8 = utf8Value( bytes );
assertSame( stringValue, utf8 ); assertSame( stringValue, utf8 );
} }
Expand All @@ -55,7 +59,7 @@ public void shouldTrimDifferentTypesOfStrings()
for ( String string : strings ) for ( String string : strings )
{ {
TextValue stringValue = stringValue( string ); TextValue stringValue = stringValue( string );
byte[] bytes = string.getBytes( StandardCharsets.UTF_8 ); byte[] bytes = string.getBytes( UTF_8 );
TextValue utf8 = utf8Value( bytes ); TextValue utf8 = utf8Value( bytes );
assertSame( stringValue.trim(), utf8.trim() ); assertSame( stringValue.trim(), utf8.trim() );
} }
Expand All @@ -67,7 +71,7 @@ public void shouldLTrimDifferentTypesOfStrings()
for ( String string : strings ) for ( String string : strings )
{ {
TextValue stringValue = stringValue( string ); TextValue stringValue = stringValue( string );
byte[] bytes = string.getBytes( StandardCharsets.UTF_8 ); byte[] bytes = string.getBytes( UTF_8 );
TextValue utf8 = utf8Value( bytes ); TextValue utf8 = utf8Value( bytes );
assertSame( stringValue.ltrim(), utf8.ltrim() ); assertSame( stringValue.ltrim(), utf8.ltrim() );
} }
Expand All @@ -78,7 +82,7 @@ public void trimShouldBeSameAsLtrimAndRtrim()
{ {
for ( String string : strings ) for ( String string : strings )
{ {
TextValue utf8 = utf8Value( string.getBytes( StandardCharsets.UTF_8 ) ); TextValue utf8 = utf8Value( string.getBytes( UTF_8 ) );
assertSame( utf8.trim(), utf8.ltrim().rtrim() ); assertSame( utf8.trim(), utf8.ltrim().rtrim() );
} }
} }
Expand All @@ -87,7 +91,7 @@ public void trimShouldBeSameAsLtrimAndRtrim()
public void shouldSubstring() public void shouldSubstring()
{ {
String string = "ü"; String string = "ü";
TextValue utf8 = utf8Value( string.getBytes( StandardCharsets.UTF_8 ) ); TextValue utf8 = utf8Value( string.getBytes( UTF_8 ) );
assertThat( utf8.substring( 0, 1 ).stringValue(), equalTo( "ü" ) ); assertThat( utf8.substring( 0, 1 ).stringValue(), equalTo( "ü" ) );
} }


Expand All @@ -97,7 +101,7 @@ public void shouldRTrimDifferentTypesOfStrings()
for ( String string : strings ) for ( String string : strings )
{ {
TextValue stringValue = stringValue( string ); TextValue stringValue = stringValue( string );
byte[] bytes = string.getBytes( StandardCharsets.UTF_8 ); byte[] bytes = string.getBytes( UTF_8 );
TextValue utf8 = utf8Value( bytes ); TextValue utf8 = utf8Value( bytes );
assertSame( stringValue.rtrim(), utf8.rtrim() ); assertSame( stringValue.rtrim(), utf8.rtrim() );
} }
Expand All @@ -111,10 +115,10 @@ public void shouldCompareTo()
for ( String string2 : strings ) for ( String string2 : strings )
{ {


int x = stringValue( string1 ).compareTo( utf8Value( string2.getBytes( StandardCharsets.UTF_8 ) ) ); int x = stringValue( string1 ).compareTo( utf8Value( string2.getBytes( UTF_8 ) ) );
int y = utf8Value( string1.getBytes( StandardCharsets.UTF_8 ) ).compareTo( stringValue( string2 ) ); int y = utf8Value( string1.getBytes( UTF_8 ) ).compareTo( stringValue( string2 ) );
int z = utf8Value( string1.getBytes( StandardCharsets.UTF_8 ) ) int z = utf8Value( string1.getBytes( UTF_8 ) )
.compareTo( utf8Value( string2.getBytes( StandardCharsets.UTF_8 ) ) ); .compareTo( utf8Value( string2.getBytes( UTF_8 ) ) );


assertThat( x, equalTo( y ) ); assertThat( x, equalTo( y ) );
assertThat( x, equalTo( z ) ); assertThat( x, equalTo( z ) );
Expand All @@ -126,7 +130,7 @@ public void shouldCompareTo()
public void shouldHandleOffset() public void shouldHandleOffset()
{ {
// Given // Given
byte[] bytes = "abcdefg".getBytes( StandardCharsets.UTF_8 ); byte[] bytes = "abcdefg".getBytes( UTF_8 );


// When // When
TextValue textValue = utf8Value( bytes, 3, 2 ); TextValue textValue = utf8Value( bytes, 3, 2 );
Expand All @@ -144,4 +148,56 @@ private void assertSame( TextValue lhs, TextValue rhs )
assertThat( format( "%s.hashCode != %s.hashCode", rhs, lhs ), lhs.hashCode(), equalTo( rhs.hashCode() ) ); assertThat( format( "%s.hashCode != %s.hashCode", rhs, lhs ), lhs.hashCode(), equalTo( rhs.hashCode() ) );
assertThat( lhs, equalTo( rhs ) ); assertThat( lhs, equalTo( rhs ) );
} }

@Test
public void shouldHandleTooLargeStartPointInSubstring()
{
// Given
UTF8StringValue value = utf8Value( "hello".getBytes( UTF_8 ) );

// When
TextValue substring = value.substring( 8, 5 );

// Then
assertThat( substring, equalTo( StringValue.EMTPY ) );
}

@Test
public void shouldHandleTooLargeLengthInSubstring()
{
// Given
UTF8StringValue value = utf8Value( "hello".getBytes( UTF_8 ) );

// When
TextValue substring = value.substring( 3, 76 );

// Then
assertThat( substring.stringValue(), equalTo( "lo" ) );
}

@Test
public void shouldThrowOnNegativeStart()
{
// Given
UTF8StringValue value = utf8Value( "hello".getBytes( UTF_8 ) );

// Expect
exception.expect( IndexOutOfBoundsException.class );

// When
value.substring( -4, 3 );
}

@Test
public void shouldThrowOnNegativeLength()
{
// Given
UTF8StringValue value = utf8Value( "hello".getBytes( UTF_8 ) );

// Expect
exception.expect( IndexOutOfBoundsException.class );

// When
value.substring( 4, -3 );
}
} }

0 comments on commit e80ac45

Please sign in to comment.