Ejemplo n.º 1
0
void
URLMainThread::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
{
  nsAString::const_iterator start, end;
  aProtocol.BeginReading(start);
  aProtocol.EndReading(end);
  nsAString::const_iterator iter(start);

  FindCharInReadable(':', iter, end);

  // Changing the protocol of a URL, changes the "nature" of the URI
  // implementation. In order to do this properly, we have to serialize the
  // existing URL and reparse it in a new object.
  nsCOMPtr<nsIURI> clone;
  nsresult rv = NS_MutateURI(GetURI())
                  .SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)))
                  .Finalize(clone);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  nsAutoCString href;
  rv = clone->GetSpec(href);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  nsCOMPtr<nsIURI> uri;
  rv = NS_NewURI(getter_AddRefs(uri), href);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  SetURI(uri.forget());
}
Ejemplo n.º 2
0
static void utf16ToUcs4(const nsAString& in, uint32_t *out, uint32_t outBufLen, uint32_t *outLen)
{
  uint32_t i = 0;
  nsAString::const_iterator start, end;
  in.BeginReading(start); 
  in.EndReading(end); 

  while (start != end) {
    PRUnichar curChar;

    curChar= *start++;

    if (start != end &&
        NS_IS_HIGH_SURROGATE(curChar) && 
        NS_IS_LOW_SURROGATE(*start)) {
      out[i] = SURROGATE_TO_UCS4(curChar, *start);
      ++start;
    }
    else
      out[i] = curChar;

    i++;
    if (i >= outBufLen) {
      NS_ERROR("input too big, the result truncated");
      out[outBufLen-1] = (uint32_t)'\0';
      *outLen = outBufLen-1;
      return;
    }
  }
  out[i] = (uint32_t)'\0';
  *outLen = i;
}
Ejemplo n.º 3
0
void
nsCSSScanner::Init(const nsAString& aBuffer,
                   nsIURI* aURI, uint32_t aLineNumber,
                   nsCSSStyleSheet* aSheet, mozilla::css::Loader* aLoader)
{
  NS_PRECONDITION(!mReadPointer, "Should not have an existing input buffer!");

  mReadPointer = aBuffer.BeginReading();
  mCount = aBuffer.Length();

#ifdef CSS_REPORT_PARSE_ERRORS
  // If aURI is different from mCachedURI, invalidate the filename cache.
  if (aURI != mCachedURI) {
    mCachedURI = aURI;
    mCachedFileName.Truncate();
  }
#endif // CSS_REPORT_PARSE_ERRORS

  mLineNumber = aLineNumber;

  // Reset variables that we use to keep track of our progress through the input
  mOffset = 0;
  mPushbackCount = 0;
  mRecording = false;

#ifdef CSS_REPORT_PARSE_ERRORS
  mColNumber = 0;
  mSheet = aSheet;
  mLoader = aLoader;
#endif
}
nsresult
NS_CopyUnicodeToNative(const nsAString  &input, nsACString &output)
{
    PRUint32 inputLen = input.Length();

    nsAString::const_iterator iter;
    input.BeginReading(iter);

    const PRUnichar *buf = iter.get();

    // determine length of result
    PRUint32 resultLen = 0;

    int n = ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, NULL, 0, NULL, NULL);
    if (n > 0)
        resultLen += n;

    // allocate sufficient space
    if (!EnsureStringLength(output, resultLen))
        return NS_ERROR_OUT_OF_MEMORY;
    if (resultLen > 0) {
        nsACString::iterator out_iter;
        output.BeginWriting(out_iter);

        // default "defaultChar" is '?', which is an illegal character on windows
        // file system.  That will cause file uncreatable. Change it to '_'
        const char defaultChar = '_';

        char *result = out_iter.get();

        ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, result, resultLen,
                              &defaultChar, NULL);
    }
    return NS_OK;
}
Ejemplo n.º 5
0
void
nsCSPParser::resetCurChar(const nsAString& aToken)
{
  mCurChar = aToken.BeginReading();
  mEndChar = aToken.EndReading();
  resetCurValue();
}
Ejemplo n.º 6
0
static nsresult encodeToRACE(const char* prefix, const nsAString& in, nsACString& out)
{
  // need maximum 20 bits to encode 16 bit Unicode character
  // (include null terminator)
  const uint32_t kEncodedBufSize = kMaxDNSNodeLen * 20 / 8 + 1 + 1;  

  // set up a work buffer for RACE encoder
  PRUnichar temp[kMaxDNSNodeLen + 2];
  temp[0] = 0xFFFF;   // set a place holder (to be filled by get_compress_mode)
  temp[in.Length() + 1] = (PRUnichar)'\0';

  nsAString::const_iterator start, end;
  in.BeginReading(start); 
  in.EndReading(end);
  
  for (uint32_t i = 1; start != end; i++)
    temp[i] = *start++;

  // encode nodes if non ASCII

  char encodedBuf[kEncodedBufSize];
  idn_result_t result = race_compress_encode((const unsigned short *) temp, 
                                             get_compress_mode((unsigned short *) temp + 1), 
                                             encodedBuf, kEncodedBufSize);
  if (idn_success != result)
    return NS_ERROR_FAILURE;

  out.Assign(prefix);
  out.Append(encodedBuf);

  return NS_OK;
}
void
BluetoothScoManager::NotifyAudioManager(const nsAString& aAddress) {
  MOZ_ASSERT(NS_IsMainThread());

  nsCOMPtr<nsIObserverService> obs =
    do_GetService("@mozilla.org/observer-service;1");
  NS_ENSURE_TRUE_VOID(obs);

  if (aAddress.IsEmpty()) {
    if (NS_FAILED(obs->NotifyObservers(nullptr, BLUETOOTH_SCO_STATUS_CHANGED, nullptr))) {
      NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
      return;
    }
  } else {
    if (NS_FAILED(obs->NotifyObservers(nullptr, BLUETOOTH_SCO_STATUS_CHANGED, aAddress.BeginReading()))) {
      NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
      return;
    }
  }

  nsCOMPtr<nsIAudioManager> am =
    do_GetService("@mozilla.org/telephony/audiomanager;1");
  NS_ENSURE_TRUE_VOID(am);
  am->SetForceForUse(am->USE_COMMUNICATION, am->FORCE_BT_SCO);
}
Ejemplo n.º 8
0
void
GDIFontEntry::InitLogFont(const nsAString& aName,
                          gfxWindowsFontType aFontType)
{
#define CLIP_TURNOFF_FONTASSOCIATION 0x40

    mLogFont.lfHeight = -1;

    // Fill in logFont structure
    mLogFont.lfWidth          = 0;
    mLogFont.lfEscapement     = 0;
    mLogFont.lfOrientation    = 0;
    mLogFont.lfUnderline      = FALSE;
    mLogFont.lfStrikeOut      = FALSE;
    mLogFont.lfCharSet        = DEFAULT_CHARSET;
    mLogFont.lfOutPrecision   = FontTypeToOutPrecision(aFontType);
    mLogFont.lfClipPrecision  = CLIP_TURNOFF_FONTASSOCIATION;
    mLogFont.lfQuality        = DEFAULT_QUALITY;
    mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
    // always force lfItalic if we want it.  Font selection code will
    // do its best to give us an italic font entry, but if no face exists
    // it may give us a regular one based on weight.  Windows should
    // do fake italic for us in that case.
    mLogFont.lfItalic         = mItalic;
    mLogFont.lfWeight         = mWeight;

    int len = std::min<int>(aName.Length(), LF_FACESIZE - 1);
    memcpy(&mLogFont.lfFaceName, aName.BeginReading(), len * sizeof(char16_t));
    mLogFont.lfFaceName[len] = '\0';
}
void nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes,
                                        nsTArray<nsString>& aResult)
{
  nsAString::const_iterator start, done;
  aTypes.BeginReading(start);
  aTypes.EndReading(done);
  if (start == done)
    return;

  nsAString::const_iterator current(start);
  PRBool inString = !nsCRT::IsAsciiSpace(*current);
  nsAutoString subString;

  while (current != done) {
    if (nsCRT::IsAsciiSpace(*current)) {
      if (inString) {
        ToLowerCase(Substring(start, current), subString);
        aResult.AppendElement(subString);
        inString = PR_FALSE;
      }
    }
    else {
      if (!inString) {
        start = current;
        inString = PR_TRUE;
      }
    }
    ++current;
  }
  if (inString) {
    ToLowerCase(Substring(start, current), subString);
    aResult.AppendElement(subString);
  }
}
Ejemplo n.º 10
0
uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
{
  uint32_t linkMask = 0;
  nsAString::const_iterator start, done;
  aTypes.BeginReading(start);
  aTypes.EndReading(done);
  if (start == done)
    return linkMask;

  nsAString::const_iterator current(start);
  bool inString = !nsContentUtils::IsHTMLWhitespace(*current);
  nsAutoString subString;

  while (current != done) {
    if (nsContentUtils::IsHTMLWhitespace(*current)) {
      if (inString) {
        nsContentUtils::ASCIIToLower(Substring(start, current), subString);
        linkMask |= ToLinkMask(subString);
        inString = false;
      }
    }
    else {
      if (!inString) {
        start = current;
        inString = true;
      }
    }
    ++current;
  }
  if (inString) {
    nsContentUtils::ASCIIToLower(Substring(start, current), subString);
    linkMask |= ToLinkMask(subString);
  }
  return linkMask;
}
Ejemplo n.º 11
0
nsresult
nsParserService::CheckQName(const nsAString& aQName,
                            bool aNamespaceAware,
                            const PRUnichar** aColon)
{
    const char* colon;
    const PRUnichar *begin, *end;
    begin = aQName.BeginReading();
    end = aQName.EndReading();
    int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
                                   reinterpret_cast<const char*>(end),
                                   aNamespaceAware, &colon);
    *aColon = reinterpret_cast<const PRUnichar*>(colon);

    if (result == 0) {
        return NS_OK;
    }

    // MOZ_EXPAT_EMPTY_QNAME || MOZ_EXPAT_INVALID_CHARACTER
    if (result == (1 << 0) || result == (1 << 1)) {
        return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
    }

    return NS_ERROR_DOM_NAMESPACE_ERR;
}
Ejemplo n.º 12
0
/* static */
mozilla::widget::Modifiers
nsDOMUIEvent::ComputeModifierState(const nsAString& aModifiersList)
{
  if (aModifiersList.IsEmpty()) {
    return 0;
  }

  // Be careful about the performance.  If aModifiersList is too long,
  // parsing it needs too long time.
  // XXX Should we abort if aModifiersList is too long?

  Modifiers modifiers = 0;

  nsAString::const_iterator listStart, listEnd;
  aModifiersList.BeginReading(listStart);
  aModifiersList.EndReading(listEnd);

  for (uint32_t i = 0; i < mozilla::ArrayLength(kPairs); i++) {
    nsAString::const_iterator start(listStart), end(listEnd);
    if (!FindInReadable(NS_ConvertASCIItoUTF16(kPairs[i].name), start, end)) {
      continue;
    }

    if ((start != listStart && !NS_IsAsciiWhitespace(*(--start))) ||
        (end != listEnd && !NS_IsAsciiWhitespace(*(end)))) {
      continue;
    }
    modifiers |= kPairs[i].modifier;
  }

  return modifiers;
}
Ejemplo n.º 13
0
bool
FakeInputStream::CheckTest(nsAString& aResult)
{
  return !NS_tstrcmp(aResult.BeginReading(),
                     NS_ConvertASCIItoUTF16(mTest->mResult).BeginReading())
                     ? true : false;
}
Ejemplo n.º 14
0
nsresult
NS_CopyUnicodeToNative(const nsAString& aInput, nsACString& aOutput)
{
  aOutput.Truncate();

  nsAString::const_iterator iter, end;
  aInput.BeginReading(iter);
  aInput.EndReading(end);

  // cannot easily avoid intermediate buffer copy.
  char temp[4096];

  nsNativeCharsetConverter conv;

  const char16_t* buf = iter.get();
  uint32_t bufLeft = Distance(iter, end);
  while (bufLeft) {
    char* p = temp;
    uint32_t tempLeft = sizeof(temp);

    nsresult rv = conv.UnicodeToNative(&buf, &bufLeft, &p, &tempLeft);
    if (NS_FAILED(rv)) {
      return rv;
    }

    if (tempLeft < sizeof(temp)) {
      aOutput.Append(temp, sizeof(temp) - tempLeft);
    }
  }
  return NS_OK;
}
Ejemplo n.º 15
0
double Double::toDouble(const nsAString& aSrc)
{
    txStringToDouble sink;
    nsAString::const_iterator fromBegin, fromEnd;
    copy_string(aSrc.BeginReading(fromBegin), aSrc.EndReading(fromEnd), sink);
    return sink.getDouble();
}
Ejemplo n.º 16
0
void
nsCSSScanner::Init(const nsAString& aBuffer,
                   nsIURI* aURI, uint32_t aLineNumber,
                   nsCSSStyleSheet* aSheet, mozilla::css::Loader* aLoader)
{
  NS_PRECONDITION(!mReadPointer, "Should not have an existing input buffer!");

  mReadPointer = aBuffer.BeginReading();
  mCount = aBuffer.Length();

#ifdef CSS_REPORT_PARSE_ERRORS
  // If aURI is the same as mURI, no need to reget mFileName -- it
  // shouldn't have changed.
  if (aURI != mURI) {
    mURI = aURI;
    if (aURI) {
      aURI->GetSpec(mFileName);
    } else {
      mFileName.Adopt(NS_strdup("from DOM"));
    }
  }
#endif // CSS_REPORT_PARSE_ERRORS
  mLineNumber = aLineNumber;

  // Reset variables that we use to keep track of our progress through the input
  mOffset = 0;
  mPushbackCount = 0;
  mRecording = false;

#ifdef CSS_REPORT_PARSE_ERRORS
  mColNumber = 0;
  mSheet = aSheet;
  mLoader = aLoader;
#endif
}
Ejemplo n.º 17
0
NS_IMETHODIMP
nsConverterOutputStream::WriteString(const nsAString& aString, bool* aSuccess)
{
    PRInt32 inLen = aString.Length();
    nsAString::const_iterator i;
    aString.BeginReading(i);
    return Write(inLen, i.get(), aSuccess);
}
Ejemplo n.º 18
0
void CharacterData::ReplaceData(uint32_t aOffset, uint32_t aCount,
                                const nsAString& aData, ErrorResult& aRv) {
  nsresult rv = SetTextInternal(aOffset, aCount, aData.BeginReading(),
                                aData.Length(), true);
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
  }
}
Ejemplo n.º 19
0
JS::Value StringValue(JSContext* cx, const nsAString& str, ErrorResult& er) {
  JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
  if (!jsStr) {
    er.Throw(NS_ERROR_OUT_OF_MEMORY);
    return JS::NullValue();
  }

  return JS::StringValue(jsStr);
}
Ejemplo n.º 20
0
void PolicyTokenizer::tokenizePolicy(const nsAString& aPolicyString,
                                     policyTokens& outTokens) {
  POLICYTOKENIZERLOG(("PolicyTokenizer::tokenizePolicy"));

  PolicyTokenizer tokenizer(aPolicyString.BeginReading(),
                            aPolicyString.EndReading());

  tokenizer.generateTokens(outTokens);
}
Ejemplo n.º 21
0
void
CharacterData::SetData(const nsAString& aData, ErrorResult& aRv)
{
  nsresult rv = SetTextInternal(0, mText.GetLength(), aData.BeginReading(),
                                aData.Length(), true);
  if (NS_FAILED(rv)) {
    aRv.Throw(rv);
  }
}
Ejemplo n.º 22
0
nsresult
nsSMILParserUtils::ParseValues(const nsAString& aSpec,
                               const nsISMILAnimationElement* aSrcElement,
                               const nsISMILAttr& aAttribute,
                               nsTArray<nsSMILValue>& aValuesArray)
{
  nsresult rv = NS_ERROR_FAILURE;
  nsAString::const_iterator start;
  nsAString::const_iterator end;
  nsAString::const_iterator substr_end;
  nsAString::const_iterator next;

  aSpec.BeginReading(start);
  aSpec.EndReading(end);

  while (start != end) {
    rv = NS_ERROR_FAILURE;

    SkipWsp(start, end);

    if (start == end || *start == ';')
      break;

    substr_end = start;

    while (substr_end != end && *substr_end != ';') {
      ++substr_end;
    }

    next = substr_end;
    if (*substr_end == ';') {
      ++next;
      if (next == end)
        break;
    }

    do --substr_end; while (start != substr_end && NS_IS_SPACE(*substr_end));
    ++substr_end;

    nsSMILValue newValue;
    rv = aAttribute.ValueFromString(Substring(start, substr_end),
                                    aSrcElement, newValue);
    if (NS_FAILED(rv))
      break;

    if (!aValuesArray.AppendElement(newValue)) {
      rv = NS_ERROR_OUT_OF_MEMORY;
      break;
    }

    rv = NS_OK;
    start = next;
  }

  return rv;
}
Ejemplo n.º 23
0
void
nsCSPParser::percentDecodeStr(const nsAString& aEncStr, nsAString& outDecStr)
{
  outDecStr.Truncate();

  // helper function that should not be visible outside this methods scope
  struct local {
    static inline char16_t convertHexDig(char16_t aHexDig) {
      if (isNumberToken(aHexDig)) {
        return aHexDig - '0';
      }
      if (aHexDig >= 'A' && aHexDig <= 'F') {
        return aHexDig - 'A' + 10;
      }
      // must be a lower case character
      // (aHexDig >= 'a' && aHexDig <= 'f')
      return aHexDig - 'a' + 10;
    }
  };

  const char16_t *cur, *end, *hexDig1, *hexDig2;
  cur = aEncStr.BeginReading();
  end = aEncStr.EndReading();

  while (cur != end) {
    // if it's not a percent sign then there is
    // nothing to do for that character
    if (*cur != PERCENT_SIGN) {
      outDecStr.Append(*cur);
      cur++;
      continue;
    }

    // get the two hexDigs following the '%'-sign
    hexDig1 = cur + 1;
    hexDig2 = cur + 2;

    // if there are no hexdigs after the '%' then
    // there is nothing to do for us.
    if (hexDig1 == end || hexDig2 == end ||
        !isValidHexDig(*hexDig1) ||
        !isValidHexDig(*hexDig2)) {
      outDecStr.Append(PERCENT_SIGN);
      cur++;
      continue;
    }

    // decode "% hexDig1 hexDig2" into a character.
    char16_t decChar = (local::convertHexDig(*hexDig1) << 4) +
                       local::convertHexDig(*hexDig2);
    outDecStr.Append(decChar);

    // increment 'cur' to after the second hexDig
    cur = ++hexDig2;
  }
}
Ejemplo n.º 24
0
NS_StringGetData(const nsAString& aStr, const char16_t** aData,
                 bool* aTerminated)
{
  if (aTerminated) {
    *aTerminated = aStr.IsTerminated();
  }

  *aData = aStr.BeginReading();
  return aStr.Length();
}
Ejemplo n.º 25
0
/* void setVoice (in AString id); */
NS_IMETHODIMP CLidaAudio::SetVoice(const nsAString & id)
{
	//tiramos uma copia da string
	//ela nao é nulo-terminated
	std::wstring texto_str;
	texto_str.assign(id.BeginReading(), id.EndReading());

	m_sapitts.SetVoice(texto_str);
	return NS_OK;
}
Ejemplo n.º 26
0
/*
retorna TRUE se está OK, false se deu erro
*/
NS_IMETHODIMP CLidaAudio::PlayTTS(const nsAString & texto, PRBool *_retval)
{
	//tiramos uma copia da string
	//ela nao é nulo-terminated
	std::wstring texto_str;
	texto_str.assign(texto.BeginReading(), texto.EndReading());

	*_retval = m_sapitts.PlayTTS(texto_str.c_str());
	return NS_OK;
}
Ejemplo n.º 27
0
void TX_ToLowerCase(const nsAString& aSource, nsAString& aDest)
{
  nsAString::const_iterator fromBegin, fromEnd;
  nsAString::iterator toBegin;
  if (!EnsureStringLength(aDest, aSource.Length()))
    return; // XXX no way to signal out-of-memory
  CopyToLowerCase converter(aDest.BeginWriting(toBegin));
  copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
              converter);
}
nsXMLProcessingInstruction::nsXMLProcessingInstruction(nsINodeInfo *aNodeInfo,
                                                       const nsAString& aTarget,
                                                       const nsAString& aData)
  : nsGenericDOMDataNode(aNodeInfo),
    mTarget(aTarget)
{
  SetTextInternal(0, mText.GetLength(),
                  aData.BeginReading(), aData.Length(),
                  PR_FALSE);  // Don't notify (bug 420429).
}
Ejemplo n.º 29
0
NS_IMETHODIMP
nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
                             nsIContent* aTargetNode,
                             nsIAtom* aContextLocalName,
                             PRInt32 aContextNamespace,
                             PRBool aQuirks)
{
  nsIDocument* doc = aTargetNode->GetOwnerDoc();
  NS_ENSURE_TRUE(doc, NS_ERROR_NOT_AVAILABLE);
  
  nsIURI* uri = doc->GetDocumentURI();
  NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);

  Initialize(doc, uri, nsnull, nsnull);

  mExecutor->SetParser(this);
  mExecutor->SetNodeInfoManager(doc->NodeInfoManager());

  nsIContent* target = aTargetNode;
  mTreeBuilder->setFragmentContext(aContextLocalName,
                                   aContextNamespace,
                                   &target,
                                   aQuirks);
  mExecutor->EnableFragmentMode();
  
  NS_PRECONDITION(!mExecutor->HasStarted(),
                  "Tried to start parse without initializing the parser.");
  mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
  mTokenizer->start();
  mExecutor->Start(); // Don't call WillBuildModel in fragment case
  if (!aSourceBuffer.IsEmpty()) {
    PRBool lastWasCR = PR_FALSE;
    nsHtml5UTF16Buffer buffer(aSourceBuffer.Length());
    memcpy(buffer.getBuffer(),
           aSourceBuffer.BeginReading(),
           aSourceBuffer.Length() * sizeof(PRUnichar));
    buffer.setEnd(aSourceBuffer.Length());
    while (buffer.hasMore()) {
      buffer.adjust(lastWasCR);
      lastWasCR = PR_FALSE;
      if (buffer.hasMore()) {
        lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
      }
    }
  }
  mTokenizer->eof();
  mTreeBuilder->StreamEnded();
  mTreeBuilder->Flush();
  mExecutor->FlushDocumentWrite();
  mTokenizer->end();
  mExecutor->DropParserAndPerfHint();
  mExecutor->DropHeldElements();
  mAtomTable.Clear();
  return NS_OK;
}
Ejemplo n.º 30
0
static void
ExtractSpacingValues(const nsAString&   aString,
                     nsIAtom*           aAttribute,
                     nsTArray<nscoord>& aSpacingArray,
                     nsIFrame*          aFrame,
                     nscoord            aDefaultValue0,
                     nscoord            aDefaultValue1,
                     float              aFontSizeInflation)
{
  nsPresContext* presContext = aFrame->PresContext();
  nsStyleContext* styleContext = aFrame->StyleContext();

  const char16_t* start = aString.BeginReading();
  const char16_t* end = aString.EndReading();

  int32_t startIndex = 0;
  int32_t count = 0;
  int32_t elementNum = 0;

  while (start < end) {
    // Skip leading spaces.
    while ((start < end) && nsCRT::IsAsciiSpace(*start)) {
      start++;
      startIndex++;
    }

    // Look for the end of the string, or another space.
    while ((start < end) && !nsCRT::IsAsciiSpace(*start)) {
      start++;
      count++;
    }

    // Grab the value found and process it.
    if (count > 0) {
      const nsAString& str = Substring(aString, startIndex, count);
      nsAutoString valueString;
      valueString.Assign(str);
      nscoord newValue;
      if (aAttribute == nsGkAtoms::framespacing_ && elementNum) {
        newValue = aDefaultValue1;
      } else {
        newValue = aDefaultValue0;
      }
      nsMathMLFrame::ParseNumericValue(valueString, &newValue,
                                       nsMathMLElement::PARSE_ALLOW_UNITLESS,
                                       presContext, styleContext,
                                       aFontSizeInflation);
      aSpacingArray.AppendElement(newValue);

      startIndex += count;
      count = 0;
      elementNum++;
    }
  }
}