Skip to content

Commit

Permalink
Tidied up Nullable array values
Browse files Browse the repository at this point in the history
  • Loading branch information
jhy committed Aug 12, 2024
1 parent b731fd7 commit 55e50b9
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 27 deletions.
1 change: 0 additions & 1 deletion src/main/java/org/jsoup/helper/HttpConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,6 @@ public String header(String name) {
@Override
public T addHeader(String name, @Nullable String value) {
Validate.notEmptyParam(name, "name");
//noinspection ConstantConditions
value = value == null ? "" : value;

List<String> values = headers(name);
Expand Down
68 changes: 42 additions & 26 deletions src/main/java/org/jsoup/nodes/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public class Attributes implements Iterable<Attribute>, Cloneable {

// the number of instance fields is kept as low as possible giving an object size of 24 bytes
private int size = 0; // number of slots used (not total capacity, which is keys.length)
String[] keys = new String[InitialCapacity];
Object[] vals = new Object[InitialCapacity]; // Genericish: all non-internal attribute values must be Strings and are cast on access.
@Nullable String[] keys = new String[InitialCapacity]; // keys is not null, but contents may be. Same for vals
@Nullable Object[] vals = new Object[InitialCapacity]; // Genericish: all non-internal attribute values must be Strings and are cast on access.
// todo - make keys iterable without creating Attribute objects

// check there's room for more
Expand Down Expand Up @@ -119,7 +119,7 @@ public String get(String key) {
@return the Attribute for this key, or null if not present.
@since 1.17.2
*/
public Attribute attribute(String key) {
@Nullable Attribute attribute(String key) {
int i = indexOfKey(key);
return i == NotFound ? null : new Attribute(key, checkNotNull(vals[i]), this);
}
Expand Down Expand Up @@ -182,6 +182,7 @@ Map<String, Object> userData() {
//noinspection unchecked
userData = (Map<String, Object>) vals[i];
}
assert userData != null;
return userData;
}

Expand Down Expand Up @@ -218,7 +219,9 @@ void putIgnoreCase(String key, @Nullable String value) {
int i = indexOfKeyIgnoreCase(key);
if (i != NotFound) {
vals[i] = value;
if (!keys[i].equals(key)) // case changed, update
String old = keys[i];
assert old != null;
if (!old.equals(key)) // case changed, update
keys[i] = key;
}
else
Expand Down Expand Up @@ -389,15 +392,18 @@ public Range.AttributeRange sourceRange(String key) {

@Override
public Iterator<Attribute> iterator() {
return new Iterator<Attribute>() {
//noinspection ReturnOfInnerClass
return new Iterator<>() {
int expectedSize = size;
int i = 0;

@Override
public boolean hasNext() {
checkModified();
while (i < size) {
if (isInternalKey(keys[i])) // skip over internal keys
String key = keys[i];
assert key != null;
if (isInternalKey(key)) // skip over internal keys
i++;
else
break;
Expand All @@ -410,7 +416,9 @@ public boolean hasNext() {
public Attribute next() {
checkModified();
if (i >= size) throw new NoSuchElementException();
final Attribute attr = new Attribute(keys[i], (String) vals[i], Attributes.this);
String key = keys[i];
assert key != null;
final Attribute attr = new Attribute(key, (String) vals[i], Attributes.this);
i++;
return attr;
}
Expand All @@ -434,9 +442,11 @@ public void remove() {
public List<Attribute> asList() {
ArrayList<Attribute> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
if (isInternalKey(keys[i]))
String key = keys[i];
assert key != null;
if (isInternalKey(key))
continue; // skip internal keys
Attribute attr = new Attribute(keys[i], (String) vals[i], Attributes.this);
Attribute attr = new Attribute(key, (String) vals[i], Attributes.this);
list.add(attr);
}
return Collections.unmodifiableList(list);
Expand Down Expand Up @@ -468,11 +478,13 @@ public String html() {
final void html(final Appendable accum, final Document.OutputSettings out) throws IOException {
final int sz = size;
for (int i = 0; i < sz; i++) {
if (isInternalKey(keys[i]))
String key = keys[i];
assert key != null;
if (isInternalKey(key))
continue;
final String key = Attribute.getValidKey(keys[i], out.syntax());
if (key != null)
Attribute.htmlNoValidate(key, (String) vals[i], accum.append(' '), out);
final String validated = Attribute.getValidKey(key, out.syntax());
if (validated != null)
Attribute.htmlNoValidate(validated, (String) vals[i], accum.append(' '), out);
}
}

Expand All @@ -496,6 +508,7 @@ public boolean equals(@Nullable Object o) {
if (size != that.size) return false;
for (int i = 0; i < size; i++) {
String key = keys[i];
assert key != null;
int thatI = that.indexOfKey(key);
if (thatI == NotFound || !Objects.equals(vals[i], that.vals[thatI]))
return false;
Expand Down Expand Up @@ -534,8 +547,11 @@ public Attributes clone() {
*/
public void normalize() {
for (int i = 0; i < size; i++) {
if (!isInternalKey(keys[i]))
keys[i] = lowerCase(keys[i]);
assert keys[i] != null;
String key = keys[i];
assert key != null;
if (!isInternalKey(key))
keys[i] = lowerCase(key);
}
}

Expand All @@ -549,11 +565,11 @@ public int deduplicate(ParseSettings settings) {
return 0;
boolean preserve = settings.preserveAttributeCase();
int dupes = 0;
OUTER: for (int i = 0; i < keys.length; i++) {
for (int j = i + 1; j < keys.length; j++) {
if (keys[j] == null)
continue OUTER; // keys.length doesn't shrink when removing, so re-test
if ((preserve && keys[i].equals(keys[j])) || (!preserve && keys[i].equalsIgnoreCase(keys[j]))) {
for (int i = 0; i < size; i++) {
String keyI = keys[i];
assert keyI != null;
for (int j = i + 1; j < size; j++) {
if ((preserve && keyI.equals(keys[j])) || (!preserve && keyI.equalsIgnoreCase(keys[j]))) {
dupes++;
remove(j);
j--;
Expand Down Expand Up @@ -593,29 +609,29 @@ public Iterator<Map.Entry<String, String>> iterator() {
@Override
public int size() {
int count = 0;
Iterator iter = new DatasetIterator();
Iterator<Entry<String, String>> iter = new DatasetIterator();
while (iter.hasNext())
count++;
return count;
}
}

private class DatasetIterator implements Iterator<Map.Entry<String, String>> {
private Iterator<Attribute> attrIter = attributes.iterator();
private final Iterator<Attribute> attrIter = attributes.iterator();
private Attribute attr;
public boolean hasNext() {
@Override public boolean hasNext() {
while (attrIter.hasNext()) {
attr = attrIter.next();
if (attr.isDataAttribute()) return true;
}
return false;
}

public Entry<String, String> next() {
@Override public Entry<String, String> next() {
return new Attribute(attr.getKey().substring(dataPrefix.length()), attr.getValue());
}

public void remove() {
@Override public void remove() {
attributes.remove(attr.getKey());
}
}
Expand All @@ -630,6 +646,6 @@ static String internalKey(String key) {
}

static boolean isInternalKey(String key) {
return key != null && key.length() > 1 && key.charAt(0) == InternalPrefix;
return key.length() > 1 && key.charAt(0) == InternalPrefix;
}
}

0 comments on commit 55e50b9

Please sign in to comment.