package org.python.core.stringlib;
import org.python.core.PyBoolean;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedType;
/**
* Provides an implementation of str._formatter_field_name_split()
*/
@ExposedType(name = "fieldnameiterator", base = PyObject.class, isBaseType = false)
public class FieldNameIterator extends PyObject {
public static final PyType TYPE = PyType.fromClass(FieldNameIterator.class);
private String markup;
private Object head;
private int index;
public FieldNameIterator(String markup) {
this.markup = markup;
this.index = nextDotOrBracket(markup);
String headStr = markup.substring(0, index);
try {
this.head = Integer.parseInt(headStr);
} catch (NumberFormatException e) {
this.head = headStr;
}
}
@Override
public PyObject __iter__() {
return fieldnameiterator___iter__();
}
@ExposedMethod
final PyObject fieldnameiterator___iter__() {
return this;
}
@Override
public PyObject __iternext__() {
return fieldnameiterator___iternext__();
}
@ExposedMethod
final PyObject fieldnameiterator___iternext__() {
Chunk chunk = nextChunk();
if (chunk == null) {
return null;
}
PyObject[] elements = new PyObject[2];
elements [0] = new PyBoolean(chunk.is_attr);
if (chunk.value instanceof Integer) {
elements [1] = new PyInteger((Integer) chunk.value);
} else {
elements [1] = new PyString((String) chunk.value);
}
return new PyTuple(elements);
}
private int nextDotOrBracket(String markup) {
int dotPos = markup.indexOf('.', index);
if (dotPos < 0) {
dotPos = markup.length();
}
int bracketPos = markup.indexOf('[', index);
if (bracketPos < 0) {
bracketPos = markup.length();
}
return Math.min(dotPos, bracketPos);
}
public Object head() {
return head;
}
public Chunk nextChunk() {
if (index == markup.length()) {
return null;
}
Chunk chunk = new Chunk();
if (markup.charAt(index) == '[') {
parseItemChunk(chunk);
} else if (markup.charAt(index) == '.') {
parseAttrChunk(chunk);
}
return chunk;
}
private void parseItemChunk(Chunk chunk) {
chunk.is_attr = false;
int endBracket = markup.indexOf(']', index+1);
if (endBracket < 0) {
throw new IllegalArgumentException("Missing ']' in format string");
}
String itemValue = markup.substring(index + 1, endBracket);
if (itemValue.length() == 0) {
throw new IllegalArgumentException("Empty attribute in format string");
}
try {
chunk.value = Integer.parseInt(itemValue);
} catch (NumberFormatException e) {
chunk.value = itemValue;
}
index = endBracket + 1;
}
private void parseAttrChunk(Chunk chunk) {
index++; // skip dot
chunk.is_attr = true;
int pos = nextDotOrBracket(markup);
if (pos == index) {
throw new IllegalArgumentException("Empty attribute in format string");
}
chunk.value = markup.substring(index, pos);
index = pos;
}
public static class Chunk {
public boolean is_attr;
/** Integer or String. */
public Object value;
}
}