Skip to content

Commit

Permalink
zero copy split
Browse files Browse the repository at this point in the history
  • Loading branch information
yuzawa-san committed Jul 26, 2024
1 parent 02f53c4 commit 8bac901
Show file tree
Hide file tree
Showing 37 changed files with 188 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.iab.gpp.encoder.section.EncodableSection;
import com.iab.gpp.encoder.section.HeaderV1;
import com.iab.gpp.encoder.section.Sections;
import com.iab.gpp.encoder.section.SlicedCharSequence;
import com.iab.gpp.encoder.section.TcfCaV1;
import com.iab.gpp.encoder.section.TcfEuV2;
import com.iab.gpp.encoder.section.UsCaV1;
Expand Down Expand Up @@ -285,14 +286,14 @@ protected Map<String, EncodableSection> decodeModel(String str) {
Map<String, EncodableSection> sections = new HashMap<>();

if(str != null && !str.isEmpty()) {
String[] encodedSections = str.split("~");
HeaderV1 header = new HeaderV1(encodedSections[0]);
List<CharSequence> encodedSections = SlicedCharSequence.split(str, '~');
HeaderV1 header = new HeaderV1(encodedSections.get(0));
sections.put(HeaderV1.NAME, header);

@SuppressWarnings("unchecked")
List<Integer> sectionIds = (List<Integer>) header.getFieldValue("SectionIds");
for (int i = 0; i < sectionIds.size(); i++) {
String section = encodedSections[i + 1];
CharSequence section = encodedSections.get(i + 1);
switch (sectionIds.get(i)) {
case TcfEuV2.ID:
sections.put(TcfEuV2.NAME, new TcfEuV2(section));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public String encode(String bitString) {
return str.toString();
}

public BitString decode(String str) {
public BitString decode(CharSequence str) {
int length = str.length();
BitStringBuilder sb = new BitStringBuilder(length * BASE64_BITS);
for (int i = 0; i < length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private void decodeSegmentFromBitString(String[] segment, BitString segmentBitSt
public abstract String encode() throws EncodingException;

@Override
public abstract void decode(String encodedString) throws DecodingException;
public abstract void decode(CharSequence encodedString) throws DecodingException;

@Override
public abstract int getId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public abstract class AbstractLazilyEncodableSection implements EncodableSection

private List<EncodableSegment> segments;

private String encodedString = null;
private CharSequence encodedString = null;

private boolean dirty = false;
private boolean decoded = true;
Expand All @@ -21,7 +21,7 @@ public AbstractLazilyEncodableSection() {

protected abstract String encodeSection(List<EncodableSegment> segments);

protected abstract List<EncodableSegment> decodeSection(String encodedString);
protected abstract List<EncodableSegment> decodeSection(CharSequence encodedString);

public boolean hasField(String fieldName) {
if (!this.decoded) {
Expand Down Expand Up @@ -73,16 +73,16 @@ public void setFieldValue(String fieldName, Object value) {
}

public String encode() {
if (this.encodedString == null || this.encodedString.isEmpty() || this.dirty) {
if (this.encodedString == null || this.encodedString.length() == 0 || this.dirty) {
this.encodedString = this.encodeSection(this.segments);
this.dirty = false;
this.decoded = true;
}

return this.encodedString;
return this.encodedString.toString();
}

public void decode(String encodedString) {
public void decode(CharSequence encodedString) {
this.encodedString = encodedString;
this.dirty = false;
this.decoded = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ public interface EncodableSection {

String encode();

void decode(String encodedString);
void decode(CharSequence encodedString);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public HeaderV1() {
super();
}

public HeaderV1(String encodedString) {
public HeaderV1(CharSequence encodedString) {
super();
decode(encodedString);
}
Expand All @@ -43,15 +43,15 @@ protected List<EncodableSegment> initializeSegments() {
}

@Override
protected List<EncodableSegment> decodeSection(String encodedString) {
protected List<EncodableSegment> decodeSection(CharSequence encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
if(encodedString != null && encodedString.length() > 0) {
List<CharSequence> encodedSegments = SlicedCharSequence.split(encodedString, '.');

for(int i=0; i<segments.size(); i++) {
if(encodedSegments.length > i) {
segments.get(i).decode(encodedSegments[i]);
for (int i=0; i<segments.size(); i++) {
if (encodedSegments.size() > i) {
segments.get(i).decode(encodedSegments.get(i));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.iab.gpp.encoder.section;

import java.util.ArrayList;
import java.util.List;

public final class SlicedCharSequence implements CharSequence {

private final CharSequence base;
private final int start;
private final int end;

private SlicedCharSequence(CharSequence base, int start, int end) {
this.base = base;
this.start = start;
this.end = end;
}

public static List<CharSequence> split(CharSequence charSequence, char splitter) {
List<CharSequence> out = new ArrayList<>(1);
int length = charSequence.length();
int start = 0;
for (int i = 0; i < length; i++) {
if (charSequence.charAt(i) == splitter) {
out.add(new SlicedCharSequence(charSequence, start, i));
start = i + 1;
}
}
out.add(new SlicedCharSequence(charSequence, start, length));
return out;
}

@Override
public int length() {
return end - start;
}

@Override
public char charAt(int index) {
return base.charAt(start + index);
}

@Override
public CharSequence subSequence(int newStart, int newEnd) {
return base.subSequence(start + newStart, start + newEnd);
}

@Override
public String toString() {
return base.subSequence(start, end).toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public TcfCaV1() {
super();
}

public TcfCaV1(String encodedString) {
public TcfCaV1(CharSequence encodedString) {
super();
decode(encodedString);
}
Expand All @@ -50,12 +50,12 @@ protected List<EncodableSegment> initializeSegments() {
}

@Override
public List<EncodableSegment> decodeSection(String encodedString) {
public List<EncodableSegment> decodeSection(CharSequence encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
for (int i = 0; i < encodedSegments.length; i++) {
if (encodedString != null && encodedString.length() > 0) {
List<CharSequence> encodedSegments = SlicedCharSequence.split(encodedString, '.');
for (int i = 0; i < encodedSegments.size(); i++) {

/**
* The first 3 bits contain the segment id. Rather than decode the entire string, just check the first character.
Expand All @@ -68,16 +68,16 @@ public List<EncodableSegment> decodeSection(String encodedString) {
* for the encoding version which only coincidentally works here because the version value is less than 8.
*/

String encodedSegment = encodedSegments[i];
if(!encodedSegment.isEmpty()) {
CharSequence encodedSegment = encodedSegments.get(i);
if (encodedSegment.length() > 0) {
char firstChar = encodedSegment.charAt(0);

if(firstChar >= 'A' && firstChar <= 'H') {
segments.get(0).decode(encodedSegments[i]);
segments.get(0).decode(encodedSegment);
} else if(firstChar >= 'I' && firstChar <= 'P') {
segments.get(2).decode(encodedSegments[i]);
segments.get(2).decode(encodedSegment);
} else if((firstChar >= 'Y' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'f')) {
segments.get(1).decode(encodedSegments[i]);
segments.get(1).decode(encodedSegment);
} else {
throw new DecodingException("Invalid segment '" + encodedSegment + "'");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public TcfEuV2() {
super();
}

public TcfEuV2(String encodedString) {
public TcfEuV2(CharSequence encodedString) {
super();
decode(encodedString);
}
Expand All @@ -51,12 +51,12 @@ protected List<EncodableSegment> initializeSegments() {
}

@Override
public List<EncodableSegment> decodeSection(String encodedString) {
public List<EncodableSegment> decodeSection(CharSequence encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
for (int i = 0; i < encodedSegments.length; i++) {
if (encodedString != null && encodedString.length() > 0) {
List<CharSequence> encodedSegments = SlicedCharSequence.split(encodedString, '.');
for (int i = 0; i < encodedSegments.size(); i++) {

/**
* The first 3 bits contain the segment id. Rather than decode the entire string, just check the first character.
Expand All @@ -70,19 +70,19 @@ public List<EncodableSegment> decodeSection(String encodedString) {
* for the encoding version which only coincidentally works here because the version value is less than 8.
*/

String encodedSegment = encodedSegments[i];
if(!encodedSegment.isEmpty()) {
CharSequence encodedSegment = encodedSegments.get(i);
if (encodedSegment.length() > 0) {
char firstChar = encodedSegment.charAt(0);

// unfortunately, the segment ordering doesn't match the segment ids
if(firstChar >= 'A' && firstChar <= 'H') {
segments.get(0).decode(encodedSegments[i]);
segments.get(0).decode(encodedSegment);
} else if(firstChar >= 'I' && firstChar <= 'P') {
segments.get(3).decode(encodedSegments[i]);
segments.get(3).decode(encodedSegment);
} else if(firstChar >= 'Q' && firstChar <= 'X') {
segments.get(2).decode(encodedSegments[i]);
segments.get(2).decode(encodedSegment);
} else if((firstChar >= 'Y' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'f')) {
segments.get(1).decode(encodedSegments[i]);
segments.get(1).decode(encodedSegment);
} else {
throw new DecodingException("Invalid segment '" + encodedSegment + "'");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public UsCaV1() {
super();
}

public UsCaV1(String encodedString) {
public UsCaV1(CharSequence encodedString) {
super();
decode(encodedString);
}
Expand All @@ -44,19 +44,19 @@ protected List<EncodableSegment> initializeSegments() {
}

@Override
protected List<EncodableSegment> decodeSection(String encodedString) {
protected List<EncodableSegment> decodeSection(CharSequence encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
if (encodedString != null && encodedString.length() > 0) {
List<CharSequence> encodedSegments = SlicedCharSequence.split(encodedString, '.');

if(encodedSegments.length > 0) {
segments.get(0).decode(encodedSegments[0]);
if (encodedSegments.size() > 0) {
segments.get(0).decode(encodedSegments.get(0));
}

if(encodedSegments.length > 1) {
if (encodedSegments.size() > 1) {
segments.get(1).setFieldValue(UsCaV1Field.GPC_SEGMENT_INCLUDED, true);
segments.get(1).decode(encodedSegments[1]);
segments.get(1).decode(encodedSegments.get(1));
} else {
segments.get(1).setFieldValue(UsCaV1Field.GPC_SEGMENT_INCLUDED, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public UsCoV1() {
super();
}

public UsCoV1(String encodedString) {
public UsCoV1(CharSequence encodedString) {
super();
decode(encodedString);
}
Expand All @@ -44,19 +44,19 @@ protected List<EncodableSegment> initializeSegments() {
}

@Override
protected List<EncodableSegment> decodeSection(String encodedString) {
protected List<EncodableSegment> decodeSection(CharSequence encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
if (encodedString != null && encodedString.length() > 0) {
List<CharSequence> encodedSegments = SlicedCharSequence.split(encodedString, '.');

if(encodedSegments.length > 0) {
segments.get(0).decode(encodedSegments[0]);
if (encodedSegments.size() > 0) {
segments.get(0).decode(encodedSegments.get(0));
}

if(encodedSegments.length > 1) {
if (encodedSegments.size() > 1) {
segments.get(1).setFieldValue(UsCoV1Field.GPC_SEGMENT_INCLUDED, true);
segments.get(1).decode(encodedSegments[1]);
segments.get(1).decode(encodedSegments.get(1));
} else {
segments.get(1).setFieldValue(UsCoV1Field.GPC_SEGMENT_INCLUDED, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public UsCtV1() {
super();
}

public UsCtV1(String encodedString) {
public UsCtV1(CharSequence encodedString) {
super();
decode(encodedString);
}
Expand All @@ -44,19 +44,19 @@ protected List<EncodableSegment> initializeSegments() {
}

@Override
protected List<EncodableSegment> decodeSection(String encodedString) {
protected List<EncodableSegment> decodeSection(CharSequence encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
if (encodedString != null && encodedString.length() > 0) {
List<CharSequence> encodedSegments = SlicedCharSequence.split(encodedString, '.');

if(encodedSegments.length > 0) {
segments.get(0).decode(encodedSegments[0]);
if (encodedSegments.size() > 0) {
segments.get(0).decode(encodedSegments.get(0));
}

if(encodedSegments.length > 1) {
if (encodedSegments.size() > 1) {
segments.get(1).setFieldValue(UsCtV1Field.GPC_SEGMENT_INCLUDED, true);
segments.get(1).decode(encodedSegments[1]);
segments.get(1).decode(encodedSegments.get(1));
} else {
segments.get(1).setFieldValue(UsCtV1Field.GPC_SEGMENT_INCLUDED, false);
}
Expand Down
Loading

0 comments on commit 8bac901

Please sign in to comment.