Reputation: 2646
I'm experiencing a weird behavior...
In short - running this command (on a Range<Index>
) within an application code
currIndexPlaceA = a!.startIndex.successor()..<newText.endIndex;
is ignored...
When I set a breakpoint after this command, and run po a
in the debug window (lldb), I get:
▿ Optional> ▿ Some : Range(39..<44) - startIndex : 39 - endIndex : 44
while po currIndexPlaceA
is:
▿ Range(5..<54) - startIndex : 5 - endIndex : 54
it is clear that startIndex should have been higher than 39!
but, running the same command through the lldb window:
expr currIndexPlaceA = a!.startIndex.successor()..<newText.endIndex;
results in (po currIndexPlaceA
):
▿ Range(40..<54) - startIndex : 40 - endIndex : 54
What's going on here?????
If you want to debug my full function.. it's kind of a headache - it's a sort of xml parser...
I test it with text: <id><id></id><id/><id /><id><id /><id/><id></id></id></id>
and tagName: id
func getTagContent(text : String, tagName : String) -> [String!]!{
// Extracts reply
var newText = text;
var currProcessing = text;
var retVal = [String!]();
while (newText != ""){
let rangeFirst = newText.rangeOfString("<" + tagName, options: [], range: nil, locale: nil);
if let actrange = rangeFirst
{
newText = newText.substringFromIndex(actrange.startIndex.advancedBy(tagName.characters.count + 1));
let rangeEndFirstTag = newText.rangeOfString(">");
if let actRangeEndFirstTab = rangeEndFirstTag {
let distToCloseTag = newText.startIndex.distanceTo(actRangeEndFirstTab.startIndex)
if (distToCloseTag == 0 || (distToCloseTag > 0 && newText[actRangeEndFirstTab.startIndex.predecessor()] != "/")) {
newText = newText.substringFromIndex(actRangeEndFirstTab.startIndex.advancedBy(1));
var currIndexPlaceA = newText.startIndex..<newText.endIndex;
var currIndexPlaceB = newText.startIndex..<newText.endIndex;
var a = newText.rangeOfString("</" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);
if a == nil {a = newText.rangeOfString("</" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);}
var b = newText.rangeOfString("<" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
if b == nil {b = newText.rangeOfString("<" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);}
while (a != nil && b != nil && b?.startIndex < a?.startIndex){
let txt = newText.substringFromIndex(b!.endIndex);
var closedTag = false;
if let tmpRagne = txt.rangeOfString(">"){
if (tmpRagne.startIndex > txt.startIndex){
if (txt[tmpRagne.startIndex.predecessor()] == "/"){
closedTag = true;
}
}
}
if closedTag{
currIndexPlaceB = b!.startIndex.successor()..<newText.endIndex;
var b = newText.rangeOfString("<" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
if b == nil {b = newText.rangeOfString("<" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);}
}
else{
currIndexPlaceA = a!.startIndex.successor()..<newText.endIndex;
currIndexPlaceB = b!.startIndex.successor()..<newText.endIndex;
var a = newText.rangeOfString("</" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);
if a == nil {a = newText.rangeOfString("</" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);}
var b = newText.rangeOfString("<" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
if b == nil {b = newText.rangeOfString("<" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);}
}
}
if a == nil { return nil; }
currProcessing = newText.substringToIndex(a!.startIndex);
retVal.append(currProcessing);
newText = newText.substringFromIndex(a!.startIndex.successor());
if let lastRange = newText.rangeOfString(">"){
newText = newText.substringFromIndex(lastRange.endIndex);
}
else {
return nil;
}
}
else{
newText = newText.substringFromIndex(actRangeEndFirstTab.startIndex.successor());
retVal.append(nil);
}
}
}
else {
break;
}
}
return retVal;
}
Upvotes: 0
Views: 24
Reputation: 3440
So here is the offending code.
currIndexPlaceA = a!.startIndex.successor()..<newText.endIndex;
currIndexPlaceB = b!.startIndex.successor()..<newText.endIndex;
var a = newText.rangeOfString("</" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);
A definite bug is the shadowing of a
and b
declared outside the while
loop with the var a
and var b
in this else
block. As for your LLDB problem, make absolutely sure that you have stopped on the line where currIndexPlaceB
is set and not on or after where var a
is set. Make sure all optimizations have been turned off as that may be causing code placement to be shuffled.
(Question writer... Adding code edits which solved the issue)
I'm adding here the final code, with additional bugs fixed (so if someone wants to get tags from xml - you'll have a copy-paste).
When debugging initially - I did't understand what was going on so I started using endIndex
instead of startIndex
etc.
func getTagContent(text : String, tagName : String) -> [String!]!{
// Extracts reply
var newText = text;
var currProcessing = text;
var retVal = [String!]();
while (newText != ""){
let rangeFirst = newText.rangeOfString("<" + tagName, options: [], range: nil, locale: nil);
if let actrange = rangeFirst
{
newText = newText.substringFromIndex(actrange.startIndex.advancedBy(tagName.characters.count + 1));
let rangeEndFirstTag = newText.rangeOfString(">");
if let actRangeEndFirstTab = rangeEndFirstTag {
let distToCloseTag = newText.startIndex.distanceTo(actRangeEndFirstTab.startIndex)
if (distToCloseTag == 0 || (distToCloseTag > 0 && newText[actRangeEndFirstTab.startIndex.predecessor()] != "/")) {
newText = newText.substringFromIndex(actRangeEndFirstTab.startIndex.advancedBy(1));
var currIndexPlaceA = newText.startIndex..<newText.endIndex;
var currIndexPlaceB = newText.startIndex..<newText.endIndex;
var a = newText.rangeOfString("</" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);
if a == nil {a = newText.rangeOfString("</" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);}
var b = newText.rangeOfString("<" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
if b == nil {b = newText.rangeOfString("<" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);}
while (a != nil && b != nil && b?.startIndex < a?.startIndex){
let txt = newText.substringFromIndex(b!.startIndex);
var closedTag = false;
if let tmpRagne = txt.rangeOfString(">"){
if (tmpRagne.startIndex > txt.startIndex){
if (txt[tmpRagne.startIndex.predecessor()] == "/"){
closedTag = true;
}
}
}
if closedTag{
currIndexPlaceB = b!.endIndex..<newText.endIndex;
b = newText.rangeOfString("<" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
let tmpb = newText.rangeOfString("<" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
if (b == nil || (tmpb != nil && tmpb?.startIndex < b?.startIndex)) {b = tmpb;}
}
else{
currIndexPlaceA = a!.endIndex..<newText.endIndex;
currIndexPlaceB = b!.endIndex..<newText.endIndex;
a = newText.rangeOfString("</" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);
let tmpa = newText.rangeOfString("</" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceA, locale: nil);
if (a == nil || (tmpa != nil && tmpa!.startIndex < a?.startIndex)) {a = tmpa;}
b = newText.rangeOfString("<" + tagName + ">", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
let tmpb = newText.rangeOfString("<" + tagName + " ", options: NSStringCompareOptions.LiteralSearch, range: currIndexPlaceB, locale: nil);
if (b == nil || (tmpb != nil && tmpb?.startIndex < b?.startIndex)) {b = tmpb;}
}
}
if a == nil { return nil; }
currProcessing = newText.substringToIndex(a!.startIndex);
retVal.append(currProcessing);
newText = newText.substringFromIndex(a!.startIndex.successor());
if let lastRange = newText.rangeOfString(">"){
newText = newText.substringFromIndex(lastRange.endIndex);
}
else {
return nil;
}
}
else{
newText = newText.substringFromIndex(actRangeEndFirstTab.startIndex.successor());
retVal.append(nil);
}
}
}
else {
break;
}
}
return retVal;
}
Upvotes: 1