Пример #1
0
int moIStream::Get(wchar_t& c)
{
	int		r;

	r = Read(&c, sizeof(wchar_t));
	if(r != sizeof(wchar_t)) {
		if(r > 0) {
			Unread(&c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER) {
		if(sizeof(wchar_t) == 2) {
			c = moSwap16Bits((uint16_t) c);
		}
		else if(sizeof(wchar_t) == 4) {
			c = moSwap32Bits((uint32_t) c);
		}
		else {
			throw moError("FATAL ERROR: don't know how to swap a 'wchar_t'.\n");
		}
	}

	return r;
}
Пример #2
0
/************************************************************ DOC:

CLASS

	moIStream

NAME

	Get - read a value from the input stream

SYNOPSIS

	virtual int Get(<type>& c);

	where <type> is any one of the C++ integer and floating point
	type (bool, char, wchar_t, short, int, long, long long, float,
	double, long double -- integers have signed and an unsigned
	versions.)

PARAMETERS

	c - a reference where the data read is written

DESCRIPTION

	The Get() functions will read the necessary number of bytes
	from the input stream using the Read() function and return the
	resulting value. By default, the endian of the input stream
	is assumed to be the same as the system being used. It can
	be changed with the SetInputEndianess() function.

	Though these are defined as virtual, they don't need to be
	overridden in your own stream declaration if it isn't to make
	it any faster.

RETURN VALUE

	the number of bytes read (1, 2, 4 or 8 at this time)
	-1 when an error occurs

BUGS

	On some systems the size of some C++ types won't be properly
	recognized and thus an error will be thrown. This should never
	happen though.

SEE ALSO

	Unget(), moOStream::Put(), SetInputEndianess()

*/
int moIStream::Get(bool& c)
{
	int		r;
	bool*		p_c = &c;

	r = Read(p_c, sizeof(bool));
	if(r != sizeof(bool)) {
		if(r > 0) {
			Unread(p_c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER && sizeof(bool) != 1) {
		if(sizeof(bool) == 2) {
			uint16_t *ptr = reinterpret_cast<uint16_t *>(p_c);
			*ptr = moSwap16Bits(*ptr);
		}
		else if(sizeof(bool) == 4) {
			uint32_t *ptr = reinterpret_cast<uint32_t *>(p_c);
			*ptr = moSwap32Bits(*ptr);
		}
		else {
			throw moError("FATAL ERROR: don't know how to swap a 'bool'.\n");
		}
	}

	return r;
}
Пример #3
0
int moIStream::Get(unsigned long& c)
{
	int		r;

	r = Read(&c, sizeof(unsigned long));
	if(r != sizeof(unsigned long)) {
		if(r > 0) {
			Unread(&c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER) {
		if(sizeof(unsigned long) == 4) {
			c = moSwap32Bits((uint32_t) c);
		}
		else if(sizeof(unsigned long) == 8) {
			c = moSwap64Bits((uint64_t) c);
		}
		else {
			throw moError("FATAL ERROR: don't know how to swap a 'long'.\n");
		}
	}

	return r;
}
Пример #4
0
int moIStream::Unget(uint64_t c)
{
	if(f_input_endian != BYTE_ORDER) {
		c = moSwap64Bits(c);
	}

	return Unread(&c, sizeof(uint64_t));
}
Пример #5
0
int moIStream::Unget(float c)
{
	float* p_c = &c;
	if(f_input_endian != BYTE_ORDER) {
		// we assume that float is 32 bits
		int32_t *ptr = reinterpret_cast<int32_t *>(p_c);
		*ptr = moSwap32Bits(*ptr);
	}

	return Unread(p_c, sizeof(float));
}
Пример #6
0
int moIStream::Unget(double c)
{
	double* p_c = &c;
	if(f_input_endian != BYTE_ORDER) {
		// we assume that double is 64 bits
		int64_t *ptr = reinterpret_cast<int64_t *>(p_c);
		*ptr = moSwap64Bits(*ptr);
	}

	return Unread(p_c, sizeof(double));
}
Пример #7
0
PRBool nsCSSScanner::LookAhead(nsresult& aErrorCode, PRUnichar aChar)
{
  PRInt32 ch = Read(aErrorCode);
  if (ch < 0) {
    return PR_FALSE;
  }
  if (ch == aChar) {
    return PR_TRUE;
  }
  Unread();
  return PR_FALSE;
}
Пример #8
0
int moIStream::Unget(long double c)
{
	int64_t		a, b;
	long double *	p_c = &c;

	if(f_input_endian != BYTE_ORDER) {
		// we assume that double is 64 bits
		a = moSwap64Bits(reinterpret_cast<int64_t *>(p_c)[0]);
		b = moSwap64Bits(reinterpret_cast<int64_t *>(p_c)[1]);
		reinterpret_cast<int64_t *>(p_c)[0] = b;
		reinterpret_cast<int64_t *>(p_c)[1] = a;
	}

	return Unread(p_c, sizeof(long double));
}
Пример #9
0
int moIStream::Get(unsigned char& c)
{
	int		r;

	r = Read(&c, sizeof(unsigned char));
	if(r != sizeof(unsigned char)) {
		if(r > 0) {
			Unread(&c, r);
			return 0;
		}
		return r;
	}

	return r;
}
Пример #10
0
int moIStream::Unget(unsigned long c)
{
	if(f_input_endian != BYTE_ORDER) {
		if(sizeof(unsigned long) == 4) {
			c = moSwap32Bits((uint32_t) c);
		}
		else if(sizeof(unsigned long) == 8) {
			c = moSwap64Bits((uint64_t) c);
		}
		else {
			throw moError("FATAL ERROR: don't know how to swap a 'long'.\n");
		}
	}

	return Unread(&c, sizeof(unsigned long));
}
Пример #11
0
int moIStream::Unget(wchar_t c)
{
	if(f_input_endian != BYTE_ORDER) {
		if(sizeof(wchar_t) == 2) {
			c = moSwap16Bits((uint16_t) c);
		}
		else if(sizeof(wchar_t) == 4) {
			c = moSwap32Bits((uint32_t) c);
		}
		else {
			throw moError("FATAL ERROR: don't know how to swap a 'wchar_t'.\n");
		}
	}

	return Unread(&c, sizeof(wchar_t));
}
Пример #12
0
PRBool nsCSSScanner::EatWhiteSpace(nsresult& aErrorCode)
{
  PRBool eaten = PR_FALSE;
  for (;;) {
    PRInt32 ch = Read(aErrorCode);
    if (ch < 0) {
      break;
    }
    if ((ch == ' ') || (ch == '\n') || (ch == '\r') || (ch == '\t')) {
      eaten = PR_TRUE;
      continue;
    }
    Unread();
    break;
  }
  return eaten;
}
Пример #13
0
int moIStream::Get(uint64_t& c)
{
	int		r;

	r = Read(&c, sizeof(uint64_t));
	if(r != sizeof(uint64_t)) {
		if(r > 0) {
			Unread(&c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER) {
		c = moSwap64Bits(c);
	}

	return r;
}
Пример #14
0
PRBool nsCSSScanner::EatNewline(nsresult& aErrorCode)
{
  PRInt32 ch = Read(aErrorCode);
  if (ch < 0) {
    return PR_FALSE;
  }
  PRBool eaten = PR_FALSE;
  if (ch == '\r') {
    eaten = PR_TRUE;
    ch = Peek(aErrorCode);
    if (ch == '\n') {
      (void) Read(aErrorCode);
    }
  } else if (ch == '\n') {
    eaten = PR_TRUE;
  } else {
    Unread();
  }
  return eaten;
}
Пример #15
0
int moIStream::Get(double& c)
{
	int		r;
	double*		p_c = &c;

	r = Read(p_c, sizeof(double));
	if(r != sizeof(double)) {
		if(r > 0) {
			Unread(p_c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER) {
		int64_t *ptr = reinterpret_cast<int64_t *>(p_c);
		*ptr = moSwap64Bits(*ptr);
	}

	return r;
}
Пример #16
0
int moIStream::Get(float& c)
{
	int		r;
	float*		p_c = &c;

	r = Read(p_c, sizeof(float));
	if(r != sizeof(float)) {
		if(r > 0) {
			Unread(p_c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER) {
		int32_t *ptr = reinterpret_cast<int32_t *>(p_c);
		*ptr = moSwap32Bits(*ptr);
	}

	return r;
}
Пример #17
0
int moIStream::Get(long double& c)
{
	int		r;
	int64_t		a, b;

	r = Read(&c, sizeof(long double));
	if(r != sizeof(long double)) {
		if(r > 0) {
			Unread(&c, r);
			return 0;
		}
		return r;
	}

	if(f_input_endian != BYTE_ORDER) {
		a = moSwap64Bits(((int64_t *) &c)[0]);
		b = moSwap64Bits(((int64_t *) &c)[1]);
		((int64_t *) &c)[0] = b;
		((int64_t *) &c)[1] = a;
	}

	return r;
}
Пример #18
0
/**
 * Gather up the characters in an identifier. The identfier was
 * started by "aChar" which will be appended to aIdent. The result
 * will be aIdent with all of the identifier characters appended
 * until the first non-identifier character is seen. The termination
 * character is unread for the future re-reading.
 */
PRBool nsCSSScanner::GatherIdent(nsresult& aErrorCode, PRInt32 aChar,
                                 nsString& aIdent)
{
  if (aChar == CSS_ESCAPE) {
    ParseAndAppendEscape(aErrorCode, aIdent);
  }
  else if (0 < aChar) {
    aIdent.Append(aChar);
  }
  for (;;) {
    aChar = Read(aErrorCode);
    if (aChar < 0) break;
    if (aChar == CSS_ESCAPE) {
      ParseAndAppendEscape(aErrorCode, aIdent);
    } else if ((aChar > 255) || ((gLexTable[aChar] & IS_IDENT) != 0)) {
      aIdent.Append(PRUnichar(aChar));
    } else {
      Unread();
      break;
    }
  }
  return PR_TRUE;
}
Пример #19
0
PRBool nsCSSScanner::ParseRef(nsresult& aErrorCode,
                              PRInt32 aChar,
                              nsCSSToken& aToken)
{
  aToken.mIdent.SetLength(0);
  aToken.mType = eCSSToken_Ref;
  PRInt32 ch = Read(aErrorCode);
  if (ch < 0) {
    return PR_FALSE;
  }
  if (ch > 255 || (gLexTable[ch] & IS_IDENT) || ch == CSS_ESCAPE) {
    // First char after the '#' is a valid ident char (or an escape),
    // so it makes sense to keep going
    if (StartsIdent(ch, Peek(aErrorCode), gLexTable)) {
      aToken.mType = eCSSToken_ID;
    }
    return GatherIdent(aErrorCode, ch, aToken.mIdent);
  }

  // No ident chars after the '#'.  Just unread |ch| and get out of here.
  Unread();
  return PR_TRUE;
}
Пример #20
0
PRBool nsCSSScanner::NextURL(nsresult& aErrorCode, nsCSSToken& aToken)
{
  PRInt32 ch = Read(aErrorCode);
  if (ch < 0) {
    return PR_FALSE;
  }
  if (ch < 256) {
    PRUint8* lexTable = gLexTable;

    // STRING
    if ((ch == '"') || (ch == '\'')) {
      return ParseString(aErrorCode, ch, aToken);
    }

    // WS
    if ((lexTable[ch] & IS_WHITESPACE) != 0) {
      aToken.mType = eCSSToken_WhiteSpace;
      aToken.mIdent.Assign(PRUnichar(ch));
      (void) EatWhiteSpace(aErrorCode);
      return PR_TRUE;
    }
    if (ch == '/') {
      PRInt32 nextChar = Peek(aErrorCode);
      if (nextChar == '*') {
        (void) Read(aErrorCode);
#if 0
        // If we change our storage data structures such that comments are
        // stored (for Editor), we should reenable this code, condition it
        // on being in editor mode, and apply glazou's patch from bug
        // 60290.
        aToken.mIdent.SetCapacity(2);
        aToken.mIdent.Assign(PRUnichar(ch));
        aToken.mIdent.Append(PRUnichar(nextChar));
        return ParseCComment(aErrorCode, aToken);
#endif
        return SkipCComment(aErrorCode) && Next(aErrorCode, aToken);
      }
    }

    // Process a url lexical token. A CSS1 url token can contain
    // characters beyond identifier characters (e.g. '/', ':', etc.)
    // Because of this the normal rules for tokenizing the input don't
    // apply very well. To simplify the parser and relax some of the
    // requirements on the scanner we parse url's here. If we find a
    // malformed URL then we emit a token of type "InvalidURL" so that
    // the CSS1 parser can ignore the invalid input. We attempt to eat
    // the right amount of input data when an invalid URL is presented.

    aToken.mType = eCSSToken_InvalidURL;
    nsString& ident = aToken.mIdent;
    ident.SetLength(0);

    if (ch == ')') {
      Pushback(ch);
      // empty url spec; just get out of here
      aToken.mType = eCSSToken_URL;
    } else {
      // start of a non-quoted url
      Pushback(ch);
      PRBool ok = PR_TRUE;
      for (;;) {
        ch = Read(aErrorCode);
        if (ch < 0) break;
        if (ch == CSS_ESCAPE) {
          ParseAndAppendEscape(aErrorCode, ident);
        } else if ((ch == '"') || (ch == '\'') || (ch == '(')) {
          // This is an invalid URL spec
          ok = PR_FALSE;
        } else if ((256 > ch) && ((gLexTable[ch] & IS_WHITESPACE) != 0)) {
          // Whitespace is allowed at the end of the URL
          (void) EatWhiteSpace(aErrorCode);
          if (LookAhead(aErrorCode, ')')) {
            Pushback(')');  // leave the closing symbol
            // done!
            break;
          }
          // Whitespace is followed by something other than a
          // ")". This is an invalid url spec.
          ok = PR_FALSE;
        } else if (ch == ')') {
          Unread();
          // All done
          break;
        } else {
          // A regular url character.
          ident.Append(PRUnichar(ch));
        }
      }

      // If the result of the above scanning is ok then change the token
      // type to a useful one.
      if (ok) {
        aToken.mType = eCSSToken_URL;
      }
    }
  }
  return PR_TRUE;
}
Пример #21
0
void
nsCSSScanner::ParseAndAppendEscape(nsresult& aErrorCode, nsString& aOutput)
{
  PRUint8* lexTable = gLexTable;
  PRInt32 ch = Peek(aErrorCode);
  if (ch < 0) {
    aOutput.Append(CSS_ESCAPE);
    return;
  }
  if ((ch <= 255) && ((lexTable[ch] & IS_HEX_DIGIT) != 0)) {
    PRInt32 rv = 0;
    int i;
    for (i = 0; i < 6; i++) { // up to six digits
      ch = Read(aErrorCode);
      if (ch < 0) {
        // Whoops: error or premature eof
        break;
      }
      if (ch >= 256 || (lexTable[ch] & (IS_HEX_DIGIT | IS_WHITESPACE)) == 0) {
        Unread();
        break;
      } else if ((lexTable[ch] & IS_HEX_DIGIT) != 0) {
        if ((lexTable[ch] & IS_DIGIT) != 0) {
          rv = rv * 16 + (ch - '0');
        } else {
          // Note: c&7 just keeps the low three bits which causes
          // upper and lower case alphabetics to both yield their
          // "relative to 10" value for computing the hex value.
          rv = rv * 16 + ((ch & 0x7) + 9);
        }
      } else {
        NS_ASSERTION((lexTable[ch] & IS_WHITESPACE) != 0, "bad control flow");
        // single space ends escape
        if (ch == '\r' && Peek(aErrorCode) == '\n') {
          // if CR/LF, eat LF too
          Read(aErrorCode);
        }
        break;
      }
    }
    if (6 == i) { // look for trailing whitespace and eat it
      ch = Peek(aErrorCode);
      if ((0 <= ch) && (ch <= 255) && 
          ((lexTable[ch] & IS_WHITESPACE) != 0)) {
        (void) Read(aErrorCode);
        // special case: if trailing whitespace is CR/LF, eat both chars.
        if (ch == '\r' && Peek(aErrorCode) == '\n') {
          (void) Read(aErrorCode);
          // if we hit the "\0" special case below, we'll push back
          // only the '\r', but that's okay, because '\r' by itself
          // is still a newline.
        }
      }
    }
    NS_ASSERTION(rv >= 0, "How did rv become negative?");
    // "[at most six hexadecimal digits following a backslash] stand
    // for the ISO 10646 character with that number, which must not be
    // zero. (It is undefined in CSS 2.1 what happens if a style sheet
    // does contain a character with Unicode codepoint zero.)"
    //   -- CSS2.1 section 4.1.3
    //
    // Silently deleting \0 opens a content-filtration loophole (see
    // bug 228856), so what we do instead is pretend the "cancels the
    // meaning of special characters" rule applied.
    if (rv > 0) {
      AppendUCS4ToUTF16(ENSURE_VALID_CHAR(rv), aOutput);
    } else {
      while (i--)
        aOutput.Append('0');
      if ((0 <= ch) && (ch <= 255) && ((lexTable[ch] & IS_WHITESPACE) != 0))
        Pushback(ch);
    }
    return;
  } else {
    // "Any character except a hexidecimal digit can be escaped to
    // remove its special meaning by putting a backslash in front"
    // -- CSS1 spec section 7.1
    if (!EatNewline(aErrorCode)) { // skip escaped newline
      (void) Read(aErrorCode);
      if (ch > 0) {
        aOutput.Append(ch);
      }
    }
    return;
  }
}
Пример #22
0
int moIStream::Unget(unsigned char c)
{
	return Unread(&c, sizeof(unsigned char));
}
Пример #23
0
PRBool nsCSSScanner::ParseNumber(nsresult& aErrorCode, PRInt32 c,
                                 nsCSSToken& aToken)
{
  nsString& ident = aToken.mIdent;
  ident.SetLength(0);
  PRBool gotDot = (c == '.') ? PR_TRUE : PR_FALSE;
  if (c != '+') {
    ident.Append(PRUnichar(c));
  }

  // Gather up characters that make up the number
  PRUint8* lexTable = gLexTable;
  for (;;) {
    c = Read(aErrorCode);
    if (c < 0) break;
    if (!gotDot && (c == '.') &&
        CheckLexTable(Peek(aErrorCode), IS_DIGIT, lexTable)) {
      gotDot = PR_TRUE;
    } else if ((c > 255) || ((lexTable[c] & IS_DIGIT) == 0)) {
      break;
    }
    ident.Append(PRUnichar(c));
  }

  // Convert number to floating point
  nsCSSTokenType type = eCSSToken_Number;
  PRInt32 ec;
  float value = ident.ToFloat(&ec);

  // Look at character that terminated the number
  aToken.mIntegerValid = PR_FALSE;
  if (c >= 0) {
    if ((c <= 255) && ((lexTable[c] & START_IDENT) != 0)) {
      ident.SetLength(0);
      if (!GatherIdent(aErrorCode, c, ident)) {
        return PR_FALSE;
      }
      type = eCSSToken_Dimension;
    } else if ('%' == c) {
      type = eCSSToken_Percentage;
      value = value / 100.0f;
      ident.SetLength(0);
    } else {
      // Put back character that stopped numeric scan
      Unread();
      if (!gotDot) {
        aToken.mInteger = ident.ToInteger(&ec);
        aToken.mIntegerValid = PR_TRUE;
      }
      ident.SetLength(0);
    }
  }
  else {  // stream ended
    if (!gotDot) {
      aToken.mInteger = ident.ToInteger(&ec);
      aToken.mIntegerValid = PR_TRUE;
    }
    ident.SetLength(0);
  }
  aToken.mNumber = value;
  aToken.mType = type;
  return PR_TRUE;
}