public function attributes() { // Make sure the tag type is correct. if ($this->tagType() != 'attribute') { return null; } elseif ($this->attributes !== null) { return $this->attributes; } else { // Just append one space... This will come in handy. $attributes = trim(SpeedyBBC::substr($this->text(), SpeedyBBC::strlen($this->tagName()) + 1, -1)) . ' '; // Set up a few useful variables. $pos = 0; $length = SpeedyBBC::strlen($attributes); $this->attributes = array(); while ($pos < $length) { // Keep going until we find no more space. $char = SpeedyBBC::substr($attributes, $pos, 1); // So, space? if ($char != ' ') { // Nope! // Go on until we find a space or equal sign. $equals = SpeedyBBC::strpos($attributes, '=', $pos); $space = SpeedyBBC::strpos($attributes, ' ', $pos); // This should be the attribute's name. $attr_name = SpeedyBBC::strtolower(SpeedyBBC::substr($attributes, $pos, ($equals === false || $equals > $space ? $space : $equals) - $pos)); // There should be nothing between the equals sign, if there is one. if ($equals === false || $equals > $space && SpeedyBBC::strlen(trim(SpeedyBBC::substr($attributes, $space, $equals - $space))) > 0) { // Looks like there is something else there! So this is just a // lonesome attribute name. $this->attributes[$attr_name] = true; $pos = $space + 1; // Now, we don't want to continue. continue; } // Let's see... We want to find the value, which we want to find by // going until we find anything but space. $pos = $equals + 1; while ($pos < $length && SpeedyBBC::substr($attributes, $pos, 1) == ' ') { $pos++; } // Alright, so the position we found should not be out-of-bounds. if ($pos >= $length) { // Woopsie! $this->attributes[$attr_name] = true; break; } elseif (($delimiter = SpeedyBBC::substr($attributes, $pos, 6)) == '"' || $delimiter == ''') { // Let's not forget where we came from, that's never a good idea. $start_pos = $pos; // Oh, and move passed the starting delimiter... Duh! $pos++; // This is also pretty simple, but not as simple as compared to the // one below. But oh well! Such is life on the farm! while ($pos < $length) { // Try to find the delimiter, somewhere! $pos = SpeedyBBC::strpos($attributes, $delimiter, $pos); // Did we find it? if ($pos === false) { // Uh, oh! break; } elseif (SpeedyBBC::substr($attributes, $pos - 1, 1) == '\\') { // I guess this won't be the right place to terminate the value, // huh? $pos += 2; // ... and so the search goes on! continue; } // Looks like we found it, in which case we just quit. break; } // Did we come to an end? if ($pos === false) { // In which case, we will do this: $this->attributes[$attr_name] = rtrim(SpeedyBBC::substr($attributes, $start_pos + 6)); // Let's get out of this loop, shall we? $pos = $length; } else { // Just fetch the value between the delimiter, and remove any // backslashes escaping a the delimiter in the value. $this->attributes[$attr_name] = str_replace('\\' . $delimiter, $delimiter, SpeedyBBC::substr($attributes, $start_pos + 6, $pos - $start_pos - 6)); // Just move on, a little bit. $pos += 6; } } else { // This is really simple... Thankfully! We will just find the next // space, which means the value is over. $space = SpeedyBBC::strpos($attributes, ' ', $pos + 1); $this->attributes[$attr_name] = trim(SpeedyBBC::substr($attributes, $pos, $space - $pos)); // Now set the position we want to start looking at next time. Which // is the space we just found. $pos = $space + 1; } } else { // Yup, a space, so go on. $pos++; } } return $this->attributes; } }