From 75f6a23b8196e2bb83d3cfa9233beadf2cacc152 Mon Sep 17 00:00:00 2001 From: Andrew Sutherland Date: Wed, 31 Mar 2010 13:30:26 -0700 Subject: [PATCH 01/69] Bug 555719 - (SQLite3.6.23.1) Upgrade to SQLite 3.6.23.1. rs=sdwilsh, some other dude who gave him an rs for such upgrades in general. --- configure.in | 2 +- db/sqlite3/README.MOZILLA | 2 +- db/sqlite3/src/sqlite3.c | 824 +++++++++++++++++++------------------- db/sqlite3/src/sqlite3.h | 4 +- 4 files changed, 427 insertions(+), 405 deletions(-) diff --git a/configure.in b/configure.in index c836bb3c3e44..1b35ec1c7dfa 100644 --- a/configure.in +++ b/configure.in @@ -132,7 +132,7 @@ GCONF_VERSION=1.2.1 GIO_VERSION=2.0 STARTUP_NOTIFICATION_VERSION=0.8 DBUS_VERSION=0.60 -SQLITE_VERSION=3.6.23 +SQLITE_VERSION=3.6.23.1 LIBNOTIFY_VERSION=0.4 MSMANIFEST_TOOL= diff --git a/db/sqlite3/README.MOZILLA b/db/sqlite3/README.MOZILLA index 078ac715cb7a..a90db532cc52 100644 --- a/db/sqlite3/README.MOZILLA +++ b/db/sqlite3/README.MOZILLA @@ -1,4 +1,4 @@ -This is sqlite 3.6.23 +This is sqlite 3.6.23.1 -- Shawn Wilsher , 03/2010 diff --git a/db/sqlite3/src/sqlite3.c b/db/sqlite3/src/sqlite3.c index 0e473c6ef700..8c44ff4b39a5 100644 --- a/db/sqlite3/src/sqlite3.c +++ b/db/sqlite3/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.6.23. By combining all the individual C code files into this +** version 3.6.23.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a one translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -628,9 +628,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.6.23" +#define SQLITE_VERSION "3.6.23.1" #define SQLITE_VERSION_NUMBER 3006023 -#define SQLITE_SOURCE_ID "2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d" +#define SQLITE_SOURCE_ID "2010-03-26 22:28:06 b078b588d617e07886ad156e9f54ade6d823568e" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -10868,6 +10868,393 @@ SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; /************** End of global.c **********************************************/ +/************** Begin file ctime.c *******************************************/ +/* +** 2010 February 23 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements routines used to report what compile-time options +** SQLite was built with. +*/ + +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + + +/* +** An array of names of all compile-time options. This array should +** be sorted A-Z. +** +** This array looks large, but in a typical installation actually uses +** only a handful of compile-time options, so most times this array is usually +** rather short and uses little memory space. +*/ +static const char * const azCompileOpt[] = { + +/* These macros are provided to "stringify" the value of the define +** for those options in which the value is meaningful. */ +#define CTIMEOPT_VAL_(opt) #opt +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + +#ifdef SQLITE_32BIT_ROWID + "32BIT_ROWID", +#endif +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC + "4_BYTE_ALIGNED_MALLOC", +#endif +#ifdef SQLITE_CASE_SENSITIVE_LIKE + "CASE_SENSITIVE_LIKE", +#endif +#ifdef SQLITE_CHECK_PAGES + "CHECK_PAGES", +#endif +#ifdef SQLITE_COVERAGE_TEST + "COVERAGE_TEST", +#endif +#ifdef SQLITE_DEBUG + "DEBUG", +#endif +#ifdef SQLITE_DEFAULT_LOCKING_MODE + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), +#endif +#ifdef SQLITE_DISABLE_DIRSYNC + "DISABLE_DIRSYNC", +#endif +#ifdef SQLITE_DISABLE_LFS + "DISABLE_LFS", +#endif +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + "ENABLE_ATOMIC_WRITE", +#endif +#ifdef SQLITE_ENABLE_CEROD + "ENABLE_CEROD", +#endif +#ifdef SQLITE_ENABLE_COLUMN_METADATA + "ENABLE_COLUMN_METADATA", +#endif +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + "ENABLE_EXPENSIVE_ASSERT", +#endif +#ifdef SQLITE_ENABLE_FTS1 + "ENABLE_FTS1", +#endif +#ifdef SQLITE_ENABLE_FTS2 + "ENABLE_FTS2", +#endif +#ifdef SQLITE_ENABLE_FTS3 + "ENABLE_FTS3", +#endif +#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS + "ENABLE_FTS3_PARENTHESIS", +#endif +#ifdef SQLITE_ENABLE_FTS4 + "ENABLE_FTS4", +#endif +#ifdef SQLITE_ENABLE_ICU + "ENABLE_ICU", +#endif +#ifdef SQLITE_ENABLE_IOTRACE + "ENABLE_IOTRACE", +#endif +#ifdef SQLITE_ENABLE_LOAD_EXTENSION + "ENABLE_LOAD_EXTENSION", +#endif +#ifdef SQLITE_ENABLE_LOCKING_STYLE + "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), +#endif +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + "ENABLE_MEMORY_MANAGEMENT", +#endif +#ifdef SQLITE_ENABLE_MEMSYS3 + "ENABLE_MEMSYS3", +#endif +#ifdef SQLITE_ENABLE_MEMSYS5 + "ENABLE_MEMSYS5", +#endif +#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK + "ENABLE_OVERSIZE_CELL_CHECK", +#endif +#ifdef SQLITE_ENABLE_RTREE + "ENABLE_RTREE", +#endif +#ifdef SQLITE_ENABLE_STAT2 + "ENABLE_STAT2", +#endif +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY + "ENABLE_UNLOCK_NOTIFY", +#endif +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT + "ENABLE_UPDATE_DELETE_LIMIT", +#endif +#ifdef SQLITE_HAS_CODEC + "HAS_CODEC", +#endif +#ifdef SQLITE_HAVE_ISNAN + "HAVE_ISNAN", +#endif +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + "HOMEGROWN_RECURSIVE_MUTEX", +#endif +#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS + "IGNORE_AFP_LOCK_ERRORS", +#endif +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS + "IGNORE_FLOCK_LOCK_ERRORS", +#endif +#ifdef SQLITE_INT64_TYPE + "INT64_TYPE", +#endif +#ifdef SQLITE_LOCK_TRACE + "LOCK_TRACE", +#endif +#ifdef SQLITE_MEMDEBUG + "MEMDEBUG", +#endif +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT + "MIXED_ENDIAN_64BIT_FLOAT", +#endif +#ifdef SQLITE_NO_SYNC + "NO_SYNC", +#endif +#ifdef SQLITE_OMIT_ALTERTABLE + "OMIT_ALTERTABLE", +#endif +#ifdef SQLITE_OMIT_ANALYZE + "OMIT_ANALYZE", +#endif +#ifdef SQLITE_OMIT_ATTACH + "OMIT_ATTACH", +#endif +#ifdef SQLITE_OMIT_AUTHORIZATION + "OMIT_AUTHORIZATION", +#endif +#ifdef SQLITE_OMIT_AUTOINCREMENT + "OMIT_AUTOINCREMENT", +#endif +#ifdef SQLITE_OMIT_AUTOINIT + "OMIT_AUTOINIT", +#endif +#ifdef SQLITE_OMIT_AUTOVACUUM + "OMIT_AUTOVACUUM", +#endif +#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION + "OMIT_BETWEEN_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_BLOB_LITERAL + "OMIT_BLOB_LITERAL", +#endif +#ifdef SQLITE_OMIT_BTREECOUNT + "OMIT_BTREECOUNT", +#endif +#ifdef SQLITE_OMIT_BUILTIN_TEST + "OMIT_BUILTIN_TEST", +#endif +#ifdef SQLITE_OMIT_CAST + "OMIT_CAST", +#endif +#ifdef SQLITE_OMIT_CHECK + "OMIT_CHECK", +#endif +#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS + "OMIT_COMPILEOPTION_DIAGS", +#endif +#ifdef SQLITE_OMIT_COMPLETE + "OMIT_COMPLETE", +#endif +#ifdef SQLITE_OMIT_COMPOUND_SELECT + "OMIT_COMPOUND_SELECT", +#endif +#ifdef SQLITE_OMIT_DATETIME_FUNCS + "OMIT_DATETIME_FUNCS", +#endif +#ifdef SQLITE_OMIT_DECLTYPE + "OMIT_DECLTYPE", +#endif +#ifdef SQLITE_OMIT_DEPRECATED + "OMIT_DEPRECATED", +#endif +#ifdef SQLITE_OMIT_DISKIO + "OMIT_DISKIO", +#endif +#ifdef SQLITE_OMIT_EXPLAIN + "OMIT_EXPLAIN", +#endif +#ifdef SQLITE_OMIT_FLAG_PRAGMAS + "OMIT_FLAG_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_FLOATING_POINT + "OMIT_FLOATING_POINT", +#endif +#ifdef SQLITE_OMIT_FOREIGN_KEY + "OMIT_FOREIGN_KEY", +#endif +#ifdef SQLITE_OMIT_GET_TABLE + "OMIT_GET_TABLE", +#endif +#ifdef SQLITE_OMIT_GLOBALRECOVER + "OMIT_GLOBALRECOVER", +#endif +#ifdef SQLITE_OMIT_INCRBLOB + "OMIT_INCRBLOB", +#endif +#ifdef SQLITE_OMIT_INTEGRITY_CHECK + "OMIT_INTEGRITY_CHECK", +#endif +#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION + "OMIT_LIKE_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_LOAD_EXTENSION + "OMIT_LOAD_EXTENSION", +#endif +#ifdef SQLITE_OMIT_LOCALTIME + "OMIT_LOCALTIME", +#endif +#ifdef SQLITE_OMIT_LOOKASIDE + "OMIT_LOOKASIDE", +#endif +#ifdef SQLITE_OMIT_MEMORYDB + "OMIT_MEMORYDB", +#endif +#ifdef SQLITE_OMIT_OR_OPTIMIZATION + "OMIT_OR_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_PAGER_PRAGMAS + "OMIT_PAGER_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_PRAGMA + "OMIT_PRAGMA", +#endif +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK + "OMIT_PROGRESS_CALLBACK", +#endif +#ifdef SQLITE_OMIT_QUICKBALANCE + "OMIT_QUICKBALANCE", +#endif +#ifdef SQLITE_OMIT_REINDEX + "OMIT_REINDEX", +#endif +#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS + "OMIT_SCHEMA_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + "OMIT_SCHEMA_VERSION_PRAGMAS", +#endif +#ifdef SQLITE_OMIT_SHARED_CACHE + "OMIT_SHARED_CACHE", +#endif +#ifdef SQLITE_OMIT_SUBQUERY + "OMIT_SUBQUERY", +#endif +#ifdef SQLITE_OMIT_TCL_VARIABLE + "OMIT_TCL_VARIABLE", +#endif +#ifdef SQLITE_OMIT_TEMPDB + "OMIT_TEMPDB", +#endif +#ifdef SQLITE_OMIT_TRACE + "OMIT_TRACE", +#endif +#ifdef SQLITE_OMIT_TRIGGER + "OMIT_TRIGGER", +#endif +#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION + "OMIT_TRUNCATE_OPTIMIZATION", +#endif +#ifdef SQLITE_OMIT_UTF16 + "OMIT_UTF16", +#endif +#ifdef SQLITE_OMIT_VACUUM + "OMIT_VACUUM", +#endif +#ifdef SQLITE_OMIT_VIEW + "OMIT_VIEW", +#endif +#ifdef SQLITE_OMIT_VIRTUALTABLE + "OMIT_VIRTUALTABLE", +#endif +#ifdef SQLITE_OMIT_WSD + "OMIT_WSD", +#endif +#ifdef SQLITE_OMIT_XFER_OPT + "OMIT_XFER_OPT", +#endif +#ifdef SQLITE_PERFORMANCE_TRACE + "PERFORMANCE_TRACE", +#endif +#ifdef SQLITE_PROXY_DEBUG + "PROXY_DEBUG", +#endif +#ifdef SQLITE_SECURE_DELETE + "SECURE_DELETE", +#endif +#ifdef SQLITE_SMALL_STACK + "SMALL_STACK", +#endif +#ifdef SQLITE_SOUNDEX + "SOUNDEX", +#endif +#ifdef SQLITE_TCL + "TCL", +#endif +#ifdef SQLITE_TEMP_STORE + "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), +#endif +#ifdef SQLITE_TEST + "TEST", +#endif +#ifdef SQLITE_THREADSAFE + "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), +#endif +#ifdef SQLITE_USE_ALLOCA + "USE_ALLOCA", +#endif +#ifdef SQLITE_ZERO_MALLOC + "ZERO_MALLOC" +#endif +}; + +/* +** Given the name of a compile-time option, return true if that option +** was used and false if not. +** +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix +** is not required for a match. +*/ +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ + int i, n; + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; + n = sqlite3Strlen30(zOptName); + + /* Since ArraySize(azCompileOpt) is normally in single digits, a + ** linear search is adequate. No need for a binary search. */ + for(i=0; i=0 && Njfd, zMaster, pPager->pVfs->mxPathname+1); testcase( rc!=SQLITE_OK ); } + if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){ + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + } if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager, zMaster[0]!='\0'); testcase( rc!=SQLITE_OK ); @@ -71127,395 +71517,6 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ } /************** End of callback.c ********************************************/ -/************** Begin file ctime.c *******************************************/ -/* -** 2010 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements routines used to report what compile-time options -** SQLite was built with. -*/ - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - - -/* -** An array of names of all compile-time options. This array should -** be sorted A-Z. -** -** This array looks large, but in a typical installation actually uses -** only a handful of compile-time options, so most times this array is usually -** rather short and uses little memory space. -*/ -static const char * const azCompileOpt[] = { - -/* These macros are provided to "stringify" the value of the define -** for those options in which the value is meaningful. */ -#define CTIMEOPT_VAL_(opt) #opt -#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) - -#ifdef SQLITE_32BIT_ROWID - "32BIT_ROWID", -#endif -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC - "4_BYTE_ALIGNED_MALLOC", -#endif -#ifdef SQLITE_CASE_SENSITIVE_LIKE - "CASE_SENSITIVE_LIKE", -#endif -#ifdef SQLITE_CHECK_PAGES - "CHECK_PAGES", -#endif -#ifdef SQLITE_COVERAGE_TEST - "COVERAGE_TEST", -#endif -#ifdef SQLITE_DEBUG - "DEBUG", -#endif -#ifdef SQLITE_DEFAULT_LOCKING_MODE - "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), -#endif -#ifdef SQLITE_DISABLE_DIRSYNC - "DISABLE_DIRSYNC", -#endif -#ifdef SQLITE_DISABLE_LFS - "DISABLE_LFS", -#endif -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - "ENABLE_ATOMIC_WRITE", -#endif -#ifdef SQLITE_ENABLE_CEROD - "ENABLE_CEROD", -#endif -#ifdef SQLITE_ENABLE_COLUMN_METADATA - "ENABLE_COLUMN_METADATA", -#endif -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - "ENABLE_EXPENSIVE_ASSERT", -#endif -#ifdef SQLITE_ENABLE_FTS1 - "ENABLE_FTS1", -#endif -#ifdef SQLITE_ENABLE_FTS2 - "ENABLE_FTS2", -#endif -#ifdef SQLITE_ENABLE_FTS3 - "ENABLE_FTS3", -#endif -#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS - "ENABLE_FTS3_PARENTHESIS", -#endif -#if 0 /* Disabled because FTS4 is not ready for publication */ -#ifdef SQLITE_ENABLE_FTS4 - "ENABLE_FTS4", -#endif -#endif -#ifdef SQLITE_ENABLE_ICU - "ENABLE_ICU", -#endif -#ifdef SQLITE_ENABLE_IOTRACE - "ENABLE_IOTRACE", -#endif -#ifdef SQLITE_ENABLE_LOAD_EXTENSION - "ENABLE_LOAD_EXTENSION", -#endif -#ifdef SQLITE_ENABLE_LOCKING_STYLE - "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), -#endif -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - "ENABLE_MEMORY_MANAGEMENT", -#endif -#ifdef SQLITE_ENABLE_MEMSYS3 - "ENABLE_MEMSYS3", -#endif -#ifdef SQLITE_ENABLE_MEMSYS5 - "ENABLE_MEMSYS5", -#endif -#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK - "ENABLE_OVERSIZE_CELL_CHECK", -#endif -#ifdef SQLITE_ENABLE_RTREE - "ENABLE_RTREE", -#endif -#ifdef SQLITE_ENABLE_STAT2 - "ENABLE_STAT2", -#endif -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - "ENABLE_UNLOCK_NOTIFY", -#endif -#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - "ENABLE_UPDATE_DELETE_LIMIT", -#endif -#ifdef SQLITE_HAS_CODEC - "HAS_CODEC", -#endif -#ifdef SQLITE_HAVE_ISNAN - "HAVE_ISNAN", -#endif -#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX - "HOMEGROWN_RECURSIVE_MUTEX", -#endif -#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS - "IGNORE_AFP_LOCK_ERRORS", -#endif -#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - "IGNORE_FLOCK_LOCK_ERRORS", -#endif -#ifdef SQLITE_INT64_TYPE - "INT64_TYPE", -#endif -#ifdef SQLITE_LOCK_TRACE - "LOCK_TRACE", -#endif -#ifdef SQLITE_MEMDEBUG - "MEMDEBUG", -#endif -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT - "MIXED_ENDIAN_64BIT_FLOAT", -#endif -#ifdef SQLITE_NO_SYNC - "NO_SYNC", -#endif -#ifdef SQLITE_OMIT_ALTERTABLE - "OMIT_ALTERTABLE", -#endif -#ifdef SQLITE_OMIT_ANALYZE - "OMIT_ANALYZE", -#endif -#ifdef SQLITE_OMIT_ATTACH - "OMIT_ATTACH", -#endif -#ifdef SQLITE_OMIT_AUTHORIZATION - "OMIT_AUTHORIZATION", -#endif -#ifdef SQLITE_OMIT_AUTOINCREMENT - "OMIT_AUTOINCREMENT", -#endif -#ifdef SQLITE_OMIT_AUTOINIT - "OMIT_AUTOINIT", -#endif -#ifdef SQLITE_OMIT_AUTOVACUUM - "OMIT_AUTOVACUUM", -#endif -#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION - "OMIT_BETWEEN_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_BLOB_LITERAL - "OMIT_BLOB_LITERAL", -#endif -#ifdef SQLITE_OMIT_BTREECOUNT - "OMIT_BTREECOUNT", -#endif -#ifdef SQLITE_OMIT_BUILTIN_TEST - "OMIT_BUILTIN_TEST", -#endif -#ifdef SQLITE_OMIT_CAST - "OMIT_CAST", -#endif -#ifdef SQLITE_OMIT_CHECK - "OMIT_CHECK", -#endif -#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS - "OMIT_COMPILEOPTION_DIAGS", -#endif -#ifdef SQLITE_OMIT_COMPLETE - "OMIT_COMPLETE", -#endif -#ifdef SQLITE_OMIT_COMPOUND_SELECT - "OMIT_COMPOUND_SELECT", -#endif -#ifdef SQLITE_OMIT_DATETIME_FUNCS - "OMIT_DATETIME_FUNCS", -#endif -#ifdef SQLITE_OMIT_DECLTYPE - "OMIT_DECLTYPE", -#endif -#ifdef SQLITE_OMIT_DEPRECATED - "OMIT_DEPRECATED", -#endif -#ifdef SQLITE_OMIT_DISKIO - "OMIT_DISKIO", -#endif -#ifdef SQLITE_OMIT_EXPLAIN - "OMIT_EXPLAIN", -#endif -#ifdef SQLITE_OMIT_FLAG_PRAGMAS - "OMIT_FLAG_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_FLOATING_POINT - "OMIT_FLOATING_POINT", -#endif -#ifdef SQLITE_OMIT_FOREIGN_KEY - "OMIT_FOREIGN_KEY", -#endif -#ifdef SQLITE_OMIT_GET_TABLE - "OMIT_GET_TABLE", -#endif -#ifdef SQLITE_OMIT_GLOBALRECOVER - "OMIT_GLOBALRECOVER", -#endif -#ifdef SQLITE_OMIT_INCRBLOB - "OMIT_INCRBLOB", -#endif -#ifdef SQLITE_OMIT_INTEGRITY_CHECK - "OMIT_INTEGRITY_CHECK", -#endif -#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION - "OMIT_LIKE_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_LOAD_EXTENSION - "OMIT_LOAD_EXTENSION", -#endif -#ifdef SQLITE_OMIT_LOCALTIME - "OMIT_LOCALTIME", -#endif -#ifdef SQLITE_OMIT_LOOKASIDE - "OMIT_LOOKASIDE", -#endif -#ifdef SQLITE_OMIT_MEMORYDB - "OMIT_MEMORYDB", -#endif -#ifdef SQLITE_OMIT_OR_OPTIMIZATION - "OMIT_OR_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_PAGER_PRAGMAS - "OMIT_PAGER_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_PRAGMA - "OMIT_PRAGMA", -#endif -#ifdef SQLITE_OMIT_PROGRESS_CALLBACK - "OMIT_PROGRESS_CALLBACK", -#endif -#ifdef SQLITE_OMIT_QUICKBALANCE - "OMIT_QUICKBALANCE", -#endif -#ifdef SQLITE_OMIT_REINDEX - "OMIT_REINDEX", -#endif -#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS - "OMIT_SCHEMA_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - "OMIT_SCHEMA_VERSION_PRAGMAS", -#endif -#ifdef SQLITE_OMIT_SHARED_CACHE - "OMIT_SHARED_CACHE", -#endif -#ifdef SQLITE_OMIT_SUBQUERY - "OMIT_SUBQUERY", -#endif -#ifdef SQLITE_OMIT_TCL_VARIABLE - "OMIT_TCL_VARIABLE", -#endif -#ifdef SQLITE_OMIT_TEMPDB - "OMIT_TEMPDB", -#endif -#ifdef SQLITE_OMIT_TRACE - "OMIT_TRACE", -#endif -#ifdef SQLITE_OMIT_TRIGGER - "OMIT_TRIGGER", -#endif -#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION - "OMIT_TRUNCATE_OPTIMIZATION", -#endif -#ifdef SQLITE_OMIT_UTF16 - "OMIT_UTF16", -#endif -#ifdef SQLITE_OMIT_VACUUM - "OMIT_VACUUM", -#endif -#ifdef SQLITE_OMIT_VIEW - "OMIT_VIEW", -#endif -#ifdef SQLITE_OMIT_VIRTUALTABLE - "OMIT_VIRTUALTABLE", -#endif -#ifdef SQLITE_OMIT_WSD - "OMIT_WSD", -#endif -#ifdef SQLITE_OMIT_XFER_OPT - "OMIT_XFER_OPT", -#endif -#ifdef SQLITE_PERFORMANCE_TRACE - "PERFORMANCE_TRACE", -#endif -#ifdef SQLITE_PROXY_DEBUG - "PROXY_DEBUG", -#endif -#ifdef SQLITE_SECURE_DELETE - "SECURE_DELETE", -#endif -#ifdef SQLITE_SMALL_STACK - "SMALL_STACK", -#endif -#ifdef SQLITE_SOUNDEX - "SOUNDEX", -#endif -#ifdef SQLITE_TCL - "TCL", -#endif -#ifdef SQLITE_TEMP_STORE - "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), -#endif -#ifdef SQLITE_TEST - "TEST", -#endif -#ifdef SQLITE_THREADSAFE - "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), -#endif -#ifdef SQLITE_USE_ALLOCA - "USE_ALLOCA", -#endif -#ifdef SQLITE_ZERO_MALLOC - "ZERO_MALLOC" -#endif -}; - -/* -** Given the name of a compile-time option, return true if that option -** was used and false if not. -** -** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix -** is not required for a match. -*/ -SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ - int i, n; - if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; - n = sqlite3Strlen30(zOptName); - - /* Since ArraySize(azCompileOpt) is normally in single digits, a - ** linear search is adequate. No need for a binary search. */ - for(i=0; i=0 && NpTokenizer, p->azColumn, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr ); - if( rc!=SQLITE_OK ) return rc; + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_ERROR ){ + p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]", + zQuery); + } + return rc; + } rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0); pCsr->pNextId = pCsr->aDoclist; @@ -102280,13 +102302,11 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ rc = sqlite3_create_module_v2( db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); -#if 0 /* FTS4 is disabled in 3.6.23 since it is not yet ready for publication */ if( rc==SQLITE_OK ){ rc = sqlite3_create_module_v2( db, "fts4", &fts3Module, (void *)pHash, 0 ); } -#endif /* disable FTS4 */ return rc; } @@ -105167,9 +105187,9 @@ static int fts3SqlStmt( /* 5 */ "DELETE FROM %Q.'%q_docsize'", /* 6 */ "DELETE FROM %Q.'%q_stat'", /* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?", -/* 8 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?", +/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", /* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", -/* 10 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'", +/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", /* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", /* Return segments in order from oldest to newest.*/ @@ -108728,11 +108748,13 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart ); rc = fts3StringAppend(&res, aBuffer, -1); + }else if( rc==SQLITE_DONE ){ + rc = SQLITE_CORRUPT; } } } if( rc==SQLITE_DONE ){ - rc = SQLITE_CORRUPT; + rc = SQLITE_OK; } pMod->xClose(pC); diff --git a/db/sqlite3/src/sqlite3.h b/db/sqlite3/src/sqlite3.h index ae45d818fade..d72fdbd51af3 100644 --- a/db/sqlite3/src/sqlite3.h +++ b/db/sqlite3/src/sqlite3.h @@ -107,9 +107,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.6.23" +#define SQLITE_VERSION "3.6.23.1" #define SQLITE_VERSION_NUMBER 3006023 -#define SQLITE_SOURCE_ID "2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d" +#define SQLITE_SOURCE_ID "2010-03-26 22:28:06 b078b588d617e07886ad156e9f54ade6d823568e" /* ** CAPI3REF: Run-Time Library Version Numbers From efa27354ff0abec54a8af6971a55872cdba6ac7c Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 31 Mar 2010 16:22:37 -0400 Subject: [PATCH 02/69] Bug 552124 - Reset URL bar transaction manager when leaving private browsing; r=gavin --- browser/base/content/browser.js | 4 ++ .../privatebrowsing/test/browser/Makefile.in | 1 + .../browser_privatebrowsing_urlbarundo.js | 66 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 5502e4e582a4..2c1c52810ea1 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -7341,6 +7341,10 @@ let gPrivateBrowsingUI = { } } + if (gURLBar) { + gURLBar.editor.transactionManager.clear(); + } + document.getElementById("menu_import").removeAttribute("disabled"); // Re-enable the Clear Recent History... menu item on exit of PB mode diff --git a/browser/components/privatebrowsing/test/browser/Makefile.in b/browser/components/privatebrowsing/test/browser/Makefile.in index aa98f6b57621..9f6e97751747 100644 --- a/browser/components/privatebrowsing/test/browser/Makefile.in +++ b/browser/components/privatebrowsing/test/browser/Makefile.in @@ -72,6 +72,7 @@ _BROWSER_TEST_FILES = \ browser_privatebrowsing_transition.js \ browser_privatebrowsing_ui.js \ browser_privatebrowsing_urlbarfocus.js \ + browser_privatebrowsing_urlbarundo.js \ browser_privatebrowsing_viewsource.js \ browser_privatebrowsing_windowtitle.js \ browser_privatebrowsing_windowtitle_page.html \ diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js new file mode 100644 index 000000000000..0e6df75dc621 --- /dev/null +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js @@ -0,0 +1,66 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Private Browsing Tests. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ehsan Akhgari (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +// This test makes sure that the undo history of the URL bar is cleared when +// leaving the private browsing mode. + +function test() { + // initialization + let prefBranch = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true); + let pb = Cc["@mozilla.org/privatebrowsing;1"]. + getService(Ci.nsIPrivateBrowsingService); + + // enter private browsing mode + pb.privateBrowsingEnabled = true; + + // fill in the URL bar with something + gURLBar.value = "some test value"; + + ok(gURLBar.editor.transactionManager.numberOfUndoItems > 0, + "The undo history for the URL bar should not be empty"); + + // leave private browsing mode + pb.privateBrowsingEnabled = false; + + is(gURLBar.editor.transactionManager.numberOfUndoItems, 0, + "The undo history of the URL bar should be cleared after leaving the private browsing mode"); + + // cleanup + prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session"); +} + From ae227d8320027b6f21de47f25511c362147aa26b Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 31 Mar 2010 17:44:47 -0400 Subject: [PATCH 03/69] Bug 555851 - nsHTMLFragmentContentSink::AddTextToContent is dead code; r=jst --- .../src/nsHTMLFragmentContentSink.cpp | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/content/html/document/src/nsHTMLFragmentContentSink.cpp b/content/html/document/src/nsHTMLFragmentContentSink.cpp index 21f0971ce3c4..7cddd9dc934e 100644 --- a/content/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp @@ -134,7 +134,6 @@ public: nsIContent* aContent); nsresult AddText(const nsAString& aString); - nsresult AddTextToContent(nsIContent* aContent, const nsAString& aText); nsresult FlushText(); void ProcessBaseTag(nsIContent* aContent); @@ -763,26 +762,6 @@ nsHTMLFragmentContentSink::AddText(const nsAString& aString) return NS_OK; } -nsresult -nsHTMLFragmentContentSink::AddTextToContent(nsIContent* aContent, const nsAString& aText) { - NS_ASSERTION(aContent !=nsnull, "can't add text w/o a content"); - - nsresult result=NS_OK; - - if(aContent) { - if (!aText.IsEmpty()) { - nsCOMPtr text; - result = NS_NewTextNode(getter_AddRefs(text), mNodeInfoManager); - if (NS_SUCCEEDED(result)) { - text->SetText(aText, PR_TRUE); - - result = aContent->AppendChildTo(text, PR_FALSE); - } - } - } - return result; -} - nsresult nsHTMLFragmentContentSink::FlushText() { From 724ecf37b94e269ec8b3d51f1879a8e2deb1346f Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Wed, 31 Mar 2010 17:00:04 -0700 Subject: [PATCH 04/69] Add dumps to crashtest in the hope of shedding light on orange bug 471185 --- editor/composer/src/crashtests/428844-1-inner.xhtml | 2 +- editor/composer/src/crashtests/428844-1.html | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/editor/composer/src/crashtests/428844-1-inner.xhtml b/editor/composer/src/crashtests/428844-1-inner.xhtml index 905d38e2d8f5..1cc72d085699 100644 --- a/editor/composer/src/crashtests/428844-1-inner.xhtml +++ b/editor/composer/src/crashtests/428844-1-inner.xhtml @@ -1,4 +1,4 @@ - + diff --git a/editor/composer/src/crashtests/428844-1.html b/editor/composer/src/crashtests/428844-1.html index 11143ab72a80..1815118d235e 100644 --- a/editor/composer/src/crashtests/428844-1.html +++ b/editor/composer/src/crashtests/428844-1.html @@ -4,10 +4,11 @@ function boom() { var iframe = document.getElementById('inner'); iframe.src = iframe.src; + dump("Outer onload\n"); } - From 8a8adc758b8af503895988ed8876573717e1912b Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Wed, 31 Mar 2010 17:43:32 -0700 Subject: [PATCH 05/69] Bug 494117 preliminary refactor: Search-and-replace 'ReStyle' with 'Restyle' throughout layout. r=roc --- layout/base/nsCSSFrameConstructor.cpp | 42 +++++++++++++-------------- layout/base/nsCSSFrameConstructor.h | 10 +++---- layout/base/nsChangeHint.h | 10 +++---- layout/base/nsFrameManager.cpp | 6 ++-- layout/base/nsFrameManager.h | 2 +- layout/base/nsPresShell.cpp | 8 ++--- layout/mathml/nsMathMLTokenFrame.cpp | 2 +- layout/mathml/nsMathMLmtableFrame.cpp | 6 ++-- layout/style/nsCSSRuleProcessor.cpp | 24 +++++++-------- layout/style/nsCSSRuleProcessor.h | 4 +-- layout/style/nsHTMLCSSStyleSheet.cpp | 8 ++--- layout/style/nsHTMLCSSStyleSheet.h | 4 +-- layout/style/nsHTMLStyleSheet.cpp | 16 +++++----- layout/style/nsHTMLStyleSheet.h | 4 +-- layout/style/nsIStyleRuleProcessor.h | 6 ++-- layout/style/nsStyleSet.cpp | 26 ++++++++--------- layout/style/nsStyleSet.h | 4 +-- layout/style/nsTransitionManager.cpp | 8 ++--- layout/style/nsTransitionManager.h | 4 +-- layout/svg/base/src/nsSVGEffects.cpp | 4 +-- 20 files changed, 99 insertions(+), 99 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 9618daf3dac2..634e176484f7 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7645,7 +7645,7 @@ nsCSSFrameConstructor::DoContentStateChanged(nsIContent* aContent, } } - nsReStyleHint rshint = + nsRestyleHint rshint = styleSet->HasStateDependentStyle(presContext, aContent, aStateMask); if ((aStateMask & NS_EVENT_STATE_HOVER) && rshint != 0) { @@ -7662,7 +7662,7 @@ nsCSSFrameConstructor::AttributeWillChange(nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType) { - nsReStyleHint rshint = + nsRestyleHint rshint = mPresShell->FrameManager()->HasAttributeDependentStyle(aContent, aAttribute, aModType, @@ -7749,7 +7749,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIContent* aContent, // See if we can optimize away the style re-resolution -- must be called after // the frame's AttributeChanged() in case it does something that affects the style nsFrameManager *frameManager = shell->FrameManager(); - nsReStyleHint rshint = frameManager->HasAttributeDependentStyle(aContent, + nsRestyleHint rshint = frameManager->HasAttributeDependentStyle(aContent, aAttribute, aModType, PR_TRUE); @@ -8601,7 +8601,7 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, // ContentRemoved triggered reconstruction, then we don't need to do this // because the frames will already have been built. if (aAsyncInsert) { - PostRestyleEvent(aContent, nsReStyleHint(0), nsChangeHint_ReconstructFrame); + PostRestyleEvent(aContent, nsRestyleHint(0), nsChangeHint_ReconstructFrame); } else { rv = ContentInserted(container, aContent, indexInContainer, mTempFrameTreeState); @@ -10797,7 +10797,7 @@ nsCSSFrameConstructor::RestyleForAppend(nsIContent* aContainer, return; if (selectorFlags & NODE_HAS_SLOW_SELECTOR) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10817,7 +10817,7 @@ nsCSSFrameConstructor::RestyleForAppend(nsIContent* aContainer, } } if (wasEmpty) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10827,7 +10827,7 @@ nsCSSFrameConstructor::RestyleForAppend(nsIContent* aContainer, for (PRInt32 index = aNewIndexInContainer - 1; index >= 0; --index) { nsIContent *content = aContainer->GetChildAt(index); if (content->IsNodeOfType(nsINode::eELEMENT)) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); break; } } @@ -10853,7 +10853,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, if (selectorFlags & (NODE_HAS_SLOW_SELECTOR | NODE_HAS_SLOW_SELECTOR_NOAPPEND)) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10877,7 +10877,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, } } if (wasEmpty) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10896,7 +10896,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, } if (content->IsNodeOfType(nsINode::eELEMENT)) { if (passedChild) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -10912,7 +10912,7 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer, } if (content->IsNodeOfType(nsINode::eELEMENT)) { if (passedChild) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -10934,7 +10934,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, if (selectorFlags & (NODE_HAS_SLOW_SELECTOR | NODE_HAS_SLOW_SELECTOR_NOAPPEND)) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10956,7 +10956,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, } } if (isEmpty) { - PostRestyleEvent(aContainer, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE); // Restyling the container is the most we can do here, so we're done. return; } @@ -10970,7 +10970,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, break; // went through all children if (content->IsNodeOfType(nsINode::eELEMENT)) { if (index >= aIndexInContainer) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -10981,7 +10981,7 @@ nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer, nsIContent *content = aContainer->GetChildAt(index); if (content->IsNodeOfType(nsINode::eELEMENT)) { if (index < aIndexInContainer) { - PostRestyleEvent(content, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(content, eRestyle_Self, NS_STYLE_HINT_NONE); } break; } @@ -11012,7 +11012,7 @@ CollectRestyles(nsISupports* aContent, void nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, - nsReStyleHint aRestyleHint, + nsRestyleHint aRestyleHint, nsChangeHint aChangeHint) { NS_PRECONDITION(aContent, "Must have content node"); @@ -11025,7 +11025,7 @@ nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, } nsIFrame* primaryFrame = aContent->GetPrimaryFrame(); - if (aRestyleHint & eReStyle_Self) { + if (aRestyleHint & eRestyle_Self) { RestyleElement(aContent, primaryFrame, aChangeHint); } else if (aChangeHint && (primaryFrame || @@ -11036,7 +11036,7 @@ nsCSSFrameConstructor::ProcessOneRestyle(nsIContent* aContent, ProcessRestyledFrames(changeList); } - if (aRestyleHint & eReStyle_LaterSiblings) { + if (aRestyleHint & eRestyle_LaterSiblings) { RestyleLaterSiblings(aContent); } } @@ -11198,7 +11198,7 @@ nsCSSFrameConstructor::ProcessPendingRestyles() void nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent, - nsReStyleHint aRestyleHint, + nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint, PRBool aForAnimation) { @@ -11215,7 +11215,7 @@ nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent, "Shouldn't be trying to restyle non-elements directly"); RestyleData existingData; - existingData.mRestyleHint = nsReStyleHint(0); + existingData.mRestyleHint = nsRestyleHint(0); existingData.mChangeHint = NS_STYLE_HINT_NONE; nsDataHashtable &restyles = @@ -11223,7 +11223,7 @@ nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent, restyles.Get(aContent, &existingData); existingData.mRestyleHint = - nsReStyleHint(existingData.mRestyleHint | aRestyleHint); + nsRestyleHint(existingData.mRestyleHint | aRestyleHint); NS_UpdateHint(existingData.mChangeHint, aMinChangeHint); restyles.Put(aContent, existingData); diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 989e3e0821d5..a44b47b9376e 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -193,7 +193,7 @@ private: // This function does not call ProcessAttachedQueue() on the binding manager. // If the caller wants that to happen synchronously, it needs to handle that // itself. - void ProcessOneRestyle(nsIContent* aContent, nsReStyleHint aRestyleHint, + void ProcessOneRestyle(nsIContent* aContent, nsRestyleHint aRestyleHint, nsChangeHint aChangeHint); void ProcessPendingRestyleTable( @@ -229,7 +229,7 @@ public: void RebuildAllStyleData(nsChangeHint aExtraHint); // See PostRestyleEventCommon below. - void PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint, + void PostRestyleEvent(nsIContent* aContent, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { nsPresContext *presContext = mPresShell->GetPresContext(); @@ -241,7 +241,7 @@ public: // See PostRestyleEventCommon below. void PostAnimationRestyleEvent(nsIContent* aContent, - nsReStyleHint aRestyleHint, + nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint) { PostRestyleEventCommon(aContent, aRestyleHint, aMinChangeHint, PR_TRUE); @@ -265,7 +265,7 @@ private: * IsProcessingAnimationStyleChange() value * (which is the default value). */ - void PostRestyleEventCommon(nsIContent* aContent, nsReStyleHint aRestyleHint, + void PostRestyleEventCommon(nsIContent* aContent, nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint, PRBool aForAnimation); void PostRestyleEventInternal(); @@ -1698,7 +1698,7 @@ private: public: struct RestyleData { - nsReStyleHint mRestyleHint; // What we want to restyle + nsRestyleHint mRestyleHint; // What we want to restyle nsChangeHint mChangeHint; // The minimal change hint for "self" }; diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index b6a22179d176..6677c7a61105 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -139,13 +139,13 @@ inline PRBool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) { nsChangeHint(NS_STYLE_HINT_REFLOW | nsChangeHint_ReconstructFrame) /** - * |nsReStyleHint| is a bitfield for the result of |HasStateDependentStyle| + * |nsRestyleHint| is a bitfield for the result of |HasStateDependentStyle| * and |HasAttributeDependentStyle|. All values have an implied "and - * descendants." When no restyling is necessary, use |nsReStyleHint(0)|. + * descendants." When no restyling is necessary, use |nsRestyleHint(0)|. */ -enum nsReStyleHint { - eReStyle_Self = 0x1, - eReStyle_LaterSiblings = 0x2 +enum nsRestyleHint { + eRestyle_Self = 0x1, + eRestyle_LaterSiblings = 0x2 }; diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index d89399ae2189..53f14769ed1e 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -1505,13 +1505,13 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame, } -nsReStyleHint +nsRestyleHint nsFrameManager::HasAttributeDependentStyle(nsIContent *aContent, nsIAtom *aAttribute, PRInt32 aModType, PRBool aAttrHasChanged) { - nsReStyleHint hint = mStyleSet->HasAttributeDependentStyle(GetPresContext(), + nsRestyleHint hint = mStyleSet->HasAttributeDependentStyle(GetPresContext(), aContent, aAttribute, aModType, @@ -1521,7 +1521,7 @@ nsFrameManager::HasAttributeDependentStyle(nsIContent *aContent, // Perhaps should check that it's XUL, SVG, (or HTML) namespace, but // it doesn't really matter. Or we could even let // HTMLCSSStyleSheetImpl::HasAttributeDependentStyle handle it. - hint = nsReStyleHint(hint | eReStyle_Self); + hint = nsRestyleHint(hint | eRestyle_Self); } return hint; diff --git a/layout/base/nsFrameManager.h b/layout/base/nsFrameManager.h index 5088c67d8188..d8b184788695 100644 --- a/layout/base/nsFrameManager.h +++ b/layout/base/nsFrameManager.h @@ -163,7 +163,7 @@ public: // Determine whether an attribute affects style // If aAttrHasChanged is false, the attribute's value is about to // change. If it's true, it has already changed. - NS_HIDDEN_(nsReStyleHint) HasAttributeDependentStyle(nsIContent *aContent, + NS_HIDDEN_(nsRestyleHint) HasAttributeDependentStyle(nsIContent *aContent, nsIAtom *aAttribute, PRInt32 aModType, PRBool aAttrHasChanged); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 7a33295fcb83..f979f209b849 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -3496,14 +3496,14 @@ PresShell::RecreateFramesFor(nsIContent* aContent) void nsIPresShell::PostRecreateFramesFor(nsIContent* aContent) { - FrameConstructor()->PostRestyleEvent(aContent, eReStyle_Self, + FrameConstructor()->PostRestyleEvent(aContent, eRestyle_Self, nsChangeHint_ReconstructFrame); } void nsIPresShell::RestyleForAnimation(nsIContent* aContent) { - FrameConstructor()->PostAnimationRestyleEvent(aContent, eReStyle_Self, + FrameConstructor()->PostAnimationRestyleEvent(aContent, eRestyle_Self, NS_STYLE_HINT_NONE); } @@ -4750,7 +4750,7 @@ PresShell::DocumentStatesChanged(nsIDocument* aDocument, mDocument->GetRootContent(), aStateMask)) { mFrameConstructor->PostRestyleEvent(mDocument->GetRootContent(), - eReStyle_Self, NS_STYLE_HINT_NONE); + eRestyle_Self, NS_STYLE_HINT_NONE); VERIFY_STYLE_TREE; } } @@ -4924,7 +4924,7 @@ nsIPresShell::ReconstructStyleDataInternal() return; } - mFrameConstructor->PostRestyleEvent(root, eReStyle_Self, NS_STYLE_HINT_NONE); + mFrameConstructor->PostRestyleEvent(root, eRestyle_Self, NS_STYLE_HINT_NONE); #ifdef ACCESSIBILITY InvalidateAccessibleSubtree(nsnull); diff --git a/layout/mathml/nsMathMLTokenFrame.cpp b/layout/mathml/nsMathMLTokenFrame.cpp index 7e07ff57241e..0d4074e01ee5 100644 --- a/layout/mathml/nsMathMLTokenFrame.cpp +++ b/layout/mathml/nsMathMLTokenFrame.cpp @@ -276,7 +276,7 @@ nsMathMLTokenFrame::ProcessTextData() // explicitly request a re-resolve to pick up the change of style PresContext()->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, NS_STYLE_HINT_NONE); + PostRestyleEvent(mContent, eRestyle_Self, NS_STYLE_HINT_NONE); } /////////////////////////////////////////////////////////////////////////// diff --git a/layout/mathml/nsMathMLmtableFrame.cpp b/layout/mathml/nsMathMLmtableFrame.cpp index 8ca08e3e4573..b8b172312a00 100644 --- a/layout/mathml/nsMathMLmtableFrame.cpp +++ b/layout/mathml/nsMathMLmtableFrame.cpp @@ -525,7 +525,7 @@ nsMathMLmtableOuterFrame::AttributeChanged(PRInt32 aNameSpaceID, // Explicitly request a re-resolve and reflow in our subtree to pick up any changes presContext->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, nsChangeHint_ReflowFrame); + PostRestyleEvent(mContent, eRestyle_Self, nsChangeHint_ReflowFrame); return NS_OK; } @@ -704,7 +704,7 @@ nsMathMLmtableFrame::RestyleTable() // Explicitly request a re-resolve and reflow in our subtree to pick up any changes PresContext()->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, nsChangeHint_ReflowFrame); + PostRestyleEvent(mContent, eRestyle_Self, nsChangeHint_ReflowFrame); } // -------- @@ -764,7 +764,7 @@ nsMathMLmtrFrame::AttributeChanged(PRInt32 aNameSpaceID, // Explicitly request a re-resolve and reflow in our subtree to pick up any changes presContext->PresShell()->FrameConstructor()-> - PostRestyleEvent(mContent, eReStyle_Self, nsChangeHint_ReflowFrame); + PostRestyleEvent(mContent, eRestyle_Self, nsChangeHint_ReflowFrame); return NS_OK; } diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 258f3c755f85..41361dc1f272 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -2271,7 +2271,7 @@ IsSiblingOperator(PRUnichar oper) return oper == PRUnichar('+') || oper == PRUnichar('~'); } -nsReStyleHint +nsRestyleHint nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) { NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT), @@ -2287,15 +2287,15 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) // "body > p:hover" will be in |cascade->mStateSelectors|). Note that // |IsStateSelector| below determines which selectors are in // |cascade->mStateSelectors|. - nsReStyleHint hint = nsReStyleHint(0); + nsRestyleHint hint = nsRestyleHint(0); if (cascade) { nsCSSSelector **iter = cascade->mStateSelectors.Elements(), **end = iter + cascade->mStateSelectors.Length(); for(; iter != end; ++iter) { nsCSSSelector* selector = *iter; - nsReStyleHint possibleChange = IsSiblingOperator(selector->mOperator) ? - eReStyle_LaterSiblings : eReStyle_Self; + nsRestyleHint possibleChange = IsSiblingOperator(selector->mOperator) ? + eRestyle_LaterSiblings : eRestyle_Self; // If hint already includes all the bits of possibleChange, // don't bother calling SelectorMatches, since even if it returns false @@ -2303,7 +2303,7 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) if ((possibleChange & ~hint) && SelectorMatches(*aData, selector, aData->mStateMask, PR_FALSE) && SelectorMatchesTree(*aData, selector->mNext, PR_FALSE)) { - hint = nsReStyleHint(hint | possibleChange); + hint = nsRestyleHint(hint | possibleChange); } } } @@ -2320,10 +2320,10 @@ nsCSSRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessorData* aData struct AttributeEnumData { AttributeEnumData(AttributeRuleProcessorData *aData) - : data(aData), change(nsReStyleHint(0)) {} + : data(aData), change(nsRestyleHint(0)) {} AttributeRuleProcessorData *data; - nsReStyleHint change; + nsRestyleHint change; }; @@ -2332,8 +2332,8 @@ AttributeEnumFunc(nsCSSSelector* aSelector, AttributeEnumData* aData) { AttributeRuleProcessorData *data = aData->data; - nsReStyleHint possibleChange = IsSiblingOperator(aSelector->mOperator) ? - eReStyle_LaterSiblings : eReStyle_Self; + nsRestyleHint possibleChange = IsSiblingOperator(aSelector->mOperator) ? + eRestyle_LaterSiblings : eRestyle_Self; // If enumData->change already includes all the bits of possibleChange, don't // bother calling SelectorMatches, since even if it returns false @@ -2341,11 +2341,11 @@ AttributeEnumFunc(nsCSSSelector* aSelector, AttributeEnumData* aData) if ((possibleChange & ~(aData->change)) && SelectorMatches(*data, aSelector, 0, PR_FALSE) && SelectorMatchesTree(*data, aSelector->mNext, PR_FALSE)) { - aData->change = nsReStyleHint(aData->change | possibleChange); + aData->change = nsRestyleHint(aData->change | possibleChange); } } -nsReStyleHint +nsRestyleHint nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT), @@ -2365,7 +2365,7 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData aData->mNameSpaceID == kNameSpaceID_XUL && aData->mContent == aData->mContent->GetOwnerDoc()->GetRootContent()) { - data.change = nsReStyleHint(data.change | eReStyle_Self); + data.change = nsRestyleHint(data.change | eRestyle_Self); } } diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index ff785d62e021..89c4053036ae 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -102,11 +102,11 @@ public: NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index fe8cf4213d6b..ed9e5faeade0 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -142,10 +142,10 @@ nsHTMLCSSStyleSheet::Init(nsIURI* aURL, nsIDocument* aDocument) } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsHTMLCSSStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } PRBool @@ -155,10 +155,10 @@ nsHTMLCSSStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aDat } // Test if style is dependent on attribute -nsReStyleHint +nsRestyleHint nsHTMLCSSStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } NS_IMETHODIMP diff --git a/layout/style/nsHTMLCSSStyleSheet.h b/layout/style/nsHTMLCSSStyleSheet.h index 603b61253ca0..8cd4fce181c3 100644 --- a/layout/style/nsHTMLCSSStyleSheet.h +++ b/layout/style/nsHTMLCSSStyleSheet.h @@ -79,9 +79,9 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, PRBool* aResult); diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 76f2914d1236..680e9e34e0bd 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -286,7 +286,7 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) { if (aData->mIsHTMLContent && @@ -295,10 +295,10 @@ nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) ((mActiveRule && (aData->mStateMask & NS_EVENT_STATE_ACTIVE)) || (mLinkRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)) || (mVisitedRule && (aData->mStateMask & NS_EVENT_STATE_VISITED)))) { - return eReStyle_Self; + return eRestyle_Self; } - return nsReStyleHint(0); + return nsRestyleHint(0); } PRBool @@ -307,12 +307,12 @@ nsHTMLStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) return PR_FALSE; } -nsReStyleHint +nsRestyleHint nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { // Do nothing on before-change checks if (!aData->mAttrHasChanged) { - return nsReStyleHint(0); + return nsRestyleHint(0); } // Note: no need to worry about whether some states changed with this @@ -326,7 +326,7 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) content && content->IsHTML() && aData->mContentTag == nsGkAtoms::a) { - return eReStyle_Self; + return eRestyle_Self; } // Don't worry about the mDocumentColorRule since it only applies @@ -334,10 +334,10 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) // Handle the content style rules. if (content && content->IsAttributeMapped(aData->mAttribute)) { - return eReStyle_Self; + return eRestyle_Self; } - return nsReStyleHint(0); + return nsRestyleHint(0); } NS_IMETHODIMP diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index 46f7fe2d761e..8c7ad8e31c0f 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -84,9 +84,9 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, PRBool* aRulesChanged); diff --git a/layout/style/nsIStyleRuleProcessor.h b/layout/style/nsIStyleRuleProcessor.h index b9b206bb925f..3b6a6e4c91c3 100644 --- a/layout/style/nsIStyleRuleProcessor.h +++ b/layout/style/nsIStyleRuleProcessor.h @@ -118,14 +118,14 @@ public: HasDocumentStateDependentStyle(StateRuleProcessorData* aData) = 0; /** - * Return how (as described by nsReStyleHint) style can depend on a + * Return how (as described by nsRestyleHint) style can depend on a * change of the given content state on the given content node. This * test is used for optimization only, and may err on the side of * reporting more dependencies than really exist. * * Event states are defined in nsIEventStateManager.h. */ - virtual nsReStyleHint + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) = 0; /** @@ -144,7 +144,7 @@ public: * only, and may err on the side of reporting more dependencies than * really exist. */ - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData) = 0; /** diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 188fd9b86551..9079602a57d0 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -1072,9 +1072,9 @@ struct StatefulData : public StateRuleProcessorData { StatefulData(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask) : StateRuleProcessorData(aPresContext, aContent, aStateMask), - mHint(nsReStyleHint(0)) + mHint(nsRestyleHint(0)) {} - nsReStyleHint mHint; + nsRestyleHint mHint; }; static PRBool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor, @@ -1082,7 +1082,7 @@ static PRBool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor, { StatefulData* data = (StatefulData*)aData; if (aProcessor->HasDocumentStateDependentStyle(data)) { - data->mHint = eReStyle_Self; + data->mHint = eRestyle_Self; return PR_FALSE; // don't continue } return PR_TRUE; // continue @@ -1106,18 +1106,18 @@ static PRBool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { StatefulData* data = (StatefulData*)aData; - nsReStyleHint hint = aProcessor->HasStateDependentStyle(data); - data->mHint = nsReStyleHint(data->mHint | hint); + nsRestyleHint hint = aProcessor->HasStateDependentStyle(data); + data->mHint = nsRestyleHint(data->mHint | hint); return PR_TRUE; // continue } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsStyleSet::HasStateDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask) { - nsReStyleHint result = nsReStyleHint(0); + nsRestyleHint result = nsRestyleHint(0); if (aContent->IsNodeOfType(nsINode::eELEMENT)) { StatefulData data(aPresContext, aContent, aStateMask); @@ -1134,29 +1134,29 @@ struct AttributeData : public AttributeRuleProcessorData { PRBool aAttrHasChanged) : AttributeRuleProcessorData(aPresContext, aContent, aAttribute, aModType, aAttrHasChanged), - mHint(nsReStyleHint(0)) + mHint(nsRestyleHint(0)) {} - nsReStyleHint mHint; + nsRestyleHint mHint; }; static PRBool SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) { AttributeData* data = (AttributeData*)aData; - nsReStyleHint hint = aProcessor->HasAttributeDependentStyle(data); - data->mHint = nsReStyleHint(data->mHint | hint); + nsRestyleHint hint = aProcessor->HasAttributeDependentStyle(data); + data->mHint = nsRestyleHint(data->mHint | hint); return PR_TRUE; // continue } // Test if style is dependent on content state -nsReStyleHint +nsRestyleHint nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType, PRBool aAttrHasChanged) { - nsReStyleHint result = nsReStyleHint(0); + nsRestyleHint result = nsRestyleHint(0); if (aContent->IsNodeOfType(nsINode::eELEMENT)) { AttributeData data(aPresContext, aContent, aAttribute, aModType, diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index c8fada845157..4d56e1238ab8 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -183,12 +183,12 @@ class nsStyleSet PRInt32 aStateMask); // Test if style is dependent on content state - nsReStyleHint HasStateDependentStyle(nsPresContext* aPresContext, + nsRestyleHint HasStateDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, PRInt32 aStateMask); // Test if style is dependent on the presence of an attribute. - nsReStyleHint HasAttributeDependentStyle(nsPresContext* aPresContext, + nsRestyleHint HasAttributeDependentStyle(nsPresContext* aPresContext, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType, diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 36a99f17062a..8cf6305c242b 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -886,10 +886,10 @@ nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData) } #endif -nsReStyleHint +nsRestyleHint nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } PRBool @@ -898,10 +898,10 @@ nsTransitionManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aDat return PR_FALSE; } -nsReStyleHint +nsRestyleHint nsTransitionManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) { - return nsReStyleHint(0); + return nsRestyleHint(0); } NS_IMETHODIMP diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 373e88655fa4..680585421a43 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -92,9 +92,9 @@ public: #ifdef MOZ_XUL NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData); #endif - virtual nsReStyleHint HasStateDependentStyle(StateRuleProcessorData* aData); + virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData); virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData); - virtual nsReStyleHint + virtual nsRestyleHint HasAttributeDependentStyle(AttributeRuleProcessorData* aData); NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext, PRBool* aRulesChanged); diff --git a/layout/svg/base/src/nsSVGEffects.cpp b/layout/svg/base/src/nsSVGEffects.cpp index bd990bbc75e5..237c4b5a47c6 100644 --- a/layout/svg/base/src/nsSVGEffects.cpp +++ b/layout/svg/base/src/nsSVGEffects.cpp @@ -255,7 +255,7 @@ nsSVGFilterProperty::DoUpdate() NS_UpdateHint(changeHint, nsChangeHint_ReflowFrame); } mFramePresShell->FrameConstructor()->PostRestyleEvent( - mFrame->GetContent(), nsReStyleHint(0), changeHint); + mFrame->GetContent(), nsRestyleHint(0), changeHint); } void @@ -272,7 +272,7 @@ nsSVGMarkerProperty::DoUpdate() nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects); mFramePresShell->FrameConstructor()->PostRestyleEvent( - mFrame->GetContent(), nsReStyleHint(0), changeHint); + mFrame->GetContent(), nsRestyleHint(0), changeHint); } void From f7c951c2c7292a3becc6e1686777aa45c1a136a0 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 1 Apr 2010 03:44:02 +0200 Subject: [PATCH 06/69] Bug 556288: Use linear filters so framebuffers can use the same texture on all hardware. Assert succes. r=joedrew --- gfx/layers/opengl/ContainerLayerOGL.cpp | 6 ++++++ gfx/layers/opengl/glDefs.h | 1 + gfx/layers/opengl/glWrapper.cpp | 2 ++ gfx/layers/opengl/glWrapper.h | 5 ++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp index 01028a37f56a..c93d623c56ae 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -144,6 +144,8 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_BYTE, NULL); + sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); + sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); /** * Create the framebuffer and bind it to make our content render into our @@ -158,6 +160,10 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) containerSurface, 0); + NS_ASSERTION( + sglWrapper.CheckFramebufferStatusEXT(LOCAL_GL_FRAMEBUFFER_EXT) == + LOCAL_GL_FRAMEBUFFER_COMPLETE, "Error setting up framebuffer."); + RGBLayerProgram *rgbProgram = static_cast(mManager)->GetRGBLayerProgram(); YCbCrLayerProgram *yCbCrProgram = diff --git a/gfx/layers/opengl/glDefs.h b/gfx/layers/opengl/glDefs.h index 65168f1c19e2..278d45f96dee 100644 --- a/gfx/layers/opengl/glDefs.h +++ b/gfx/layers/opengl/glDefs.h @@ -3024,5 +3024,6 @@ typedef ptrdiff_t GLintptr; #define LOCAL_GL_FRAMEBUFFER_EXT 0x8D40 #define LOCAL_GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define LOCAL_GL_FRAMEBUFFER_COMPLETE 0x8CD5 #endif diff --git a/gfx/layers/opengl/glWrapper.cpp b/gfx/layers/opengl/glWrapper.cpp index f275cc84bd1a..f1e3648ee3fd 100644 --- a/gfx/layers/opengl/glWrapper.cpp +++ b/gfx/layers/opengl/glWrapper.cpp @@ -38,6 +38,7 @@ #include "glWrapper.h" #include "nsDebug.h" + #ifdef XP_WIN #define glGetProcAddress wGetProcAddress #else @@ -170,6 +171,7 @@ glWrapper::EnsureInitialized() { (PRFuncPtr*) &BindFramebufferEXT, "glBindFramebufferEXT" }, { (PRFuncPtr*) &FramebufferTexture2DEXT, "glFramebufferTexture2DEXT" }, + { (PRFuncPtr*) &CheckFramebufferStatusEXT, "glCheckFramebufferStatusEXT" }, { (PRFuncPtr*) &BufferData, "glBufferData" }, diff --git a/gfx/layers/opengl/glWrapper.h b/gfx/layers/opengl/glWrapper.h index 8c0a8a5e2d40..ea28133bb309 100644 --- a/gfx/layers/opengl/glWrapper.h +++ b/gfx/layers/opengl/glWrapper.h @@ -103,7 +103,8 @@ public: GLenum, GLenum, GLuint, - GLint); + GLint); + typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum); typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum, GLsizeiptr, @@ -214,6 +215,8 @@ public: PFNGLGENFRAMEBUFFERSEXTPROC GenFramebuffersEXT; PFNGLDELETETEXTURESPROC DeleteTextures; PFNGLDELETEFRAMEBUFFERSEXTPROC DeleteFramebuffersEXT; + + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC CheckFramebufferStatusEXT; PFNGLBINDTEXTUREPROC BindTexture; PFNGLBINDBUFFERPROC BindBuffer; From 4a42fdf506d73836cf1337c31c6f3dc6f226a60d Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 1 Apr 2010 03:44:05 +0200 Subject: [PATCH 07/69] Bug 556387: Fix OpenGL context creation for some drivers. r=joedrew --- gfx/layers/opengl/LayerManagerOGL.cpp | 12 ------------ gfx/layers/opengl/glWrapper.cpp | 27 ++++++++++++++++++++++----- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 92473d44b0c5..b6c50dc615ec 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -83,19 +83,7 @@ LayerManagerOGL::Initialize() { #ifdef XP_WIN mDC = (HDC)mWidget->GetNativeData(NS_NATIVE_GRAPHIC); - PIXELFORMATDESCRIPTOR pfd; - ZeroMemory(&pfd, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - pfd.cDepthBits = 0; - pfd.iLayerType = PFD_MAIN_PLANE; - int iFormat = ChoosePixelFormat(mDC, &pfd); - - SetPixelFormat(mDC, iFormat, &pfd); mContext = sglWrapper.wCreateContext(mDC); if (!mContext) { diff --git a/gfx/layers/opengl/glWrapper.cpp b/gfx/layers/opengl/glWrapper.cpp index f1e3648ee3fd..b6c7f1b6850b 100644 --- a/gfx/layers/opengl/glWrapper.cpp +++ b/gfx/layers/opengl/glWrapper.cpp @@ -38,7 +38,6 @@ #include "glWrapper.h" #include "nsDebug.h" - #ifdef XP_WIN #define glGetProcAddress wGetProcAddress #else @@ -80,14 +79,32 @@ glWrapper::wCreateContext(HDC aDC) } wCreateContextInternal = (PFNWGLCREATECONTEXTPROC) - PR_FindSymbol(mOGLLibrary, "wglCreateContext"); + PR_FindFunctionSymbol(mOGLLibrary, "wglCreateContext"); wDeleteContext = (PFNWGLDELETECONTEXTPROC) - PR_FindSymbol(mOGLLibrary, "wglDeleteContext"); + PR_FindFunctionSymbol(mOGLLibrary, "wglDeleteContext"); wMakeCurrent = (PFNWGLMAKECURRENTPROC) - PR_FindSymbol(mOGLLibrary, "wglMakeCurrent"); + PR_FindFunctionSymbol(mOGLLibrary, "wglMakeCurrent"); wGetProcAddress = (PFNWGLGETPROCADDRESSPROC) - PR_FindSymbol(mOGLLibrary, "wglGetProcAddress"); + PR_FindFunctionSymbol(mOGLLibrary, "wglGetProcAddress"); } + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(pfd)); + + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cDepthBits = 0; + pfd.iLayerType = PFD_MAIN_PLANE; + int iFormat = ChoosePixelFormat(aDC, &pfd); + + /** + * We need to make sure we call SetPixelFormat -after- loading the OGL + * library, otherwise it can load/unload the dll and wglCreateContext + * will fail. + */ + SetPixelFormat(aDC, iFormat, &pfd); HGLRC retval = wCreateContextInternal(aDC); if (!retval) { From f88647e545d63756f2f6194efee3e1298e219097 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 1 Apr 2010 11:35:48 +0900 Subject: [PATCH 08/69] Bug 554822 Caret should refer the actual text color instead of the value of CSS color property r=roc --- layout/base/nsCaret.cpp | 18 ++++++++---- layout/base/nsCaret.h | 4 ++- layout/generic/nsFrame.cpp | 7 +++++ layout/generic/nsIFrame.h | 7 +++++ layout/generic/nsTextFrame.h | 2 ++ layout/generic/nsTextFrameThebes.cpp | 42 ++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index a40b20788f6f..1bda957fbf8a 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -497,7 +497,7 @@ nsresult nsCaret::DrawAtPosition(nsIDOMNode* aNode, PRInt32 aOffset) return rv; } -nsIFrame * nsCaret::GetCaretFrame() +nsIFrame * nsCaret::GetCaretFrame(PRInt32 *aOffset) { // Return null if we're not drawn to prevent anybody from trying to draw us. if (!mDrawn) @@ -505,14 +505,17 @@ nsIFrame * nsCaret::GetCaretFrame() // Recompute the frame that we're supposed to draw in to guarantee that // we're not going to try to draw into a stale (dead) frame. - PRInt32 unused; + PRInt32 offset; nsIFrame *frame = nsnull; nsresult rv = GetCaretFrameForNodeOffset(mLastContent, mLastContentOffset, mLastHint, mLastBidiLevel, &frame, - &unused); + &offset); if (NS_FAILED(rv)) return nsnull; + if (aOffset) { + *aOffset = offset; + } return frame; } @@ -545,7 +548,10 @@ void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, NS_ASSERTION(mDrawn, "The caret shouldn't be drawing"); const nsRect drawCaretRect = mCaretRect + aOffset; - nscolor cssColor = aForFrame->GetStyleColor()->mColor; + PRInt32 contentOffset; + nsIFrame* frame = GetCaretFrame(&contentOffset); + NS_ASSERTION(frame == aForFrame, "We're referring different frame"); + nscolor foregroundColor = aForFrame->GetCaretColorAt(contentOffset); // Only draw the native caret if the foreground color matches that of // -moz-fieldtext (the color of the text in a textbox). If it doesn't match @@ -559,7 +565,7 @@ void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, nsILookAndFeel* lookAndFeel = presContext->LookAndFeel(); nscolor fieldText; if (NS_SUCCEEDED(lookAndFeel->GetColor(nsILookAndFeel::eColor__moz_fieldtext, fieldText)) && - fieldText == cssColor) { + fieldText == foregroundColor) { theme->DrawWidgetBackground(aCtx, aForFrame, NS_THEME_TEXTFIELD_CARET, drawCaretRect, drawCaretRect); return; @@ -567,7 +573,7 @@ void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, } } - aCtx->SetColor(cssColor); + aCtx->SetColor(foregroundColor); aCtx->FillRect(drawCaretRect); if (!GetHookRect().IsEmpty()) aCtx->FillRect(GetHookRect() + aOffset); diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index dc74d1d9689e..74346d819861 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -136,8 +136,10 @@ class nsCaret : public nsISelectionListener * Get the current frame that the caret should be drawn in. If the caret is * not currently visible (i.e., it is between blinks), then this will * return null. + * + * @param aOffset is result of the caret offset in the content. */ - nsIFrame* GetCaretFrame(); + nsIFrame* GetCaretFrame(PRInt32 *aOffset = nsnull); /** GetCaretRect * Get the current caret rect. Only call this when GetCaretFrame returns diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e355927b553a..e469b661f488 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -973,6 +973,13 @@ nsIFrame::DisplayCaret(nsDisplayListBuilder* aBuilder, new (aBuilder) nsDisplayCaret(this, aBuilder->GetCaret())); } +nscolor +nsIFrame::GetCaretColorAt(PRInt32 aOffset) +{ + // Use text color. + return GetStyleColor()->mColor; +} + PRBool nsIFrame::HasBorder() const { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 565627994472..81a99cbe6ba6 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -977,6 +977,13 @@ public: const nsRect& aDirtyRect, nsDisplayList* aList); + /** + * Get the preferred caret color at the offset. + * + * @param aOffset is offset of the content. + */ + virtual nscolor GetCaretColorAt(PRInt32 aOffset); + PRBool IsThemed(nsTransparencyMode* aTransparencyMode = nsnull) { return IsThemed(GetStyleDisplay(), aTransparencyMode); } diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 757f5b68d87a..8bbe7b9a54b7 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -307,6 +307,8 @@ public: SelectionDetails* aDetails, SelectionType aSelectionType); + virtual nscolor GetCaretColorAt(PRInt32 aOffset); + PRInt16 GetSelectionStatus(PRInt16* aSelectionFlags); #ifdef DEBUG diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 70aad785e472..72af465d0119 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -4717,6 +4717,48 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, return PR_TRUE; } +nscolor +nsTextFrame::GetCaretColorAt(PRInt32 aOffset) +{ + NS_PRECONDITION(aOffset >= 0, "aOffset must be positive"); + + gfxSkipCharsIterator iter = EnsureTextRun(); + PropertyProvider provider(this, iter); + PRInt32 contentOffset = provider.GetStart().GetOriginalOffset(); + PRInt32 contentLength = provider.GetOriginalLength(); + NS_PRECONDITION(aOffset >= contentOffset && + aOffset <= contentOffset + contentLength, + "aOffset must be in the frame's range"); + PRInt32 offsetInFrame = aOffset - contentOffset; + if (offsetInFrame < 0 || offsetInFrame >= contentLength) { + return nsFrame::GetCaretColorAt(aOffset); + } + + nsTextPaintStyle textPaintStyle(this); + SelectionDetails* details = GetSelectionDetails(); + SelectionDetails* sdptr = details; + nscolor result = nsFrame::GetCaretColorAt(aOffset); + SelectionType type = 0; + while (sdptr) { + PRInt32 start = NS_MAX(0, sdptr->mStart - contentOffset); + PRInt32 end = NS_MIN(contentLength, sdptr->mEnd - contentOffset); + if (start <= offsetInFrame && offsetInFrame < end && + (type == 0 || sdptr->mType < type)) { + nscolor foreground, background; + if (GetSelectionTextColors(sdptr->mType, textPaintStyle, + sdptr->mTextRangeStyle, + &foreground, &background)) { + result = foreground; + type = sdptr->mType; + } + } + sdptr = sdptr->mNext; + } + + DestroySelectionDetails(details); + return result; +} + static PRUint32 ComputeTransformedLength(PropertyProvider& aProvider) { From ff90f89d15ac6bd3f5cf6a6d1aa8e951ead35171 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Wed, 31 Mar 2010 20:16:44 -0700 Subject: [PATCH 09/69] hg rm a test that was removed from the manifest. Making a working test is covered by bug 414740's in-testsuite? flag. --- layout/generic/crashtests/414740.html | 31 --------------------------- 1 file changed, 31 deletions(-) delete mode 100644 layout/generic/crashtests/414740.html diff --git a/layout/generic/crashtests/414740.html b/layout/generic/crashtests/414740.html deleted file mode 100644 index ef557cc8829f..000000000000 --- a/layout/generic/crashtests/414740.html +++ /dev/null @@ -1,31 +0,0 @@ - -Testcase bug 344164 - Hang when moving right in caret browsing with this testcase - - - -text - - From fdb1e0190db4a997507fa5a2ed23350cc5925860 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Wed, 31 Mar 2010 20:17:35 -0700 Subject: [PATCH 10/69] Add tests to manifest. (Homeless tests identified by script in bug 551617.) --- content/xbl/crashtests/crashtests.list | 1 + gfx/thebes/crashtests/crashtests.list | 2 ++ layout/base/crashtests/crashtests.list | 1 + layout/generic/crashtests/crashtests.list | 1 + 4 files changed, 5 insertions(+) diff --git a/content/xbl/crashtests/crashtests.list b/content/xbl/crashtests/crashtests.list index 69894e24d02e..1a63e3d16b7c 100644 --- a/content/xbl/crashtests/crashtests.list +++ b/content/xbl/crashtests/crashtests.list @@ -24,6 +24,7 @@ load 415192-1.xul load 420233-1.xhtml load 421997-1.xhtml load 432813-1.xhtml +load 454820-1.html load 460665-1.xhtml load 464863-1.xhtml load 472260-1.xhtml diff --git a/gfx/thebes/crashtests/crashtests.list b/gfx/thebes/crashtests/crashtests.list index f98672428aca..6cee8f5f0447 100644 --- a/gfx/thebes/crashtests/crashtests.list +++ b/gfx/thebes/crashtests/crashtests.list @@ -9,6 +9,8 @@ load 333861-1.html load 334735-1.html load 345576-1.html load 345629-1.html +load 348462-1.html +load 348462-2.html load 369688-1.html load 369947-1.html load 372094-1.xhtml diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index cd45ba3b1e0e..77e3ab246518 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -73,6 +73,7 @@ load 325967-1.html load 325984-1.xhtml load 325984-2.html load 328944-1.xul +load 329900-1.html load 330015-1.html load 331204-1.html load 331679-1.xhtml diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index d88b9a687936..c0f806a1eb3b 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -201,6 +201,7 @@ load 426272-1.html load 428263-1.html load 429969-1.html load 429981-1.html +load 430332-1.html load 430344-1.html load 430352-1.html load 430744-1.html From af8fc2abfd3332af9f7219c9c239e2aeb2c2fa4b Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 1 Apr 2010 00:38:51 -0400 Subject: [PATCH 11/69] Bug 533560 - Volume control does not control zoom level [r=dougt] --- widget/src/gtk2/nsWindow.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 1c5ea4b7e6fc..aa3efded7197 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -39,6 +39,7 @@ * ***** END LICENSE BLOCK ***** */ #ifdef MOZ_PLATFORM_MAEMO +// needed to include hildon parts in gtk.h #define MAEMO_CHANGES #endif @@ -62,6 +63,7 @@ #include #ifdef MOZ_X11 #include +#include #ifdef AIX #include @@ -4258,6 +4260,18 @@ nsWindow::Create(nsIWidget *aParent, g_signal_connect_after(default_settings, "notify::gtk-font-name", G_CALLBACK(theme_changed_cb), this); + +#ifdef MOZ_PLATFORM_MAEMO + if (mWindowType == eWindowType_toplevel) { + GdkWindow *gdkwin = mShell->window; + + // Tell maemo-status-volume daemon to ungrab keys + gulong volume_set = 1; + GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE); + gdk_property_change(gdkwin, keys, gdk_x11_xatom_to_atom(XA_INTEGER), + 32, GDK_PROP_MODE_REPLACE, (const guchar *) &volume_set, 1); + } +#endif } if (mContainer) { From ff366773685143f62148022523800bfd83f8d083 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 1 Apr 2010 20:32:13 +1300 Subject: [PATCH 12/69] Bug 550029. Don't try to run treeview script if the document global object has gone away. r=smaug --- layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp index 78f8dec6c3cf..a67fcc551cbc 100644 --- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -2813,7 +2813,9 @@ nsTreeBodyFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsresult rv = nsLeafBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); NS_ENSURE_SUCCESS(rv, rv); - if (!mView) + // Bail out now if there's no view or we can't run script because the + // document is a zombie + if (!mView || !GetContent()->GetCurrentDoc()->GetScriptGlobalObject()) return NS_OK; return aLists.Content()->AppendNewToTop(new (aBuilder) From 33785c5d2e6d9f5d943161c32e415118fb5d2dfb Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 29 Mar 2010 14:01:18 +0300 Subject: [PATCH 13/69] Bug 501082 - Use a more efficient data layout for the named character tables in the HTML5 parser. Based on patch by dbaron. r=bnewman. --HG-- extra : rebase_source : abe4519a3eeacdc2f89343b26c7b961f62dfb435 --- parser/html/nsHtml5NamedCharacters.cpp | 74 +- parser/html/nsHtml5NamedCharacters.h | 3 + parser/html/nsHtml5NamedCharactersInclude.h | 4282 ++++++++++--------- 3 files changed, 2200 insertions(+), 2159 deletions(-) diff --git a/parser/html/nsHtml5NamedCharacters.cpp b/parser/html/nsHtml5NamedCharacters.cpp index 13172d87276b..275a532acc9e 100644 --- a/parser/html/nsHtml5NamedCharacters.cpp +++ b/parser/html/nsHtml5NamedCharacters.cpp @@ -2,14 +2,16 @@ #include "prtypes.h" #include "jArray.h" #include "nscore.h" +#include "nsDebug.h" +#include "prlog.h" +#include "nsMemory.h" #include "nsHtml5NamedCharacters.h" jArray,PRInt32> nsHtml5NamedCharacters::NAMES; const PRUnichar nsHtml5NamedCharacters::VALUES[][2] = { - -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ { VALUE }, #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE @@ -349,31 +351,69 @@ const PRInt32* const nsHtml5NamedCharacters::HILO_ACCEL[] = { HILO_ACCEL_122 }; +/** + * To avoid having lots of pointers in the |charData| array, below, + * which would cause us to have to do lots of relocations at library + * load time, store all the string data for the names in one big array. + * Then use tricks with enums to help us build an array that contains + * the positions of each within the big arrays. + */ -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ -static PRInt8 const NAME_##N[] = { CHARS }; +static const PRInt8 ALL_NAMES[] = { +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +CHARS , #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE +}; -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ -static PRUnichar const VALUE_##N[] = { VALUE }; +enum NamePositions { + DUMMY_INITIAL_NAME_POSITION = 0, +/* enums don't take up space, so generate _START and _END */ +#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +NAME_##N##_DUMMY, /* automatically one higher than previous */ \ +NAME_##N##_START = NAME_##N##_DUMMY - 1, \ +NAME_##N##_END = NAME_##N##_START + LEN + FLAG, #include "nsHtml5NamedCharactersInclude.h" #undef NAMED_CHARACTER_REFERENCE + DUMMY_FINAL_NAME_VALUE +}; -// XXX bug 501082: for some reason, msvc takes forever to optimize this function -#ifdef _MSC_VER -#pragma optimize("", off) +#define NAMED_CHARACTERS_COUNT 2138 + +/* check that the start positions will fit in 16 bits */ +PR_STATIC_ASSERT(NS_ARRAY_LENGTH(ALL_NAMES) < 0x10000); + +struct NamedCharacterData { + PRUint16 nameStart; + PRUint16 nameLen; +#ifdef DEBUG + PRInt32 n; #endif +}; + +static const NamedCharacterData charData[NAMED_CHARACTERS_COUNT] = { +#ifdef DEBUG + #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +{ NAME_##N##_START, LEN, N }, +#else + #define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \ +{ NAME_##N##_START, LEN, }, +#endif +#include "nsHtml5NamedCharactersInclude.h" +#undef NAMED_CHARACTER_REFERENCE +}; void nsHtml5NamedCharacters::initializeStatics() { - NAMES = jArray,PRInt32>(2138); - -#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, VALUE) \ - NAMES[N] = jArray((PRInt8*)NAME_##N, LEN); -#include "nsHtml5NamedCharactersInclude.h" -#undef NAMED_CHARACTER_REFERENCE + NAMES = jArray,PRInt32>(NAMED_CHARACTERS_COUNT); + PRInt8* allNames = const_cast(ALL_NAMES); + for (PRInt32 i = 0; i < NAMED_CHARACTERS_COUNT; ++i) { + const NamedCharacterData &data = charData[i]; + NS_ABORT_IF_FALSE(data.n == i, + "index error in nsHtml5NamedCharactersInclude.h"); + NAMES[i] = jArray(allNames + data.nameStart, data.nameLen); + } WINDOWS_1252 = new PRUnichar*[32]; for (PRInt32 i = 0; i < 32; ++i) { @@ -381,10 +421,6 @@ nsHtml5NamedCharacters::initializeStatics() } } -#ifdef _MSC_VER -#pragma optimize("", on) -#endif - void nsHtml5NamedCharacters::releaseStatics() { diff --git a/parser/html/nsHtml5NamedCharacters.h b/parser/html/nsHtml5NamedCharacters.h index 8506cef3fbf2..02430a12c44b 100644 --- a/parser/html/nsHtml5NamedCharacters.h +++ b/parser/html/nsHtml5NamedCharacters.h @@ -4,6 +4,9 @@ #include "prtypes.h" #include "jArray.h" #include "nscore.h" +#include "nsDebug.h" +#include "prlog.h" +#include "nsMemory.h" class nsHtml5NamedCharacters { diff --git a/parser/html/nsHtml5NamedCharactersInclude.h b/parser/html/nsHtml5NamedCharactersInclude.h index dd849cbf5e41..b09250dded5d 100644 --- a/parser/html/nsHtml5NamedCharactersInclude.h +++ b/parser/html/nsHtml5NamedCharactersInclude.h @@ -7,9 +7,11 @@ * * 1. a unique integer N identifying the Nth [0,1,..] macro expansion in this file, * 2. a comma-separated sequence of characters comprising the character name, - * without the first two letters. See Tokenizer.java. + * without the first two letters or 0 if the sequence would be empty. + * See Tokenizer.java. * 3. the length of this sequence of characters, - * 4. a comma-separated sequence of PRUnichar literals (high to low) corresponding + * 4. placeholder flag (0 if argument #is not a placeholder and 1 if it is), + * 5. a comma-separated sequence of PRUnichar literals (high to low) corresponding * to the code-point of the named character. * * The macro expansion doesn't have to refer to all or any of these parameters, @@ -21,2143 +23,2143 @@ // split the sequence into multiple macro arguments. #define _ , -NAMED_CHARACTER_REFERENCE(0, /* A E */ 'l' _ 'i' _ 'g', 3, 0x00c6 _ 0) -NAMED_CHARACTER_REFERENCE(1, /* A E */ 'l' _ 'i' _ 'g' _ ';', 4, 0x00c6 _ 0) -NAMED_CHARACTER_REFERENCE(2, /* A M */ 'P', 1, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(3, /* A M */ 'P' _ ';', 2, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(4, /* A a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00c1 _ 0) -NAMED_CHARACTER_REFERENCE(5, /* A a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00c1 _ 0) -NAMED_CHARACTER_REFERENCE(6, /* A b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x0102 _ 0) -NAMED_CHARACTER_REFERENCE(7, /* A c */ 'i' _ 'r' _ 'c', 3, 0x00c2 _ 0) -NAMED_CHARACTER_REFERENCE(8, /* A c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00c2 _ 0) -NAMED_CHARACTER_REFERENCE(9, /* A c */ 'y' _ ';', 2, 0x0410 _ 0) -NAMED_CHARACTER_REFERENCE(10, /* A f */ 'r' _ ';', 2, 0xd835 _ 0xdd04) -NAMED_CHARACTER_REFERENCE(11, /* A g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00c0 _ 0) -NAMED_CHARACTER_REFERENCE(12, /* A g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00c0 _ 0) -NAMED_CHARACTER_REFERENCE(13, /* A l */ 'p' _ 'h' _ 'a' _ ';', 4, 0x0391 _ 0) -NAMED_CHARACTER_REFERENCE(14, /* A m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0100 _ 0) -NAMED_CHARACTER_REFERENCE(15, /* A n */ 'd' _ ';', 2, 0x2a53 _ 0) -NAMED_CHARACTER_REFERENCE(16, /* A o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0104 _ 0) -NAMED_CHARACTER_REFERENCE(17, /* A o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd38) -NAMED_CHARACTER_REFERENCE(18, /* A p */ 'p' _ 'l' _ 'y' _ 'F' _ 'u' _ 'n' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, 0x2061 _ 0) -NAMED_CHARACTER_REFERENCE(19, /* A r */ 'i' _ 'n' _ 'g', 3, 0x00c5 _ 0) -NAMED_CHARACTER_REFERENCE(20, /* A r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x00c5 _ 0) -NAMED_CHARACTER_REFERENCE(21, /* A s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdc9c) -NAMED_CHARACTER_REFERENCE(22, /* A s */ 's' _ 'i' _ 'g' _ 'n' _ ';', 5, 0x2254 _ 0) -NAMED_CHARACTER_REFERENCE(23, /* A t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00c3 _ 0) -NAMED_CHARACTER_REFERENCE(24, /* A t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00c3 _ 0) -NAMED_CHARACTER_REFERENCE(25, /* A u */ 'm' _ 'l', 2, 0x00c4 _ 0) -NAMED_CHARACTER_REFERENCE(26, /* A u */ 'm' _ 'l' _ ';', 3, 0x00c4 _ 0) -NAMED_CHARACTER_REFERENCE(27, /* B a */ 'c' _ 'k' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 8, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(28, /* B a */ 'r' _ 'v' _ ';', 3, 0x2ae7 _ 0) -NAMED_CHARACTER_REFERENCE(29, /* B a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0x2306 _ 0) -NAMED_CHARACTER_REFERENCE(30, /* B c */ 'y' _ ';', 2, 0x0411 _ 0) -NAMED_CHARACTER_REFERENCE(31, /* B e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0x2235 _ 0) -NAMED_CHARACTER_REFERENCE(32, /* B e */ 'r' _ 'n' _ 'o' _ 'u' _ 'l' _ 'l' _ 'i' _ 's' _ ';', 9, 0x212c _ 0) -NAMED_CHARACTER_REFERENCE(33, /* B e */ 't' _ 'a' _ ';', 3, 0x0392 _ 0) -NAMED_CHARACTER_REFERENCE(34, /* B f */ 'r' _ ';', 2, 0xd835 _ 0xdd05) -NAMED_CHARACTER_REFERENCE(35, /* B o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd39) -NAMED_CHARACTER_REFERENCE(36, /* B r */ 'e' _ 'v' _ 'e' _ ';', 4, 0x02d8 _ 0) -NAMED_CHARACTER_REFERENCE(37, /* B s */ 'c' _ 'r' _ ';', 3, 0x212c _ 0) -NAMED_CHARACTER_REFERENCE(38, /* B u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0x224e _ 0) -NAMED_CHARACTER_REFERENCE(39, /* C H */ 'c' _ 'y' _ ';', 3, 0x0427 _ 0) -NAMED_CHARACTER_REFERENCE(40, /* C O */ 'P' _ 'Y', 2, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(41, /* C O */ 'P' _ 'Y' _ ';', 3, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(42, /* C a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0106 _ 0) -NAMED_CHARACTER_REFERENCE(43, /* C a */ 'p' _ ';', 2, 0x22d2 _ 0) -NAMED_CHARACTER_REFERENCE(44, /* C a */ 'p' _ 'i' _ 't' _ 'a' _ 'l' _ 'D' _ 'i' _ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 19, 0x2145 _ 0) -NAMED_CHARACTER_REFERENCE(45, /* C a */ 'y' _ 'l' _ 'e' _ 'y' _ 's' _ ';', 6, 0x212d _ 0) -NAMED_CHARACTER_REFERENCE(46, /* C c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010c _ 0) -NAMED_CHARACTER_REFERENCE(47, /* C c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0x00c7 _ 0) -NAMED_CHARACTER_REFERENCE(48, /* C c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x00c7 _ 0) -NAMED_CHARACTER_REFERENCE(49, /* C c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0108 _ 0) -NAMED_CHARACTER_REFERENCE(50, /* C c */ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2230 _ 0) -NAMED_CHARACTER_REFERENCE(51, /* C d */ 'o' _ 't' _ ';', 3, 0x010a _ 0) -NAMED_CHARACTER_REFERENCE(52, /* C e */ 'd' _ 'i' _ 'l' _ 'l' _ 'a' _ ';', 6, 0x00b8 _ 0) -NAMED_CHARACTER_REFERENCE(53, /* C e */ 'n' _ 't' _ 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 8, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(54, /* C f */ 'r' _ ';', 2, 0x212d _ 0) -NAMED_CHARACTER_REFERENCE(55, /* C h */ 'i' _ ';', 2, 0x03a7 _ 0) -NAMED_CHARACTER_REFERENCE(56, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0x2299 _ 0) -NAMED_CHARACTER_REFERENCE(57, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 10, 0x2296 _ 0) -NAMED_CHARACTER_REFERENCE(58, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 9, 0x2295 _ 0) -NAMED_CHARACTER_REFERENCE(59, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 10, 0x2297 _ 0) -NAMED_CHARACTER_REFERENCE(60, /* C l */ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 23, 0x2232 _ 0) -NAMED_CHARACTER_REFERENCE(61, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 20, 0x201d _ 0) -NAMED_CHARACTER_REFERENCE(62, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 14, 0x2019 _ 0) -NAMED_CHARACTER_REFERENCE(63, /* C o */ 'l' _ 'o' _ 'n' _ ';', 4, 0x2237 _ 0) -NAMED_CHARACTER_REFERENCE(64, /* C o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0x2a74 _ 0) -NAMED_CHARACTER_REFERENCE(65, /* C o */ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 8, 0x2261 _ 0) -NAMED_CHARACTER_REFERENCE(66, /* C o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222f _ 0) -NAMED_CHARACTER_REFERENCE(67, /* C o */ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 14, 0x222e _ 0) -NAMED_CHARACTER_REFERENCE(68, /* C o */ 'p' _ 'f' _ ';', 3, 0x2102 _ 0) -NAMED_CHARACTER_REFERENCE(69, /* C o */ 'p' _ 'r' _ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 8, 0x2210 _ 0) -NAMED_CHARACTER_REFERENCE(70, /* C o */ 'u' _ 'n' _ 't' _ 'e' _ 'r' _ 'C' _ 'l' _ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 30, 0x2233 _ 0) -NAMED_CHARACTER_REFERENCE(71, /* C r */ 'o' _ 's' _ 's' _ ';', 4, 0x2a2f _ 0) -NAMED_CHARACTER_REFERENCE(72, /* C s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdc9e) -NAMED_CHARACTER_REFERENCE(73, /* C u */ 'p' _ ';', 2, 0x22d3 _ 0) -NAMED_CHARACTER_REFERENCE(74, /* C u */ 'p' _ 'C' _ 'a' _ 'p' _ ';', 5, 0x224d _ 0) -NAMED_CHARACTER_REFERENCE(75, /* D D */ ';', 1, 0x2145 _ 0) -NAMED_CHARACTER_REFERENCE(76, /* D D */ 'o' _ 't' _ 'r' _ 'a' _ 'h' _ 'd' _ ';', 7, 0x2911 _ 0) -NAMED_CHARACTER_REFERENCE(77, /* D J */ 'c' _ 'y' _ ';', 3, 0x0402 _ 0) -NAMED_CHARACTER_REFERENCE(78, /* D S */ 'c' _ 'y' _ ';', 3, 0x0405 _ 0) -NAMED_CHARACTER_REFERENCE(79, /* D Z */ 'c' _ 'y' _ ';', 3, 0x040f _ 0) -NAMED_CHARACTER_REFERENCE(80, /* D a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0x2021 _ 0) -NAMED_CHARACTER_REFERENCE(81, /* D a */ 'r' _ 'r' _ ';', 3, 0x21a1 _ 0) -NAMED_CHARACTER_REFERENCE(82, /* D a */ 's' _ 'h' _ 'v' _ ';', 4, 0x2ae4 _ 0) -NAMED_CHARACTER_REFERENCE(83, /* D c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010e _ 0) -NAMED_CHARACTER_REFERENCE(84, /* D c */ 'y' _ ';', 2, 0x0414 _ 0) -NAMED_CHARACTER_REFERENCE(85, /* D e */ 'l' _ ';', 2, 0x2207 _ 0) -NAMED_CHARACTER_REFERENCE(86, /* D e */ 'l' _ 't' _ 'a' _ ';', 4, 0x0394 _ 0) -NAMED_CHARACTER_REFERENCE(87, /* D f */ 'r' _ ';', 2, 0xd835 _ 0xdd07) -NAMED_CHARACTER_REFERENCE(88, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 15, 0x00b4 _ 0) -NAMED_CHARACTER_REFERENCE(89, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 't' _ ';', 13, 0x02d9 _ 0) -NAMED_CHARACTER_REFERENCE(90, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 21, 0x02dd _ 0) -NAMED_CHARACTER_REFERENCE(91, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'G' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 15, 0x0060 _ 0) -NAMED_CHARACTER_REFERENCE(92, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 15, 0x02dc _ 0) -NAMED_CHARACTER_REFERENCE(93, /* D i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0x22c4 _ 0) -NAMED_CHARACTER_REFERENCE(94, /* D i */ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 12, 0x2146 _ 0) -NAMED_CHARACTER_REFERENCE(95, /* D o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3b) -NAMED_CHARACTER_REFERENCE(96, /* D o */ 't' _ ';', 2, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(97, /* D o */ 't' _ 'D' _ 'o' _ 't' _ ';', 5, 0x20dc _ 0) -NAMED_CHARACTER_REFERENCE(98, /* D o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0x2250 _ 0) -NAMED_CHARACTER_REFERENCE(99, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 20, 0x222f _ 0) -NAMED_CHARACTER_REFERENCE(100, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(101, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21d3 _ 0) -NAMED_CHARACTER_REFERENCE(102, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21d0 _ 0) -NAMED_CHARACTER_REFERENCE(103, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(104, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 12, 0x2ae4 _ 0) -NAMED_CHARACTER_REFERENCE(105, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x27f8 _ 0) -NAMED_CHARACTER_REFERENCE(106, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 23, 0x27fa _ 0) -NAMED_CHARACTER_REFERENCE(107, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0x27f9 _ 0) -NAMED_CHARACTER_REFERENCE(108, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(109, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 13, 0x22a8 _ 0) -NAMED_CHARACTER_REFERENCE(110, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21d1 _ 0) -NAMED_CHARACTER_REFERENCE(111, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21d5 _ 0) -NAMED_CHARACTER_REFERENCE(112, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 16, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(113, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(114, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0x2913 _ 0) -NAMED_CHARACTER_REFERENCE(115, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21f5 _ 0) -NAMED_CHARACTER_REFERENCE(116, /* D o */ 'w' _ 'n' _ 'B' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 8, 0x0311 _ 0) -NAMED_CHARACTER_REFERENCE(117, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 18, 0x2950 _ 0) -NAMED_CHARACTER_REFERENCE(118, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0x295e _ 0) -NAMED_CHARACTER_REFERENCE(119, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0x21bd _ 0) -NAMED_CHARACTER_REFERENCE(120, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0x2956 _ 0) -NAMED_CHARACTER_REFERENCE(121, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0x295f _ 0) -NAMED_CHARACTER_REFERENCE(122, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x21c1 _ 0) -NAMED_CHARACTER_REFERENCE(123, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0x2957 _ 0) -NAMED_CHARACTER_REFERENCE(124, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ ';', 6, 0x22a4 _ 0) -NAMED_CHARACTER_REFERENCE(125, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x21a7 _ 0) -NAMED_CHARACTER_REFERENCE(126, /* D o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x21d3 _ 0) -NAMED_CHARACTER_REFERENCE(127, /* D s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdc9f) -NAMED_CHARACTER_REFERENCE(128, /* D s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0110 _ 0) -NAMED_CHARACTER_REFERENCE(129, /* E N */ 'G' _ ';', 2, 0x014a _ 0) -NAMED_CHARACTER_REFERENCE(130, /* E T */ 'H', 1, 0x00d0 _ 0) -NAMED_CHARACTER_REFERENCE(131, /* E T */ 'H' _ ';', 2, 0x00d0 _ 0) -NAMED_CHARACTER_REFERENCE(132, /* E a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00c9 _ 0) -NAMED_CHARACTER_REFERENCE(133, /* E a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00c9 _ 0) -NAMED_CHARACTER_REFERENCE(134, /* E c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x011a _ 0) -NAMED_CHARACTER_REFERENCE(135, /* E c */ 'i' _ 'r' _ 'c', 3, 0x00ca _ 0) -NAMED_CHARACTER_REFERENCE(136, /* E c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ca _ 0) -NAMED_CHARACTER_REFERENCE(137, /* E c */ 'y' _ ';', 2, 0x042d _ 0) -NAMED_CHARACTER_REFERENCE(138, /* E d */ 'o' _ 't' _ ';', 3, 0x0116 _ 0) -NAMED_CHARACTER_REFERENCE(139, /* E f */ 'r' _ ';', 2, 0xd835 _ 0xdd08) -NAMED_CHARACTER_REFERENCE(140, /* E g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00c8 _ 0) -NAMED_CHARACTER_REFERENCE(141, /* E g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00c8 _ 0) -NAMED_CHARACTER_REFERENCE(142, /* E l */ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 6, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(143, /* E m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0112 _ 0) -NAMED_CHARACTER_REFERENCE(144, /* E m */ 'p' _ 't' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 15, 0x25fb _ 0) -NAMED_CHARACTER_REFERENCE(145, /* E m */ 'p' _ 't' _ 'y' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 19, 0x25ab _ 0) -NAMED_CHARACTER_REFERENCE(146, /* E o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0118 _ 0) -NAMED_CHARACTER_REFERENCE(147, /* E o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3c) -NAMED_CHARACTER_REFERENCE(148, /* E p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x0395 _ 0) -NAMED_CHARACTER_REFERENCE(149, /* E q */ 'u' _ 'a' _ 'l' _ ';', 4, 0x2a75 _ 0) -NAMED_CHARACTER_REFERENCE(150, /* E q */ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0x2242 _ 0) -NAMED_CHARACTER_REFERENCE(151, /* E q */ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 10, 0x21cc _ 0) -NAMED_CHARACTER_REFERENCE(152, /* E s */ 'c' _ 'r' _ ';', 3, 0x2130 _ 0) -NAMED_CHARACTER_REFERENCE(153, /* E s */ 'i' _ 'm' _ ';', 3, 0x2a73 _ 0) -NAMED_CHARACTER_REFERENCE(154, /* E t */ 'a' _ ';', 2, 0x0397 _ 0) -NAMED_CHARACTER_REFERENCE(155, /* E u */ 'm' _ 'l', 2, 0x00cb _ 0) -NAMED_CHARACTER_REFERENCE(156, /* E u */ 'm' _ 'l' _ ';', 3, 0x00cb _ 0) -NAMED_CHARACTER_REFERENCE(157, /* E x */ 'i' _ 's' _ 't' _ 's' _ ';', 5, 0x2203 _ 0) -NAMED_CHARACTER_REFERENCE(158, /* E x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'E' _ ';', 11, 0x2147 _ 0) -NAMED_CHARACTER_REFERENCE(159, /* F c */ 'y' _ ';', 2, 0x0424 _ 0) -NAMED_CHARACTER_REFERENCE(160, /* F f */ 'r' _ ';', 2, 0xd835 _ 0xdd09) -NAMED_CHARACTER_REFERENCE(161, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 16, 0x25fc _ 0) -NAMED_CHARACTER_REFERENCE(162, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 20, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(163, /* F o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3d) -NAMED_CHARACTER_REFERENCE(164, /* F o */ 'r' _ 'A' _ 'l' _ 'l' _ ';', 5, 0x2200 _ 0) -NAMED_CHARACTER_REFERENCE(165, /* F o */ 'u' _ 'r' _ 'i' _ 'e' _ 'r' _ 't' _ 'r' _ 'f' _ ';', 9, 0x2131 _ 0) -NAMED_CHARACTER_REFERENCE(166, /* F s */ 'c' _ 'r' _ ';', 3, 0x2131 _ 0) -NAMED_CHARACTER_REFERENCE(167, /* G J */ 'c' _ 'y' _ ';', 3, 0x0403 _ 0) -NAMED_CHARACTER_REFERENCE(168, /* G T */ 0, 0, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(169, /* G T */ ';', 1, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(170, /* G a */ 'm' _ 'm' _ 'a' _ ';', 4, 0x0393 _ 0) -NAMED_CHARACTER_REFERENCE(171, /* G a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0x03dc _ 0) -NAMED_CHARACTER_REFERENCE(172, /* G b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x011e _ 0) -NAMED_CHARACTER_REFERENCE(173, /* G c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0122 _ 0) -NAMED_CHARACTER_REFERENCE(174, /* G c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x011c _ 0) -NAMED_CHARACTER_REFERENCE(175, /* G c */ 'y' _ ';', 2, 0x0413 _ 0) -NAMED_CHARACTER_REFERENCE(176, /* G d */ 'o' _ 't' _ ';', 3, 0x0120 _ 0) -NAMED_CHARACTER_REFERENCE(177, /* G f */ 'r' _ ';', 2, 0xd835 _ 0xdd0a) -NAMED_CHARACTER_REFERENCE(178, /* G g */ ';', 1, 0x22d9 _ 0) -NAMED_CHARACTER_REFERENCE(179, /* G o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd3e) -NAMED_CHARACTER_REFERENCE(180, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0x2265 _ 0) -NAMED_CHARACTER_REFERENCE(181, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'L' _ 'e' _ 's' _ 's' _ ';', 15, 0x22db _ 0) -NAMED_CHARACTER_REFERENCE(182, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0x2267 _ 0) -NAMED_CHARACTER_REFERENCE(183, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0x2aa2 _ 0) -NAMED_CHARACTER_REFERENCE(184, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0x2277 _ 0) -NAMED_CHARACTER_REFERENCE(185, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x2a7e _ 0) -NAMED_CHARACTER_REFERENCE(186, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0x2273 _ 0) -NAMED_CHARACTER_REFERENCE(187, /* G s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca2) -NAMED_CHARACTER_REFERENCE(188, /* G t */ ';', 1, 0x226b _ 0) -NAMED_CHARACTER_REFERENCE(189, /* H A */ 'R' _ 'D' _ 'c' _ 'y' _ ';', 5, 0x042a _ 0) -NAMED_CHARACTER_REFERENCE(190, /* H a */ 'c' _ 'e' _ 'k' _ ';', 4, 0x02c7 _ 0) -NAMED_CHARACTER_REFERENCE(191, /* H a */ 't' _ ';', 2, 0x005e _ 0) -NAMED_CHARACTER_REFERENCE(192, /* H c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0124 _ 0) -NAMED_CHARACTER_REFERENCE(193, /* H f */ 'r' _ ';', 2, 0x210c _ 0) -NAMED_CHARACTER_REFERENCE(194, /* H i */ 'l' _ 'b' _ 'e' _ 'r' _ 't' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 11, 0x210b _ 0) -NAMED_CHARACTER_REFERENCE(195, /* H o */ 'p' _ 'f' _ ';', 3, 0x210d _ 0) -NAMED_CHARACTER_REFERENCE(196, /* H o */ 'r' _ 'i' _ 'z' _ 'o' _ 'n' _ 't' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 13, 0x2500 _ 0) -NAMED_CHARACTER_REFERENCE(197, /* H s */ 'c' _ 'r' _ ';', 3, 0x210b _ 0) -NAMED_CHARACTER_REFERENCE(198, /* H s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0126 _ 0) -NAMED_CHARACTER_REFERENCE(199, /* H u */ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';', 11, 0x224e _ 0) -NAMED_CHARACTER_REFERENCE(200, /* H u */ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 8, 0x224f _ 0) -NAMED_CHARACTER_REFERENCE(201, /* I E */ 'c' _ 'y' _ ';', 3, 0x0415 _ 0) -NAMED_CHARACTER_REFERENCE(202, /* I J */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0132 _ 0) -NAMED_CHARACTER_REFERENCE(203, /* I O */ 'c' _ 'y' _ ';', 3, 0x0401 _ 0) -NAMED_CHARACTER_REFERENCE(204, /* I a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00cd _ 0) -NAMED_CHARACTER_REFERENCE(205, /* I a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00cd _ 0) -NAMED_CHARACTER_REFERENCE(206, /* I c */ 'i' _ 'r' _ 'c', 3, 0x00ce _ 0) -NAMED_CHARACTER_REFERENCE(207, /* I c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ce _ 0) -NAMED_CHARACTER_REFERENCE(208, /* I c */ 'y' _ ';', 2, 0x0418 _ 0) -NAMED_CHARACTER_REFERENCE(209, /* I d */ 'o' _ 't' _ ';', 3, 0x0130 _ 0) -NAMED_CHARACTER_REFERENCE(210, /* I f */ 'r' _ ';', 2, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(211, /* I g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00cc _ 0) -NAMED_CHARACTER_REFERENCE(212, /* I g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00cc _ 0) -NAMED_CHARACTER_REFERENCE(213, /* I m */ ';', 1, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(214, /* I m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x012a _ 0) -NAMED_CHARACTER_REFERENCE(215, /* I m */ 'a' _ 'g' _ 'i' _ 'n' _ 'a' _ 'r' _ 'y' _ 'I' _ ';', 9, 0x2148 _ 0) -NAMED_CHARACTER_REFERENCE(216, /* I m */ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 6, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(217, /* I n */ 't' _ ';', 2, 0x222c _ 0) -NAMED_CHARACTER_REFERENCE(218, /* I n */ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 7, 0x222b _ 0) -NAMED_CHARACTER_REFERENCE(219, /* I n */ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 11, 0x22c2 _ 0) -NAMED_CHARACTER_REFERENCE(220, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 13, 0x2063 _ 0) -NAMED_CHARACTER_REFERENCE(221, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0x2062 _ 0) -NAMED_CHARACTER_REFERENCE(222, /* I o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x012e _ 0) -NAMED_CHARACTER_REFERENCE(223, /* I o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd40) -NAMED_CHARACTER_REFERENCE(224, /* I o */ 't' _ 'a' _ ';', 3, 0x0399 _ 0) -NAMED_CHARACTER_REFERENCE(225, /* I s */ 'c' _ 'r' _ ';', 3, 0x2110 _ 0) -NAMED_CHARACTER_REFERENCE(226, /* I t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0128 _ 0) -NAMED_CHARACTER_REFERENCE(227, /* I u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0406 _ 0) -NAMED_CHARACTER_REFERENCE(228, /* I u */ 'm' _ 'l', 2, 0x00cf _ 0) -NAMED_CHARACTER_REFERENCE(229, /* I u */ 'm' _ 'l' _ ';', 3, 0x00cf _ 0) -NAMED_CHARACTER_REFERENCE(230, /* J c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0134 _ 0) -NAMED_CHARACTER_REFERENCE(231, /* J c */ 'y' _ ';', 2, 0x0419 _ 0) -NAMED_CHARACTER_REFERENCE(232, /* J f */ 'r' _ ';', 2, 0xd835 _ 0xdd0d) -NAMED_CHARACTER_REFERENCE(233, /* J o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd41) -NAMED_CHARACTER_REFERENCE(234, /* J s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca5) -NAMED_CHARACTER_REFERENCE(235, /* J s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0x0408 _ 0) -NAMED_CHARACTER_REFERENCE(236, /* J u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0404 _ 0) -NAMED_CHARACTER_REFERENCE(237, /* K H */ 'c' _ 'y' _ ';', 3, 0x0425 _ 0) -NAMED_CHARACTER_REFERENCE(238, /* K J */ 'c' _ 'y' _ ';', 3, 0x040c _ 0) -NAMED_CHARACTER_REFERENCE(239, /* K a */ 'p' _ 'p' _ 'a' _ ';', 4, 0x039a _ 0) -NAMED_CHARACTER_REFERENCE(240, /* K c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0136 _ 0) -NAMED_CHARACTER_REFERENCE(241, /* K c */ 'y' _ ';', 2, 0x041a _ 0) -NAMED_CHARACTER_REFERENCE(242, /* K f */ 'r' _ ';', 2, 0xd835 _ 0xdd0e) -NAMED_CHARACTER_REFERENCE(243, /* K o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd42) -NAMED_CHARACTER_REFERENCE(244, /* K s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca6) -NAMED_CHARACTER_REFERENCE(245, /* L J */ 'c' _ 'y' _ ';', 3, 0x0409 _ 0) -NAMED_CHARACTER_REFERENCE(246, /* L T */ 0, 0, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(247, /* L T */ ';', 1, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(248, /* L a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0139 _ 0) -NAMED_CHARACTER_REFERENCE(249, /* L a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0x039b _ 0) -NAMED_CHARACTER_REFERENCE(250, /* L a */ 'n' _ 'g' _ ';', 3, 0x27ea _ 0) -NAMED_CHARACTER_REFERENCE(251, /* L a */ 'p' _ 'l' _ 'a' _ 'c' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 9, 0x2112 _ 0) -NAMED_CHARACTER_REFERENCE(252, /* L a */ 'r' _ 'r' _ ';', 3, 0x219e _ 0) -NAMED_CHARACTER_REFERENCE(253, /* L c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x013d _ 0) -NAMED_CHARACTER_REFERENCE(254, /* L c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x013b _ 0) -NAMED_CHARACTER_REFERENCE(255, /* L c */ 'y' _ ';', 2, 0x041b _ 0) -NAMED_CHARACTER_REFERENCE(256, /* L e */ 'f' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 15, 0x27e8 _ 0) -NAMED_CHARACTER_REFERENCE(257, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(258, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0x21e4 _ 0) -NAMED_CHARACTER_REFERENCE(259, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21c6 _ 0) -NAMED_CHARACTER_REFERENCE(260, /* L e */ 'f' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 10, 0x2308 _ 0) -NAMED_CHARACTER_REFERENCE(261, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0x27e6 _ 0) -NAMED_CHARACTER_REFERENCE(262, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0x2961 _ 0) -NAMED_CHARACTER_REFERENCE(263, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0x21c3 _ 0) -NAMED_CHARACTER_REFERENCE(264, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0x2959 _ 0) -NAMED_CHARACTER_REFERENCE(265, /* L e */ 'f' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 8, 0x230a _ 0) -NAMED_CHARACTER_REFERENCE(266, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2194 _ 0) -NAMED_CHARACTER_REFERENCE(267, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x294e _ 0) -NAMED_CHARACTER_REFERENCE(268, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 6, 0x22a3 _ 0) -NAMED_CHARACTER_REFERENCE(269, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x21a4 _ 0) -NAMED_CHARACTER_REFERENCE(270, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0x295a _ 0) -NAMED_CHARACTER_REFERENCE(271, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 11, 0x22b2 _ 0) -NAMED_CHARACTER_REFERENCE(272, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 14, 0x29cf _ 0) -NAMED_CHARACTER_REFERENCE(273, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x22b4 _ 0) -NAMED_CHARACTER_REFERENCE(274, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0x2951 _ 0) -NAMED_CHARACTER_REFERENCE(275, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x2960 _ 0) -NAMED_CHARACTER_REFERENCE(276, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 11, 0x21bf _ 0) -NAMED_CHARACTER_REFERENCE(277, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 14, 0x2958 _ 0) -NAMED_CHARACTER_REFERENCE(278, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 9, 0x21bc _ 0) -NAMED_CHARACTER_REFERENCE(279, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 12, 0x2952 _ 0) -NAMED_CHARACTER_REFERENCE(280, /* L e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x21d0 _ 0) -NAMED_CHARACTER_REFERENCE(281, /* L e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(282, /* L e */ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 15, 0x22da _ 0) -NAMED_CHARACTER_REFERENCE(283, /* L e */ 's' _ 's' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2266 _ 0) -NAMED_CHARACTER_REFERENCE(284, /* L e */ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 10, 0x2276 _ 0) -NAMED_CHARACTER_REFERENCE(285, /* L e */ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 7, 0x2aa1 _ 0) -NAMED_CHARACTER_REFERENCE(286, /* L e */ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0x2a7d _ 0) -NAMED_CHARACTER_REFERENCE(287, /* L e */ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 8, 0x2272 _ 0) -NAMED_CHARACTER_REFERENCE(288, /* L f */ 'r' _ ';', 2, 0xd835 _ 0xdd0f) -NAMED_CHARACTER_REFERENCE(289, /* L l */ ';', 1, 0x22d8 _ 0) -NAMED_CHARACTER_REFERENCE(290, /* L l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21da _ 0) -NAMED_CHARACTER_REFERENCE(291, /* L m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0x013f _ 0) -NAMED_CHARACTER_REFERENCE(292, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x27f5 _ 0) -NAMED_CHARACTER_REFERENCE(293, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x27f7 _ 0) -NAMED_CHARACTER_REFERENCE(294, /* L o */ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x27f6 _ 0) -NAMED_CHARACTER_REFERENCE(295, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x27f8 _ 0) -NAMED_CHARACTER_REFERENCE(296, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x27fa _ 0) -NAMED_CHARACTER_REFERENCE(297, /* L o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x27f9 _ 0) -NAMED_CHARACTER_REFERENCE(298, /* L o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd43) -NAMED_CHARACTER_REFERENCE(299, /* L o */ 'w' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2199 _ 0) -NAMED_CHARACTER_REFERENCE(300, /* L o */ 'w' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x2198 _ 0) -NAMED_CHARACTER_REFERENCE(301, /* L s */ 'c' _ 'r' _ ';', 3, 0x2112 _ 0) -NAMED_CHARACTER_REFERENCE(302, /* L s */ 'h' _ ';', 2, 0x21b0 _ 0) -NAMED_CHARACTER_REFERENCE(303, /* L s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0141 _ 0) -NAMED_CHARACTER_REFERENCE(304, /* L t */ ';', 1, 0x226a _ 0) -NAMED_CHARACTER_REFERENCE(305, /* M a */ 'p' _ ';', 2, 0x2905 _ 0) -NAMED_CHARACTER_REFERENCE(306, /* M c */ 'y' _ ';', 2, 0x041c _ 0) -NAMED_CHARACTER_REFERENCE(307, /* M e */ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 10, 0x205f _ 0) -NAMED_CHARACTER_REFERENCE(308, /* M e */ 'l' _ 'l' _ 'i' _ 'n' _ 't' _ 'r' _ 'f' _ ';', 8, 0x2133 _ 0) -NAMED_CHARACTER_REFERENCE(309, /* M f */ 'r' _ ';', 2, 0xd835 _ 0xdd10) -NAMED_CHARACTER_REFERENCE(310, /* M i */ 'n' _ 'u' _ 's' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0x2213 _ 0) -NAMED_CHARACTER_REFERENCE(311, /* M o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd44) -NAMED_CHARACTER_REFERENCE(312, /* M s */ 'c' _ 'r' _ ';', 3, 0x2133 _ 0) -NAMED_CHARACTER_REFERENCE(313, /* M u */ ';', 1, 0x039c _ 0) -NAMED_CHARACTER_REFERENCE(314, /* N J */ 'c' _ 'y' _ ';', 3, 0x040a _ 0) -NAMED_CHARACTER_REFERENCE(315, /* N a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0143 _ 0) -NAMED_CHARACTER_REFERENCE(316, /* N c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0147 _ 0) -NAMED_CHARACTER_REFERENCE(317, /* N c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0145 _ 0) -NAMED_CHARACTER_REFERENCE(318, /* N c */ 'y' _ ';', 2, 0x041d _ 0) -NAMED_CHARACTER_REFERENCE(319, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'M' _ 'e' _ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 18, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(320, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 17, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(321, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 16, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(322, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'V' _ 'e' _ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 20, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(323, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 19, 0x226b _ 0) -NAMED_CHARACTER_REFERENCE(324, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0x226a _ 0) -NAMED_CHARACTER_REFERENCE(325, /* N e */ 'w' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 6, 0x000a _ 0) -NAMED_CHARACTER_REFERENCE(326, /* N f */ 'r' _ ';', 2, 0xd835 _ 0xdd11) -NAMED_CHARACTER_REFERENCE(327, /* N o */ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ ';', 6, 0x2060 _ 0) -NAMED_CHARACTER_REFERENCE(328, /* N o */ 'n' _ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ 'i' _ 'n' _ 'g' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 15, 0x00a0 _ 0) -NAMED_CHARACTER_REFERENCE(329, /* N o */ 'p' _ 'f' _ ';', 3, 0x2115 _ 0) -NAMED_CHARACTER_REFERENCE(330, /* N o */ 't' _ ';', 2, 0x2aec _ 0) -NAMED_CHARACTER_REFERENCE(331, /* N o */ 't' _ 'C' _ 'o' _ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 11, 0x2262 _ 0) -NAMED_CHARACTER_REFERENCE(332, /* N o */ 't' _ 'C' _ 'u' _ 'p' _ 'C' _ 'a' _ 'p' _ ';', 8, 0x226d _ 0) -NAMED_CHARACTER_REFERENCE(333, /* N o */ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 19, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(334, /* N o */ 't' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0x2209 _ 0) -NAMED_CHARACTER_REFERENCE(335, /* N o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0x2260 _ 0) -NAMED_CHARACTER_REFERENCE(336, /* N o */ 't' _ 'E' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0x2204 _ 0) -NAMED_CHARACTER_REFERENCE(337, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 9, 0x226f _ 0) -NAMED_CHARACTER_REFERENCE(338, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 14, 0x2271 _ 0) -NAMED_CHARACTER_REFERENCE(339, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0x2279 _ 0) -NAMED_CHARACTER_REFERENCE(340, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 14, 0x2275 _ 0) -NAMED_CHARACTER_REFERENCE(341, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 14, 0x22ea _ 0) -NAMED_CHARACTER_REFERENCE(342, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0x22ec _ 0) -NAMED_CHARACTER_REFERENCE(343, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ ';', 6, 0x226e _ 0) -NAMED_CHARACTER_REFERENCE(344, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0x2270 _ 0) -NAMED_CHARACTER_REFERENCE(345, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0x2278 _ 0) -NAMED_CHARACTER_REFERENCE(346, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0x2274 _ 0) -NAMED_CHARACTER_REFERENCE(347, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 10, 0x2280 _ 0) -NAMED_CHARACTER_REFERENCE(348, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0x22e0 _ 0) -NAMED_CHARACTER_REFERENCE(349, /* N o */ 't' _ 'R' _ 'e' _ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 16, 0x220c _ 0) -NAMED_CHARACTER_REFERENCE(350, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 15, 0x22eb _ 0) -NAMED_CHARACTER_REFERENCE(351, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0x22ed _ 0) -NAMED_CHARACTER_REFERENCE(352, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0x22e2 _ 0) -NAMED_CHARACTER_REFERENCE(353, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 21, 0x22e3 _ 0) -NAMED_CHARACTER_REFERENCE(354, /* N o */ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0x2288 _ 0) -NAMED_CHARACTER_REFERENCE(355, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 10, 0x2281 _ 0) -NAMED_CHARACTER_REFERENCE(356, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0x22e1 _ 0) -NAMED_CHARACTER_REFERENCE(357, /* N o */ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0x2289 _ 0) -NAMED_CHARACTER_REFERENCE(358, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0x2241 _ 0) -NAMED_CHARACTER_REFERENCE(359, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2244 _ 0) -NAMED_CHARACTER_REFERENCE(360, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x2247 _ 0) -NAMED_CHARACTER_REFERENCE(361, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x2249 _ 0) -NAMED_CHARACTER_REFERENCE(362, /* N o */ 't' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 13, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(363, /* N s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdca9) -NAMED_CHARACTER_REFERENCE(364, /* N t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00d1 _ 0) -NAMED_CHARACTER_REFERENCE(365, /* N t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00d1 _ 0) -NAMED_CHARACTER_REFERENCE(366, /* N u */ ';', 1, 0x039d _ 0) -NAMED_CHARACTER_REFERENCE(367, /* O E */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0152 _ 0) -NAMED_CHARACTER_REFERENCE(368, /* O a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00d3 _ 0) -NAMED_CHARACTER_REFERENCE(369, /* O a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00d3 _ 0) -NAMED_CHARACTER_REFERENCE(370, /* O c */ 'i' _ 'r' _ 'c', 3, 0x00d4 _ 0) -NAMED_CHARACTER_REFERENCE(371, /* O c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00d4 _ 0) -NAMED_CHARACTER_REFERENCE(372, /* O c */ 'y' _ ';', 2, 0x041e _ 0) -NAMED_CHARACTER_REFERENCE(373, /* O d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0150 _ 0) -NAMED_CHARACTER_REFERENCE(374, /* O f */ 'r' _ ';', 2, 0xd835 _ 0xdd12) -NAMED_CHARACTER_REFERENCE(375, /* O g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00d2 _ 0) -NAMED_CHARACTER_REFERENCE(376, /* O g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00d2 _ 0) -NAMED_CHARACTER_REFERENCE(377, /* O m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x014c _ 0) -NAMED_CHARACTER_REFERENCE(378, /* O m */ 'e' _ 'g' _ 'a' _ ';', 4, 0x03a9 _ 0) -NAMED_CHARACTER_REFERENCE(379, /* O m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0x039f _ 0) -NAMED_CHARACTER_REFERENCE(380, /* O o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd46) -NAMED_CHARACTER_REFERENCE(381, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 19, 0x201c _ 0) -NAMED_CHARACTER_REFERENCE(382, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 13, 0x2018 _ 0) -NAMED_CHARACTER_REFERENCE(383, /* O r */ ';', 1, 0x2a54 _ 0) -NAMED_CHARACTER_REFERENCE(384, /* O s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcaa) -NAMED_CHARACTER_REFERENCE(385, /* O s */ 'l' _ 'a' _ 's' _ 'h', 4, 0x00d8 _ 0) -NAMED_CHARACTER_REFERENCE(386, /* O s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0x00d8 _ 0) -NAMED_CHARACTER_REFERENCE(387, /* O t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00d5 _ 0) -NAMED_CHARACTER_REFERENCE(388, /* O t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00d5 _ 0) -NAMED_CHARACTER_REFERENCE(389, /* O t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x2a37 _ 0) -NAMED_CHARACTER_REFERENCE(390, /* O u */ 'm' _ 'l', 2, 0x00d6 _ 0) -NAMED_CHARACTER_REFERENCE(391, /* O u */ 'm' _ 'l' _ ';', 3, 0x00d6 _ 0) -NAMED_CHARACTER_REFERENCE(392, /* O v */ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 6, 0x203e _ 0) -NAMED_CHARACTER_REFERENCE(393, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 8, 0x23de _ 0) -NAMED_CHARACTER_REFERENCE(394, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 10, 0x23b4 _ 0) -NAMED_CHARACTER_REFERENCE(395, /* O v */ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 14, 0x23dc _ 0) -NAMED_CHARACTER_REFERENCE(396, /* P a */ 'r' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 7, 0x2202 _ 0) -NAMED_CHARACTER_REFERENCE(397, /* P c */ 'y' _ ';', 2, 0x041f _ 0) -NAMED_CHARACTER_REFERENCE(398, /* P f */ 'r' _ ';', 2, 0xd835 _ 0xdd13) -NAMED_CHARACTER_REFERENCE(399, /* P h */ 'i' _ ';', 2, 0x03a6 _ 0) -NAMED_CHARACTER_REFERENCE(400, /* P i */ ';', 1, 0x03a0 _ 0) -NAMED_CHARACTER_REFERENCE(401, /* P l */ 'u' _ 's' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 8, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(402, /* P o */ 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ 'p' _ 'l' _ 'a' _ 'n' _ 'e' _ ';', 12, 0x210c _ 0) -NAMED_CHARACTER_REFERENCE(403, /* P o */ 'p' _ 'f' _ ';', 3, 0x2119 _ 0) -NAMED_CHARACTER_REFERENCE(404, /* P r */ ';', 1, 0x2abb _ 0) -NAMED_CHARACTER_REFERENCE(405, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 7, 0x227a _ 0) -NAMED_CHARACTER_REFERENCE(406, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2aaf _ 0) -NAMED_CHARACTER_REFERENCE(407, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0x227c _ 0) -NAMED_CHARACTER_REFERENCE(408, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x227e _ 0) -NAMED_CHARACTER_REFERENCE(409, /* P r */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2033 _ 0) -NAMED_CHARACTER_REFERENCE(410, /* P r */ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 6, 0x220f _ 0) -NAMED_CHARACTER_REFERENCE(411, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 9, 0x2237 _ 0) -NAMED_CHARACTER_REFERENCE(412, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ ';', 11, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(413, /* P s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcab) -NAMED_CHARACTER_REFERENCE(414, /* P s */ 'i' _ ';', 2, 0x03a8 _ 0) -NAMED_CHARACTER_REFERENCE(415, /* Q U */ 'O' _ 'T', 2, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(416, /* Q U */ 'O' _ 'T' _ ';', 3, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(417, /* Q f */ 'r' _ ';', 2, 0xd835 _ 0xdd14) -NAMED_CHARACTER_REFERENCE(418, /* Q o */ 'p' _ 'f' _ ';', 3, 0x211a _ 0) -NAMED_CHARACTER_REFERENCE(419, /* Q s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcac) -NAMED_CHARACTER_REFERENCE(420, /* R B */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2910 _ 0) -NAMED_CHARACTER_REFERENCE(421, /* R E */ 'G', 1, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(422, /* R E */ 'G' _ ';', 2, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(423, /* R a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0154 _ 0) -NAMED_CHARACTER_REFERENCE(424, /* R a */ 'n' _ 'g' _ ';', 3, 0x27eb _ 0) -NAMED_CHARACTER_REFERENCE(425, /* R a */ 'r' _ 'r' _ ';', 3, 0x21a0 _ 0) -NAMED_CHARACTER_REFERENCE(426, /* R a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0x2916 _ 0) -NAMED_CHARACTER_REFERENCE(427, /* R c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0158 _ 0) -NAMED_CHARACTER_REFERENCE(428, /* R c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0156 _ 0) -NAMED_CHARACTER_REFERENCE(429, /* R c */ 'y' _ ';', 2, 0x0420 _ 0) -NAMED_CHARACTER_REFERENCE(430, /* R e */ ';', 1, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(431, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 13, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(432, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 17, 0x21cb _ 0) -NAMED_CHARACTER_REFERENCE(433, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'U' _ 'p' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 19, 0x296f _ 0) -NAMED_CHARACTER_REFERENCE(434, /* R f */ 'r' _ ';', 2, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(435, /* R h */ 'o' _ ';', 2, 0x03a1 _ 0) -NAMED_CHARACTER_REFERENCE(436, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0x27e9 _ 0) -NAMED_CHARACTER_REFERENCE(437, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(438, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 12, 0x21e5 _ 0) -NAMED_CHARACTER_REFERENCE(439, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21c4 _ 0) -NAMED_CHARACTER_REFERENCE(440, /* R i */ 'g' _ 'h' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 11, 0x2309 _ 0) -NAMED_CHARACTER_REFERENCE(441, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 17, 0x27e7 _ 0) -NAMED_CHARACTER_REFERENCE(442, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0x295d _ 0) -NAMED_CHARACTER_REFERENCE(443, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0x21c2 _ 0) -NAMED_CHARACTER_REFERENCE(444, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0x2955 _ 0) -NAMED_CHARACTER_REFERENCE(445, /* R i */ 'g' _ 'h' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 9, 0x230b _ 0) -NAMED_CHARACTER_REFERENCE(446, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 7, 0x22a2 _ 0) -NAMED_CHARACTER_REFERENCE(447, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21a6 _ 0) -NAMED_CHARACTER_REFERENCE(448, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0x295b _ 0) -NAMED_CHARACTER_REFERENCE(449, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0x22b3 _ 0) -NAMED_CHARACTER_REFERENCE(450, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 15, 0x29d0 _ 0) -NAMED_CHARACTER_REFERENCE(451, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0x22b5 _ 0) -NAMED_CHARACTER_REFERENCE(452, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0x294f _ 0) -NAMED_CHARACTER_REFERENCE(453, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0x295c _ 0) -NAMED_CHARACTER_REFERENCE(454, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0x21be _ 0) -NAMED_CHARACTER_REFERENCE(455, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 15, 0x2954 _ 0) -NAMED_CHARACTER_REFERENCE(456, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 10, 0x21c0 _ 0) -NAMED_CHARACTER_REFERENCE(457, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 13, 0x2953 _ 0) -NAMED_CHARACTER_REFERENCE(458, /* R i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(459, /* R o */ 'p' _ 'f' _ ';', 3, 0x211d _ 0) -NAMED_CHARACTER_REFERENCE(460, /* R o */ 'u' _ 'n' _ 'd' _ 'I' _ 'm' _ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 11, 0x2970 _ 0) -NAMED_CHARACTER_REFERENCE(461, /* R r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x21db _ 0) -NAMED_CHARACTER_REFERENCE(462, /* R s */ 'c' _ 'r' _ ';', 3, 0x211b _ 0) -NAMED_CHARACTER_REFERENCE(463, /* R s */ 'h' _ ';', 2, 0x21b1 _ 0) -NAMED_CHARACTER_REFERENCE(464, /* R u */ 'l' _ 'e' _ 'D' _ 'e' _ 'l' _ 'a' _ 'y' _ 'e' _ 'd' _ ';', 10, 0x29f4 _ 0) -NAMED_CHARACTER_REFERENCE(465, /* S H */ 'C' _ 'H' _ 'c' _ 'y' _ ';', 5, 0x0429 _ 0) -NAMED_CHARACTER_REFERENCE(466, /* S H */ 'c' _ 'y' _ ';', 3, 0x0428 _ 0) -NAMED_CHARACTER_REFERENCE(467, /* S O */ 'F' _ 'T' _ 'c' _ 'y' _ ';', 5, 0x042c _ 0) -NAMED_CHARACTER_REFERENCE(468, /* S a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x015a _ 0) -NAMED_CHARACTER_REFERENCE(469, /* S c */ ';', 1, 0x2abc _ 0) -NAMED_CHARACTER_REFERENCE(470, /* S c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0160 _ 0) -NAMED_CHARACTER_REFERENCE(471, /* S c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x015e _ 0) -NAMED_CHARACTER_REFERENCE(472, /* S c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x015c _ 0) -NAMED_CHARACTER_REFERENCE(473, /* S c */ 'y' _ ';', 2, 0x0421 _ 0) -NAMED_CHARACTER_REFERENCE(474, /* S f */ 'r' _ ';', 2, 0xd835 _ 0xdd16) -NAMED_CHARACTER_REFERENCE(475, /* S h */ 'o' _ 'r' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(476, /* S h */ 'o' _ 'r' _ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(477, /* S h */ 'o' _ 'r' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(478, /* S h */ 'o' _ 'r' _ 't' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(479, /* S i */ 'g' _ 'm' _ 'a' _ ';', 4, 0x03a3 _ 0) -NAMED_CHARACTER_REFERENCE(480, /* S m */ 'a' _ 'l' _ 'l' _ 'C' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ ';', 10, 0x2218 _ 0) -NAMED_CHARACTER_REFERENCE(481, /* S o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4a) -NAMED_CHARACTER_REFERENCE(482, /* S q */ 'r' _ 't' _ ';', 3, 0x221a _ 0) -NAMED_CHARACTER_REFERENCE(483, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0x25a1 _ 0) -NAMED_CHARACTER_REFERENCE(484, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'I' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 17, 0x2293 _ 0) -NAMED_CHARACTER_REFERENCE(485, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 11, 0x228f _ 0) -NAMED_CHARACTER_REFERENCE(486, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0x2291 _ 0) -NAMED_CHARACTER_REFERENCE(487, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 13, 0x2290 _ 0) -NAMED_CHARACTER_REFERENCE(488, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 18, 0x2292 _ 0) -NAMED_CHARACTER_REFERENCE(489, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'U' _ 'n' _ 'i' _ 'o' _ 'n' _ ';', 10, 0x2294 _ 0) -NAMED_CHARACTER_REFERENCE(490, /* S s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcae) -NAMED_CHARACTER_REFERENCE(491, /* S t */ 'a' _ 'r' _ ';', 3, 0x22c6 _ 0) -NAMED_CHARACTER_REFERENCE(492, /* S u */ 'b' _ ';', 2, 0x22d0 _ 0) -NAMED_CHARACTER_REFERENCE(493, /* S u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0x22d0 _ 0) -NAMED_CHARACTER_REFERENCE(494, /* S u */ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 10, 0x2286 _ 0) -NAMED_CHARACTER_REFERENCE(495, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 7, 0x227b _ 0) -NAMED_CHARACTER_REFERENCE(496, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2ab0 _ 0) -NAMED_CHARACTER_REFERENCE(497, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0x227d _ 0) -NAMED_CHARACTER_REFERENCE(498, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x227f _ 0) -NAMED_CHARACTER_REFERENCE(499, /* S u */ 'c' _ 'h' _ 'T' _ 'h' _ 'a' _ 't' _ ';', 7, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(500, /* S u */ 'm' _ ';', 2, 0x2211 _ 0) -NAMED_CHARACTER_REFERENCE(501, /* S u */ 'p' _ ';', 2, 0x22d1 _ 0) -NAMED_CHARACTER_REFERENCE(502, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 7, 0x2283 _ 0) -NAMED_CHARACTER_REFERENCE(503, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0x2287 _ 0) -NAMED_CHARACTER_REFERENCE(504, /* S u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0x22d1 _ 0) -NAMED_CHARACTER_REFERENCE(505, /* T H */ 'O' _ 'R' _ 'N', 3, 0x00de _ 0) -NAMED_CHARACTER_REFERENCE(506, /* T H */ 'O' _ 'R' _ 'N' _ ';', 4, 0x00de _ 0) -NAMED_CHARACTER_REFERENCE(507, /* T R */ 'A' _ 'D' _ 'E' _ ';', 4, 0x2122 _ 0) -NAMED_CHARACTER_REFERENCE(508, /* T S */ 'H' _ 'c' _ 'y' _ ';', 4, 0x040b _ 0) -NAMED_CHARACTER_REFERENCE(509, /* T S */ 'c' _ 'y' _ ';', 3, 0x0426 _ 0) -NAMED_CHARACTER_REFERENCE(510, /* T a */ 'b' _ ';', 2, 0x0009 _ 0) -NAMED_CHARACTER_REFERENCE(511, /* T a */ 'u' _ ';', 2, 0x03a4 _ 0) -NAMED_CHARACTER_REFERENCE(512, /* T c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0164 _ 0) -NAMED_CHARACTER_REFERENCE(513, /* T c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0162 _ 0) -NAMED_CHARACTER_REFERENCE(514, /* T c */ 'y' _ ';', 2, 0x0422 _ 0) -NAMED_CHARACTER_REFERENCE(515, /* T f */ 'r' _ ';', 2, 0xd835 _ 0xdd17) -NAMED_CHARACTER_REFERENCE(516, /* T h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0x2234 _ 0) -NAMED_CHARACTER_REFERENCE(517, /* T h */ 'e' _ 't' _ 'a' _ ';', 4, 0x0398 _ 0) -NAMED_CHARACTER_REFERENCE(518, /* T h */ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 8, 0x2009 _ 0) -NAMED_CHARACTER_REFERENCE(519, /* T i */ 'l' _ 'd' _ 'e' _ ';', 4, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(520, /* T i */ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 9, 0x2243 _ 0) -NAMED_CHARACTER_REFERENCE(521, /* T i */ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0x2245 _ 0) -NAMED_CHARACTER_REFERENCE(522, /* T i */ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(523, /* T o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4b) -NAMED_CHARACTER_REFERENCE(524, /* T r */ 'i' _ 'p' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0x20db _ 0) -NAMED_CHARACTER_REFERENCE(525, /* T s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcaf) -NAMED_CHARACTER_REFERENCE(526, /* T s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0166 _ 0) -NAMED_CHARACTER_REFERENCE(527, /* U a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00da _ 0) -NAMED_CHARACTER_REFERENCE(528, /* U a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00da _ 0) -NAMED_CHARACTER_REFERENCE(529, /* U a */ 'r' _ 'r' _ ';', 3, 0x219f _ 0) -NAMED_CHARACTER_REFERENCE(530, /* U a */ 'r' _ 'r' _ 'o' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2949 _ 0) -NAMED_CHARACTER_REFERENCE(531, /* U b */ 'r' _ 'c' _ 'y' _ ';', 4, 0x040e _ 0) -NAMED_CHARACTER_REFERENCE(532, /* U b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x016c _ 0) -NAMED_CHARACTER_REFERENCE(533, /* U c */ 'i' _ 'r' _ 'c', 3, 0x00db _ 0) -NAMED_CHARACTER_REFERENCE(534, /* U c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00db _ 0) -NAMED_CHARACTER_REFERENCE(535, /* U c */ 'y' _ ';', 2, 0x0423 _ 0) -NAMED_CHARACTER_REFERENCE(536, /* U d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0170 _ 0) -NAMED_CHARACTER_REFERENCE(537, /* U f */ 'r' _ ';', 2, 0xd835 _ 0xdd18) -NAMED_CHARACTER_REFERENCE(538, /* U g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00d9 _ 0) -NAMED_CHARACTER_REFERENCE(539, /* U g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00d9 _ 0) -NAMED_CHARACTER_REFERENCE(540, /* U m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x016a _ 0) -NAMED_CHARACTER_REFERENCE(541, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 7, 0x005f _ 0) -NAMED_CHARACTER_REFERENCE(542, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 9, 0x23df _ 0) -NAMED_CHARACTER_REFERENCE(543, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 11, 0x23b5 _ 0) -NAMED_CHARACTER_REFERENCE(544, /* U n */ 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 15, 0x23dd _ 0) -NAMED_CHARACTER_REFERENCE(545, /* U n */ 'i' _ 'o' _ 'n' _ ';', 4, 0x22c3 _ 0) -NAMED_CHARACTER_REFERENCE(546, /* U n */ 'i' _ 'o' _ 'n' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0x228e _ 0) -NAMED_CHARACTER_REFERENCE(547, /* U o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0172 _ 0) -NAMED_CHARACTER_REFERENCE(548, /* U o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4c) -NAMED_CHARACTER_REFERENCE(549, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(550, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 9, 0x2912 _ 0) -NAMED_CHARACTER_REFERENCE(551, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x21c5 _ 0) -NAMED_CHARACTER_REFERENCE(552, /* U p */ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2195 _ 0) -NAMED_CHARACTER_REFERENCE(553, /* U p */ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 12, 0x296e _ 0) -NAMED_CHARACTER_REFERENCE(554, /* U p */ 'T' _ 'e' _ 'e' _ ';', 4, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(555, /* U p */ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21a5 _ 0) -NAMED_CHARACTER_REFERENCE(556, /* U p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x21d1 _ 0) -NAMED_CHARACTER_REFERENCE(557, /* U p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x21d5 _ 0) -NAMED_CHARACTER_REFERENCE(558, /* U p */ 'p' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2196 _ 0) -NAMED_CHARACTER_REFERENCE(559, /* U p */ 'p' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x2197 _ 0) -NAMED_CHARACTER_REFERENCE(560, /* U p */ 's' _ 'i' _ ';', 3, 0x03d2 _ 0) -NAMED_CHARACTER_REFERENCE(561, /* U p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x03a5 _ 0) -NAMED_CHARACTER_REFERENCE(562, /* U r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x016e _ 0) -NAMED_CHARACTER_REFERENCE(563, /* U s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb0) -NAMED_CHARACTER_REFERENCE(564, /* U t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0168 _ 0) -NAMED_CHARACTER_REFERENCE(565, /* U u */ 'm' _ 'l', 2, 0x00dc _ 0) -NAMED_CHARACTER_REFERENCE(566, /* U u */ 'm' _ 'l' _ ';', 3, 0x00dc _ 0) -NAMED_CHARACTER_REFERENCE(567, /* V D */ 'a' _ 's' _ 'h' _ ';', 4, 0x22ab _ 0) -NAMED_CHARACTER_REFERENCE(568, /* V b */ 'a' _ 'r' _ ';', 3, 0x2aeb _ 0) -NAMED_CHARACTER_REFERENCE(569, /* V c */ 'y' _ ';', 2, 0x0412 _ 0) -NAMED_CHARACTER_REFERENCE(570, /* V d */ 'a' _ 's' _ 'h' _ ';', 4, 0x22a9 _ 0) -NAMED_CHARACTER_REFERENCE(571, /* V d */ 'a' _ 's' _ 'h' _ 'l' _ ';', 5, 0x2ae6 _ 0) -NAMED_CHARACTER_REFERENCE(572, /* V e */ 'e' _ ';', 2, 0x22c1 _ 0) -NAMED_CHARACTER_REFERENCE(573, /* V e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x2016 _ 0) -NAMED_CHARACTER_REFERENCE(574, /* V e */ 'r' _ 't' _ ';', 3, 0x2016 _ 0) -NAMED_CHARACTER_REFERENCE(575, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 10, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(576, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 11, 0x007c _ 0) -NAMED_CHARACTER_REFERENCE(577, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'S' _ 'e' _ 'p' _ 'a' _ 'r' _ 'a' _ 't' _ 'o' _ 'r' _ ';', 16, 0x2758 _ 0) -NAMED_CHARACTER_REFERENCE(578, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0x2240 _ 0) -NAMED_CHARACTER_REFERENCE(579, /* V e */ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 12, 0x200a _ 0) -NAMED_CHARACTER_REFERENCE(580, /* V f */ 'r' _ ';', 2, 0xd835 _ 0xdd19) -NAMED_CHARACTER_REFERENCE(581, /* V o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4d) -NAMED_CHARACTER_REFERENCE(582, /* V s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb1) -NAMED_CHARACTER_REFERENCE(583, /* V v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22aa _ 0) -NAMED_CHARACTER_REFERENCE(584, /* W c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0174 _ 0) -NAMED_CHARACTER_REFERENCE(585, /* W e */ 'd' _ 'g' _ 'e' _ ';', 4, 0x22c0 _ 0) -NAMED_CHARACTER_REFERENCE(586, /* W f */ 'r' _ ';', 2, 0xd835 _ 0xdd1a) -NAMED_CHARACTER_REFERENCE(587, /* W o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4e) -NAMED_CHARACTER_REFERENCE(588, /* W s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb2) -NAMED_CHARACTER_REFERENCE(589, /* X f */ 'r' _ ';', 2, 0xd835 _ 0xdd1b) -NAMED_CHARACTER_REFERENCE(590, /* X i */ ';', 1, 0x039e _ 0) -NAMED_CHARACTER_REFERENCE(591, /* X o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd4f) -NAMED_CHARACTER_REFERENCE(592, /* X s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb3) -NAMED_CHARACTER_REFERENCE(593, /* Y A */ 'c' _ 'y' _ ';', 3, 0x042f _ 0) -NAMED_CHARACTER_REFERENCE(594, /* Y I */ 'c' _ 'y' _ ';', 3, 0x0407 _ 0) -NAMED_CHARACTER_REFERENCE(595, /* Y U */ 'c' _ 'y' _ ';', 3, 0x042e _ 0) -NAMED_CHARACTER_REFERENCE(596, /* Y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00dd _ 0) -NAMED_CHARACTER_REFERENCE(597, /* Y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00dd _ 0) -NAMED_CHARACTER_REFERENCE(598, /* Y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0176 _ 0) -NAMED_CHARACTER_REFERENCE(599, /* Y c */ 'y' _ ';', 2, 0x042b _ 0) -NAMED_CHARACTER_REFERENCE(600, /* Y f */ 'r' _ ';', 2, 0xd835 _ 0xdd1c) -NAMED_CHARACTER_REFERENCE(601, /* Y o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd50) -NAMED_CHARACTER_REFERENCE(602, /* Y s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb4) -NAMED_CHARACTER_REFERENCE(603, /* Y u */ 'm' _ 'l' _ ';', 3, 0x0178 _ 0) -NAMED_CHARACTER_REFERENCE(604, /* Z H */ 'c' _ 'y' _ ';', 3, 0x0416 _ 0) -NAMED_CHARACTER_REFERENCE(605, /* Z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0179 _ 0) -NAMED_CHARACTER_REFERENCE(606, /* Z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x017d _ 0) -NAMED_CHARACTER_REFERENCE(607, /* Z c */ 'y' _ ';', 2, 0x0417 _ 0) -NAMED_CHARACTER_REFERENCE(608, /* Z d */ 'o' _ 't' _ ';', 3, 0x017b _ 0) -NAMED_CHARACTER_REFERENCE(609, /* Z e */ 'r' _ 'o' _ 'W' _ 'i' _ 'd' _ 't' _ 'h' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 13, 0x200b _ 0) -NAMED_CHARACTER_REFERENCE(610, /* Z e */ 't' _ 'a' _ ';', 3, 0x0396 _ 0) -NAMED_CHARACTER_REFERENCE(611, /* Z f */ 'r' _ ';', 2, 0x2128 _ 0) -NAMED_CHARACTER_REFERENCE(612, /* Z o */ 'p' _ 'f' _ ';', 3, 0x2124 _ 0) -NAMED_CHARACTER_REFERENCE(613, /* Z s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb5) -NAMED_CHARACTER_REFERENCE(614, /* a a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00e1 _ 0) -NAMED_CHARACTER_REFERENCE(615, /* a a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00e1 _ 0) -NAMED_CHARACTER_REFERENCE(616, /* a b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x0103 _ 0) -NAMED_CHARACTER_REFERENCE(617, /* a c */ ';', 1, 0x223e _ 0) -NAMED_CHARACTER_REFERENCE(618, /* a c */ 'd' _ ';', 2, 0x223f _ 0) -NAMED_CHARACTER_REFERENCE(619, /* a c */ 'i' _ 'r' _ 'c', 3, 0x00e2 _ 0) -NAMED_CHARACTER_REFERENCE(620, /* a c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00e2 _ 0) -NAMED_CHARACTER_REFERENCE(621, /* a c */ 'u' _ 't' _ 'e', 3, 0x00b4 _ 0) -NAMED_CHARACTER_REFERENCE(622, /* a c */ 'u' _ 't' _ 'e' _ ';', 4, 0x00b4 _ 0) -NAMED_CHARACTER_REFERENCE(623, /* a c */ 'y' _ ';', 2, 0x0430 _ 0) -NAMED_CHARACTER_REFERENCE(624, /* a e */ 'l' _ 'i' _ 'g', 3, 0x00e6 _ 0) -NAMED_CHARACTER_REFERENCE(625, /* a e */ 'l' _ 'i' _ 'g' _ ';', 4, 0x00e6 _ 0) -NAMED_CHARACTER_REFERENCE(626, /* a f */ ';', 1, 0x2061 _ 0) -NAMED_CHARACTER_REFERENCE(627, /* a f */ 'r' _ ';', 2, 0xd835 _ 0xdd1e) -NAMED_CHARACTER_REFERENCE(628, /* a g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00e0 _ 0) -NAMED_CHARACTER_REFERENCE(629, /* a g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00e0 _ 0) -NAMED_CHARACTER_REFERENCE(630, /* a l */ 'e' _ 'f' _ 's' _ 'y' _ 'm' _ ';', 6, 0x2135 _ 0) -NAMED_CHARACTER_REFERENCE(631, /* a l */ 'e' _ 'p' _ 'h' _ ';', 4, 0x2135 _ 0) -NAMED_CHARACTER_REFERENCE(632, /* a l */ 'p' _ 'h' _ 'a' _ ';', 4, 0x03b1 _ 0) -NAMED_CHARACTER_REFERENCE(633, /* a m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0101 _ 0) -NAMED_CHARACTER_REFERENCE(634, /* a m */ 'a' _ 'l' _ 'g' _ ';', 4, 0x2a3f _ 0) -NAMED_CHARACTER_REFERENCE(635, /* a m */ 'p', 1, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(636, /* a m */ 'p' _ ';', 2, 0x0026 _ 0) -NAMED_CHARACTER_REFERENCE(637, /* a n */ 'd' _ ';', 2, 0x2227 _ 0) -NAMED_CHARACTER_REFERENCE(638, /* a n */ 'd' _ 'a' _ 'n' _ 'd' _ ';', 5, 0x2a55 _ 0) -NAMED_CHARACTER_REFERENCE(639, /* a n */ 'd' _ 'd' _ ';', 3, 0x2a5c _ 0) -NAMED_CHARACTER_REFERENCE(640, /* a n */ 'd' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 7, 0x2a58 _ 0) -NAMED_CHARACTER_REFERENCE(641, /* a n */ 'd' _ 'v' _ ';', 3, 0x2a5a _ 0) -NAMED_CHARACTER_REFERENCE(642, /* a n */ 'g' _ ';', 2, 0x2220 _ 0) -NAMED_CHARACTER_REFERENCE(643, /* a n */ 'g' _ 'e' _ ';', 3, 0x29a4 _ 0) -NAMED_CHARACTER_REFERENCE(644, /* a n */ 'g' _ 'l' _ 'e' _ ';', 4, 0x2220 _ 0) -NAMED_CHARACTER_REFERENCE(645, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ ';', 5, 0x2221 _ 0) -NAMED_CHARACTER_REFERENCE(646, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'a' _ ';', 7, 0x29a8 _ 0) -NAMED_CHARACTER_REFERENCE(647, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'b' _ ';', 7, 0x29a9 _ 0) -NAMED_CHARACTER_REFERENCE(648, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'c' _ ';', 7, 0x29aa _ 0) -NAMED_CHARACTER_REFERENCE(649, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'd' _ ';', 7, 0x29ab _ 0) -NAMED_CHARACTER_REFERENCE(650, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'e' _ ';', 7, 0x29ac _ 0) -NAMED_CHARACTER_REFERENCE(651, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'f' _ ';', 7, 0x29ad _ 0) -NAMED_CHARACTER_REFERENCE(652, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'g' _ ';', 7, 0x29ae _ 0) -NAMED_CHARACTER_REFERENCE(653, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'h' _ ';', 7, 0x29af _ 0) -NAMED_CHARACTER_REFERENCE(654, /* a n */ 'g' _ 'r' _ 't' _ ';', 4, 0x221f _ 0) -NAMED_CHARACTER_REFERENCE(655, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 6, 0x22be _ 0) -NAMED_CHARACTER_REFERENCE(656, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 7, 0x299d _ 0) -NAMED_CHARACTER_REFERENCE(657, /* a n */ 'g' _ 's' _ 'p' _ 'h' _ ';', 5, 0x2222 _ 0) -NAMED_CHARACTER_REFERENCE(658, /* a n */ 'g' _ 's' _ 't' _ ';', 4, 0x00c5 _ 0) -NAMED_CHARACTER_REFERENCE(659, /* a n */ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x237c _ 0) -NAMED_CHARACTER_REFERENCE(660, /* a o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0105 _ 0) -NAMED_CHARACTER_REFERENCE(661, /* a o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd52) -NAMED_CHARACTER_REFERENCE(662, /* a p */ ';', 1, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(663, /* a p */ 'E' _ ';', 2, 0x2a70 _ 0) -NAMED_CHARACTER_REFERENCE(664, /* a p */ 'a' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2a6f _ 0) -NAMED_CHARACTER_REFERENCE(665, /* a p */ 'e' _ ';', 2, 0x224a _ 0) -NAMED_CHARACTER_REFERENCE(666, /* a p */ 'i' _ 'd' _ ';', 3, 0x224b _ 0) -NAMED_CHARACTER_REFERENCE(667, /* a p */ 'o' _ 's' _ ';', 3, 0x0027 _ 0) -NAMED_CHARACTER_REFERENCE(668, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ ';', 5, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(669, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ 'e' _ 'q' _ ';', 7, 0x224a _ 0) -NAMED_CHARACTER_REFERENCE(670, /* a r */ 'i' _ 'n' _ 'g', 3, 0x00e5 _ 0) -NAMED_CHARACTER_REFERENCE(671, /* a r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x00e5 _ 0) -NAMED_CHARACTER_REFERENCE(672, /* a s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb6) -NAMED_CHARACTER_REFERENCE(673, /* a s */ 't' _ ';', 2, 0x002a _ 0) -NAMED_CHARACTER_REFERENCE(674, /* a s */ 'y' _ 'm' _ 'p' _ ';', 4, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(675, /* a s */ 'y' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 6, 0x224d _ 0) -NAMED_CHARACTER_REFERENCE(676, /* a t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00e3 _ 0) -NAMED_CHARACTER_REFERENCE(677, /* a t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00e3 _ 0) -NAMED_CHARACTER_REFERENCE(678, /* a u */ 'm' _ 'l', 2, 0x00e4 _ 0) -NAMED_CHARACTER_REFERENCE(679, /* a u */ 'm' _ 'l' _ ';', 3, 0x00e4 _ 0) -NAMED_CHARACTER_REFERENCE(680, /* a w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2233 _ 0) -NAMED_CHARACTER_REFERENCE(681, /* a w */ 'i' _ 'n' _ 't' _ ';', 4, 0x2a11 _ 0) -NAMED_CHARACTER_REFERENCE(682, /* b N */ 'o' _ 't' _ ';', 3, 0x2aed _ 0) -NAMED_CHARACTER_REFERENCE(683, /* b a */ 'c' _ 'k' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 7, 0x224c _ 0) -NAMED_CHARACTER_REFERENCE(684, /* b a */ 'c' _ 'k' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 10, 0x03f6 _ 0) -NAMED_CHARACTER_REFERENCE(685, /* b a */ 'c' _ 'k' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 8, 0x2035 _ 0) -NAMED_CHARACTER_REFERENCE(686, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 6, 0x223d _ 0) -NAMED_CHARACTER_REFERENCE(687, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 8, 0x22cd _ 0) -NAMED_CHARACTER_REFERENCE(688, /* b a */ 'r' _ 'v' _ 'e' _ 'e' _ ';', 5, 0x22bd _ 0) -NAMED_CHARACTER_REFERENCE(689, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0x2305 _ 0) -NAMED_CHARACTER_REFERENCE(690, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0x2305 _ 0) -NAMED_CHARACTER_REFERENCE(691, /* b b */ 'r' _ 'k' _ ';', 3, 0x23b5 _ 0) -NAMED_CHARACTER_REFERENCE(692, /* b b */ 'r' _ 'k' _ 't' _ 'b' _ 'r' _ 'k' _ ';', 7, 0x23b6 _ 0) -NAMED_CHARACTER_REFERENCE(693, /* b c */ 'o' _ 'n' _ 'g' _ ';', 4, 0x224c _ 0) -NAMED_CHARACTER_REFERENCE(694, /* b c */ 'y' _ ';', 2, 0x0431 _ 0) -NAMED_CHARACTER_REFERENCE(695, /* b d */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201e _ 0) -NAMED_CHARACTER_REFERENCE(696, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ ';', 5, 0x2235 _ 0) -NAMED_CHARACTER_REFERENCE(697, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0x2235 _ 0) -NAMED_CHARACTER_REFERENCE(698, /* b e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0x29b0 _ 0) -NAMED_CHARACTER_REFERENCE(699, /* b e */ 'p' _ 's' _ 'i' _ ';', 4, 0x03f6 _ 0) -NAMED_CHARACTER_REFERENCE(700, /* b e */ 'r' _ 'n' _ 'o' _ 'u' _ ';', 5, 0x212c _ 0) -NAMED_CHARACTER_REFERENCE(701, /* b e */ 't' _ 'a' _ ';', 3, 0x03b2 _ 0) -NAMED_CHARACTER_REFERENCE(702, /* b e */ 't' _ 'h' _ ';', 3, 0x2136 _ 0) -NAMED_CHARACTER_REFERENCE(703, /* b e */ 't' _ 'w' _ 'e' _ 'e' _ 'n' _ ';', 6, 0x226c _ 0) -NAMED_CHARACTER_REFERENCE(704, /* b f */ 'r' _ ';', 2, 0xd835 _ 0xdd1f) -NAMED_CHARACTER_REFERENCE(705, /* b i */ 'g' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x22c2 _ 0) -NAMED_CHARACTER_REFERENCE(706, /* b i */ 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0x25ef _ 0) -NAMED_CHARACTER_REFERENCE(707, /* b i */ 'g' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x22c3 _ 0) -NAMED_CHARACTER_REFERENCE(708, /* b i */ 'g' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2a00 _ 0) -NAMED_CHARACTER_REFERENCE(709, /* b i */ 'g' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a01 _ 0) -NAMED_CHARACTER_REFERENCE(710, /* b i */ 'g' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0x2a02 _ 0) -NAMED_CHARACTER_REFERENCE(711, /* b i */ 'g' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a06 _ 0) -NAMED_CHARACTER_REFERENCE(712, /* b i */ 'g' _ 's' _ 't' _ 'a' _ 'r' _ ';', 6, 0x2605 _ 0) -NAMED_CHARACTER_REFERENCE(713, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0x25bd _ 0) -NAMED_CHARACTER_REFERENCE(714, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'u' _ 'p' _ ';', 12, 0x25b3 _ 0) -NAMED_CHARACTER_REFERENCE(715, /* b i */ 'g' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0x2a04 _ 0) -NAMED_CHARACTER_REFERENCE(716, /* b i */ 'g' _ 'v' _ 'e' _ 'e' _ ';', 5, 0x22c1 _ 0) -NAMED_CHARACTER_REFERENCE(717, /* b i */ 'g' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0x22c0 _ 0) -NAMED_CHARACTER_REFERENCE(718, /* b k */ 'a' _ 'r' _ 'o' _ 'w' _ ';', 5, 0x290d _ 0) -NAMED_CHARACTER_REFERENCE(719, /* b l */ 'a' _ 'c' _ 'k' _ 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 11, 0x29eb _ 0) -NAMED_CHARACTER_REFERENCE(720, /* b l */ 'a' _ 'c' _ 'k' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(721, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0x25b4 _ 0) -NAMED_CHARACTER_REFERENCE(722, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 16, 0x25be _ 0) -NAMED_CHARACTER_REFERENCE(723, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0x25c2 _ 0) -NAMED_CHARACTER_REFERENCE(724, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0x25b8 _ 0) -NAMED_CHARACTER_REFERENCE(725, /* b l */ 'a' _ 'n' _ 'k' _ ';', 4, 0x2423 _ 0) -NAMED_CHARACTER_REFERENCE(726, /* b l */ 'k' _ '1' _ '2' _ ';', 4, 0x2592 _ 0) -NAMED_CHARACTER_REFERENCE(727, /* b l */ 'k' _ '1' _ '4' _ ';', 4, 0x2591 _ 0) -NAMED_CHARACTER_REFERENCE(728, /* b l */ 'k' _ '3' _ '4' _ ';', 4, 0x2593 _ 0) -NAMED_CHARACTER_REFERENCE(729, /* b l */ 'o' _ 'c' _ 'k' _ ';', 4, 0x2588 _ 0) -NAMED_CHARACTER_REFERENCE(730, /* b n */ 'o' _ 't' _ ';', 3, 0x2310 _ 0) -NAMED_CHARACTER_REFERENCE(731, /* b o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd53) -NAMED_CHARACTER_REFERENCE(732, /* b o */ 't' _ ';', 2, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(733, /* b o */ 't' _ 't' _ 'o' _ 'm' _ ';', 5, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(734, /* b o */ 'w' _ 't' _ 'i' _ 'e' _ ';', 5, 0x22c8 _ 0) -NAMED_CHARACTER_REFERENCE(735, /* b o */ 'x' _ 'D' _ 'L' _ ';', 4, 0x2557 _ 0) -NAMED_CHARACTER_REFERENCE(736, /* b o */ 'x' _ 'D' _ 'R' _ ';', 4, 0x2554 _ 0) -NAMED_CHARACTER_REFERENCE(737, /* b o */ 'x' _ 'D' _ 'l' _ ';', 4, 0x2556 _ 0) -NAMED_CHARACTER_REFERENCE(738, /* b o */ 'x' _ 'D' _ 'r' _ ';', 4, 0x2553 _ 0) -NAMED_CHARACTER_REFERENCE(739, /* b o */ 'x' _ 'H' _ ';', 3, 0x2550 _ 0) -NAMED_CHARACTER_REFERENCE(740, /* b o */ 'x' _ 'H' _ 'D' _ ';', 4, 0x2566 _ 0) -NAMED_CHARACTER_REFERENCE(741, /* b o */ 'x' _ 'H' _ 'U' _ ';', 4, 0x2569 _ 0) -NAMED_CHARACTER_REFERENCE(742, /* b o */ 'x' _ 'H' _ 'd' _ ';', 4, 0x2564 _ 0) -NAMED_CHARACTER_REFERENCE(743, /* b o */ 'x' _ 'H' _ 'u' _ ';', 4, 0x2567 _ 0) -NAMED_CHARACTER_REFERENCE(744, /* b o */ 'x' _ 'U' _ 'L' _ ';', 4, 0x255d _ 0) -NAMED_CHARACTER_REFERENCE(745, /* b o */ 'x' _ 'U' _ 'R' _ ';', 4, 0x255a _ 0) -NAMED_CHARACTER_REFERENCE(746, /* b o */ 'x' _ 'U' _ 'l' _ ';', 4, 0x255c _ 0) -NAMED_CHARACTER_REFERENCE(747, /* b o */ 'x' _ 'U' _ 'r' _ ';', 4, 0x2559 _ 0) -NAMED_CHARACTER_REFERENCE(748, /* b o */ 'x' _ 'V' _ ';', 3, 0x2551 _ 0) -NAMED_CHARACTER_REFERENCE(749, /* b o */ 'x' _ 'V' _ 'H' _ ';', 4, 0x256c _ 0) -NAMED_CHARACTER_REFERENCE(750, /* b o */ 'x' _ 'V' _ 'L' _ ';', 4, 0x2563 _ 0) -NAMED_CHARACTER_REFERENCE(751, /* b o */ 'x' _ 'V' _ 'R' _ ';', 4, 0x2560 _ 0) -NAMED_CHARACTER_REFERENCE(752, /* b o */ 'x' _ 'V' _ 'h' _ ';', 4, 0x256b _ 0) -NAMED_CHARACTER_REFERENCE(753, /* b o */ 'x' _ 'V' _ 'l' _ ';', 4, 0x2562 _ 0) -NAMED_CHARACTER_REFERENCE(754, /* b o */ 'x' _ 'V' _ 'r' _ ';', 4, 0x255f _ 0) -NAMED_CHARACTER_REFERENCE(755, /* b o */ 'x' _ 'b' _ 'o' _ 'x' _ ';', 5, 0x29c9 _ 0) -NAMED_CHARACTER_REFERENCE(756, /* b o */ 'x' _ 'd' _ 'L' _ ';', 4, 0x2555 _ 0) -NAMED_CHARACTER_REFERENCE(757, /* b o */ 'x' _ 'd' _ 'R' _ ';', 4, 0x2552 _ 0) -NAMED_CHARACTER_REFERENCE(758, /* b o */ 'x' _ 'd' _ 'l' _ ';', 4, 0x2510 _ 0) -NAMED_CHARACTER_REFERENCE(759, /* b o */ 'x' _ 'd' _ 'r' _ ';', 4, 0x250c _ 0) -NAMED_CHARACTER_REFERENCE(760, /* b o */ 'x' _ 'h' _ ';', 3, 0x2500 _ 0) -NAMED_CHARACTER_REFERENCE(761, /* b o */ 'x' _ 'h' _ 'D' _ ';', 4, 0x2565 _ 0) -NAMED_CHARACTER_REFERENCE(762, /* b o */ 'x' _ 'h' _ 'U' _ ';', 4, 0x2568 _ 0) -NAMED_CHARACTER_REFERENCE(763, /* b o */ 'x' _ 'h' _ 'd' _ ';', 4, 0x252c _ 0) -NAMED_CHARACTER_REFERENCE(764, /* b o */ 'x' _ 'h' _ 'u' _ ';', 4, 0x2534 _ 0) -NAMED_CHARACTER_REFERENCE(765, /* b o */ 'x' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x229f _ 0) -NAMED_CHARACTER_REFERENCE(766, /* b o */ 'x' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x229e _ 0) -NAMED_CHARACTER_REFERENCE(767, /* b o */ 'x' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0x22a0 _ 0) -NAMED_CHARACTER_REFERENCE(768, /* b o */ 'x' _ 'u' _ 'L' _ ';', 4, 0x255b _ 0) -NAMED_CHARACTER_REFERENCE(769, /* b o */ 'x' _ 'u' _ 'R' _ ';', 4, 0x2558 _ 0) -NAMED_CHARACTER_REFERENCE(770, /* b o */ 'x' _ 'u' _ 'l' _ ';', 4, 0x2518 _ 0) -NAMED_CHARACTER_REFERENCE(771, /* b o */ 'x' _ 'u' _ 'r' _ ';', 4, 0x2514 _ 0) -NAMED_CHARACTER_REFERENCE(772, /* b o */ 'x' _ 'v' _ ';', 3, 0x2502 _ 0) -NAMED_CHARACTER_REFERENCE(773, /* b o */ 'x' _ 'v' _ 'H' _ ';', 4, 0x256a _ 0) -NAMED_CHARACTER_REFERENCE(774, /* b o */ 'x' _ 'v' _ 'L' _ ';', 4, 0x2561 _ 0) -NAMED_CHARACTER_REFERENCE(775, /* b o */ 'x' _ 'v' _ 'R' _ ';', 4, 0x255e _ 0) -NAMED_CHARACTER_REFERENCE(776, /* b o */ 'x' _ 'v' _ 'h' _ ';', 4, 0x253c _ 0) -NAMED_CHARACTER_REFERENCE(777, /* b o */ 'x' _ 'v' _ 'l' _ ';', 4, 0x2524 _ 0) -NAMED_CHARACTER_REFERENCE(778, /* b o */ 'x' _ 'v' _ 'r' _ ';', 4, 0x251c _ 0) -NAMED_CHARACTER_REFERENCE(779, /* b p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2035 _ 0) -NAMED_CHARACTER_REFERENCE(780, /* b r */ 'e' _ 'v' _ 'e' _ ';', 4, 0x02d8 _ 0) -NAMED_CHARACTER_REFERENCE(781, /* b r */ 'v' _ 'b' _ 'a' _ 'r', 4, 0x00a6 _ 0) -NAMED_CHARACTER_REFERENCE(782, /* b r */ 'v' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x00a6 _ 0) -NAMED_CHARACTER_REFERENCE(783, /* b s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb7) -NAMED_CHARACTER_REFERENCE(784, /* b s */ 'e' _ 'm' _ 'i' _ ';', 4, 0x204f _ 0) -NAMED_CHARACTER_REFERENCE(785, /* b s */ 'i' _ 'm' _ ';', 3, 0x223d _ 0) -NAMED_CHARACTER_REFERENCE(786, /* b s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x22cd _ 0) -NAMED_CHARACTER_REFERENCE(787, /* b s */ 'o' _ 'l' _ ';', 3, 0x005c _ 0) -NAMED_CHARACTER_REFERENCE(788, /* b s */ 'o' _ 'l' _ 'b' _ ';', 4, 0x29c5 _ 0) -NAMED_CHARACTER_REFERENCE(789, /* b s */ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 7, 0x27c8 _ 0) -NAMED_CHARACTER_REFERENCE(790, /* b u */ 'l' _ 'l' _ ';', 3, 0x2022 _ 0) -NAMED_CHARACTER_REFERENCE(791, /* b u */ 'l' _ 'l' _ 'e' _ 't' _ ';', 5, 0x2022 _ 0) -NAMED_CHARACTER_REFERENCE(792, /* b u */ 'm' _ 'p' _ ';', 3, 0x224e _ 0) -NAMED_CHARACTER_REFERENCE(793, /* b u */ 'm' _ 'p' _ 'E' _ ';', 4, 0x2aae _ 0) -NAMED_CHARACTER_REFERENCE(794, /* b u */ 'm' _ 'p' _ 'e' _ ';', 4, 0x224f _ 0) -NAMED_CHARACTER_REFERENCE(795, /* b u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0x224f _ 0) -NAMED_CHARACTER_REFERENCE(796, /* c a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0107 _ 0) -NAMED_CHARACTER_REFERENCE(797, /* c a */ 'p' _ ';', 2, 0x2229 _ 0) -NAMED_CHARACTER_REFERENCE(798, /* c a */ 'p' _ 'a' _ 'n' _ 'd' _ ';', 5, 0x2a44 _ 0) -NAMED_CHARACTER_REFERENCE(799, /* c a */ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 7, 0x2a49 _ 0) -NAMED_CHARACTER_REFERENCE(800, /* c a */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x2a4b _ 0) -NAMED_CHARACTER_REFERENCE(801, /* c a */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a47 _ 0) -NAMED_CHARACTER_REFERENCE(802, /* c a */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a40 _ 0) -NAMED_CHARACTER_REFERENCE(803, /* c a */ 'r' _ 'e' _ 't' _ ';', 4, 0x2041 _ 0) -NAMED_CHARACTER_REFERENCE(804, /* c a */ 'r' _ 'o' _ 'n' _ ';', 4, 0x02c7 _ 0) -NAMED_CHARACTER_REFERENCE(805, /* c c */ 'a' _ 'p' _ 's' _ ';', 4, 0x2a4d _ 0) -NAMED_CHARACTER_REFERENCE(806, /* c c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010d _ 0) -NAMED_CHARACTER_REFERENCE(807, /* c c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0x00e7 _ 0) -NAMED_CHARACTER_REFERENCE(808, /* c c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x00e7 _ 0) -NAMED_CHARACTER_REFERENCE(809, /* c c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0109 _ 0) -NAMED_CHARACTER_REFERENCE(810, /* c c */ 'u' _ 'p' _ 's' _ ';', 4, 0x2a4c _ 0) -NAMED_CHARACTER_REFERENCE(811, /* c c */ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 6, 0x2a50 _ 0) -NAMED_CHARACTER_REFERENCE(812, /* c d */ 'o' _ 't' _ ';', 3, 0x010b _ 0) -NAMED_CHARACTER_REFERENCE(813, /* c e */ 'd' _ 'i' _ 'l', 3, 0x00b8 _ 0) -NAMED_CHARACTER_REFERENCE(814, /* c e */ 'd' _ 'i' _ 'l' _ ';', 4, 0x00b8 _ 0) -NAMED_CHARACTER_REFERENCE(815, /* c e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0x29b2 _ 0) -NAMED_CHARACTER_REFERENCE(816, /* c e */ 'n' _ 't', 2, 0x00a2 _ 0) -NAMED_CHARACTER_REFERENCE(817, /* c e */ 'n' _ 't' _ ';', 3, 0x00a2 _ 0) -NAMED_CHARACTER_REFERENCE(818, /* c e */ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 8, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(819, /* c f */ 'r' _ ';', 2, 0xd835 _ 0xdd20) -NAMED_CHARACTER_REFERENCE(820, /* c h */ 'c' _ 'y' _ ';', 3, 0x0447 _ 0) -NAMED_CHARACTER_REFERENCE(821, /* c h */ 'e' _ 'c' _ 'k' _ ';', 4, 0x2713 _ 0) -NAMED_CHARACTER_REFERENCE(822, /* c h */ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 8, 0x2713 _ 0) -NAMED_CHARACTER_REFERENCE(823, /* c h */ 'i' _ ';', 2, 0x03c7 _ 0) -NAMED_CHARACTER_REFERENCE(824, /* c i */ 'r' _ ';', 2, 0x25cb _ 0) -NAMED_CHARACTER_REFERENCE(825, /* c i */ 'r' _ 'E' _ ';', 3, 0x29c3 _ 0) -NAMED_CHARACTER_REFERENCE(826, /* c i */ 'r' _ 'c' _ ';', 3, 0x02c6 _ 0) -NAMED_CHARACTER_REFERENCE(827, /* c i */ 'r' _ 'c' _ 'e' _ 'q' _ ';', 5, 0x2257 _ 0) -NAMED_CHARACTER_REFERENCE(828, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21ba _ 0) -NAMED_CHARACTER_REFERENCE(829, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21bb _ 0) -NAMED_CHARACTER_REFERENCE(830, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 7, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(831, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 7, 0x24c8 _ 0) -NAMED_CHARACTER_REFERENCE(832, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 9, 0x229b _ 0) -NAMED_CHARACTER_REFERENCE(833, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 10, 0x229a _ 0) -NAMED_CHARACTER_REFERENCE(834, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 10, 0x229d _ 0) -NAMED_CHARACTER_REFERENCE(835, /* c i */ 'r' _ 'e' _ ';', 3, 0x2257 _ 0) -NAMED_CHARACTER_REFERENCE(836, /* c i */ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a10 _ 0) -NAMED_CHARACTER_REFERENCE(837, /* c i */ 'r' _ 'm' _ 'i' _ 'd' _ ';', 5, 0x2aef _ 0) -NAMED_CHARACTER_REFERENCE(838, /* c i */ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x29c2 _ 0) -NAMED_CHARACTER_REFERENCE(839, /* c l */ 'u' _ 'b' _ 's' _ ';', 4, 0x2663 _ 0) -NAMED_CHARACTER_REFERENCE(840, /* c l */ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 7, 0x2663 _ 0) -NAMED_CHARACTER_REFERENCE(841, /* c o */ 'l' _ 'o' _ 'n' _ ';', 4, 0x003a _ 0) -NAMED_CHARACTER_REFERENCE(842, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0x2254 _ 0) -NAMED_CHARACTER_REFERENCE(843, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 6, 0x2254 _ 0) -NAMED_CHARACTER_REFERENCE(844, /* c o */ 'm' _ 'm' _ 'a' _ ';', 4, 0x002c _ 0) -NAMED_CHARACTER_REFERENCE(845, /* c o */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0x0040 _ 0) -NAMED_CHARACTER_REFERENCE(846, /* c o */ 'm' _ 'p' _ ';', 3, 0x2201 _ 0) -NAMED_CHARACTER_REFERENCE(847, /* c o */ 'm' _ 'p' _ 'f' _ 'n' _ ';', 5, 0x2218 _ 0) -NAMED_CHARACTER_REFERENCE(848, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0x2201 _ 0) -NAMED_CHARACTER_REFERENCE(849, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 8, 0x2102 _ 0) -NAMED_CHARACTER_REFERENCE(850, /* c o */ 'n' _ 'g' _ ';', 3, 0x2245 _ 0) -NAMED_CHARACTER_REFERENCE(851, /* c o */ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2a6d _ 0) -NAMED_CHARACTER_REFERENCE(852, /* c o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0x222e _ 0) -NAMED_CHARACTER_REFERENCE(853, /* c o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd54) -NAMED_CHARACTER_REFERENCE(854, /* c o */ 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0x2210 _ 0) -NAMED_CHARACTER_REFERENCE(855, /* c o */ 'p' _ 'y', 2, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(856, /* c o */ 'p' _ 'y' _ ';', 3, 0x00a9 _ 0) -NAMED_CHARACTER_REFERENCE(857, /* c o */ 'p' _ 'y' _ 's' _ 'r' _ ';', 5, 0x2117 _ 0) -NAMED_CHARACTER_REFERENCE(858, /* c r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21b5 _ 0) -NAMED_CHARACTER_REFERENCE(859, /* c r */ 'o' _ 's' _ 's' _ ';', 4, 0x2717 _ 0) -NAMED_CHARACTER_REFERENCE(860, /* c s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb8) -NAMED_CHARACTER_REFERENCE(861, /* c s */ 'u' _ 'b' _ ';', 3, 0x2acf _ 0) -NAMED_CHARACTER_REFERENCE(862, /* c s */ 'u' _ 'b' _ 'e' _ ';', 4, 0x2ad1 _ 0) -NAMED_CHARACTER_REFERENCE(863, /* c s */ 'u' _ 'p' _ ';', 3, 0x2ad0 _ 0) -NAMED_CHARACTER_REFERENCE(864, /* c s */ 'u' _ 'p' _ 'e' _ ';', 4, 0x2ad2 _ 0) -NAMED_CHARACTER_REFERENCE(865, /* c t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22ef _ 0) -NAMED_CHARACTER_REFERENCE(866, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 6, 0x2938 _ 0) -NAMED_CHARACTER_REFERENCE(867, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 6, 0x2935 _ 0) -NAMED_CHARACTER_REFERENCE(868, /* c u */ 'e' _ 'p' _ 'r' _ ';', 4, 0x22de _ 0) -NAMED_CHARACTER_REFERENCE(869, /* c u */ 'e' _ 's' _ 'c' _ ';', 4, 0x22df _ 0) -NAMED_CHARACTER_REFERENCE(870, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x21b6 _ 0) -NAMED_CHARACTER_REFERENCE(871, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 6, 0x293d _ 0) -NAMED_CHARACTER_REFERENCE(872, /* c u */ 'p' _ ';', 2, 0x222a _ 0) -NAMED_CHARACTER_REFERENCE(873, /* c u */ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 7, 0x2a48 _ 0) -NAMED_CHARACTER_REFERENCE(874, /* c u */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0x2a46 _ 0) -NAMED_CHARACTER_REFERENCE(875, /* c u */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a4a _ 0) -NAMED_CHARACTER_REFERENCE(876, /* c u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0x228d _ 0) -NAMED_CHARACTER_REFERENCE(877, /* c u */ 'p' _ 'o' _ 'r' _ ';', 4, 0x2a45 _ 0) -NAMED_CHARACTER_REFERENCE(878, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x21b7 _ 0) -NAMED_CHARACTER_REFERENCE(879, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 6, 0x293c _ 0) -NAMED_CHARACTER_REFERENCE(880, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 10, 0x22de _ 0) -NAMED_CHARACTER_REFERENCE(881, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 10, 0x22df _ 0) -NAMED_CHARACTER_REFERENCE(882, /* c u */ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 7, 0x22ce _ 0) -NAMED_CHARACTER_REFERENCE(883, /* c u */ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 9, 0x22cf _ 0) -NAMED_CHARACTER_REFERENCE(884, /* c u */ 'r' _ 'r' _ 'e' _ 'n', 4, 0x00a4 _ 0) -NAMED_CHARACTER_REFERENCE(885, /* c u */ 'r' _ 'r' _ 'e' _ 'n' _ ';', 5, 0x00a4 _ 0) -NAMED_CHARACTER_REFERENCE(886, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 13, 0x21b6 _ 0) -NAMED_CHARACTER_REFERENCE(887, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 14, 0x21b7 _ 0) -NAMED_CHARACTER_REFERENCE(888, /* c u */ 'v' _ 'e' _ 'e' _ ';', 4, 0x22ce _ 0) -NAMED_CHARACTER_REFERENCE(889, /* c u */ 'w' _ 'e' _ 'd' _ ';', 4, 0x22cf _ 0) -NAMED_CHARACTER_REFERENCE(890, /* c w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2232 _ 0) -NAMED_CHARACTER_REFERENCE(891, /* c w */ 'i' _ 'n' _ 't' _ ';', 4, 0x2231 _ 0) -NAMED_CHARACTER_REFERENCE(892, /* c y */ 'l' _ 'c' _ 't' _ 'y' _ ';', 5, 0x232d _ 0) -NAMED_CHARACTER_REFERENCE(893, /* d A */ 'r' _ 'r' _ ';', 3, 0x21d3 _ 0) -NAMED_CHARACTER_REFERENCE(894, /* d H */ 'a' _ 'r' _ ';', 3, 0x2965 _ 0) -NAMED_CHARACTER_REFERENCE(895, /* d a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0x2020 _ 0) -NAMED_CHARACTER_REFERENCE(896, /* d a */ 'l' _ 'e' _ 't' _ 'h' _ ';', 5, 0x2138 _ 0) -NAMED_CHARACTER_REFERENCE(897, /* d a */ 'r' _ 'r' _ ';', 3, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(898, /* d a */ 's' _ 'h' _ ';', 3, 0x2010 _ 0) -NAMED_CHARACTER_REFERENCE(899, /* d a */ 's' _ 'h' _ 'v' _ ';', 4, 0x22a3 _ 0) -NAMED_CHARACTER_REFERENCE(900, /* d b */ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x290f _ 0) -NAMED_CHARACTER_REFERENCE(901, /* d b */ 'l' _ 'a' _ 'c' _ ';', 4, 0x02dd _ 0) -NAMED_CHARACTER_REFERENCE(902, /* d c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x010f _ 0) -NAMED_CHARACTER_REFERENCE(903, /* d c */ 'y' _ ';', 2, 0x0434 _ 0) -NAMED_CHARACTER_REFERENCE(904, /* d d */ ';', 1, 0x2146 _ 0) -NAMED_CHARACTER_REFERENCE(905, /* d d */ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 6, 0x2021 _ 0) -NAMED_CHARACTER_REFERENCE(906, /* d d */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ca _ 0) -NAMED_CHARACTER_REFERENCE(907, /* d d */ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 6, 0x2a77 _ 0) -NAMED_CHARACTER_REFERENCE(908, /* d e */ 'g', 1, 0x00b0 _ 0) -NAMED_CHARACTER_REFERENCE(909, /* d e */ 'g' _ ';', 2, 0x00b0 _ 0) -NAMED_CHARACTER_REFERENCE(910, /* d e */ 'l' _ 't' _ 'a' _ ';', 4, 0x03b4 _ 0) -NAMED_CHARACTER_REFERENCE(911, /* d e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0x29b1 _ 0) -NAMED_CHARACTER_REFERENCE(912, /* d f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297f _ 0) -NAMED_CHARACTER_REFERENCE(913, /* d f */ 'r' _ ';', 2, 0xd835 _ 0xdd21) -NAMED_CHARACTER_REFERENCE(914, /* d h */ 'a' _ 'r' _ 'l' _ ';', 4, 0x21c3 _ 0) -NAMED_CHARACTER_REFERENCE(915, /* d h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c2 _ 0) -NAMED_CHARACTER_REFERENCE(916, /* d i */ 'a' _ 'm' _ ';', 3, 0x22c4 _ 0) -NAMED_CHARACTER_REFERENCE(917, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0x22c4 _ 0) -NAMED_CHARACTER_REFERENCE(918, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0x2666 _ 0) -NAMED_CHARACTER_REFERENCE(919, /* d i */ 'a' _ 'm' _ 's' _ ';', 4, 0x2666 _ 0) -NAMED_CHARACTER_REFERENCE(920, /* d i */ 'e' _ ';', 2, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(921, /* d i */ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0x03dd _ 0) -NAMED_CHARACTER_REFERENCE(922, /* d i */ 's' _ 'i' _ 'n' _ ';', 4, 0x22f2 _ 0) -NAMED_CHARACTER_REFERENCE(923, /* d i */ 'v' _ ';', 2, 0x00f7 _ 0) -NAMED_CHARACTER_REFERENCE(924, /* d i */ 'v' _ 'i' _ 'd' _ 'e', 4, 0x00f7 _ 0) -NAMED_CHARACTER_REFERENCE(925, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ ';', 5, 0x00f7 _ 0) -NAMED_CHARACTER_REFERENCE(926, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 12, 0x22c7 _ 0) -NAMED_CHARACTER_REFERENCE(927, /* d i */ 'v' _ 'o' _ 'n' _ 'x' _ ';', 5, 0x22c7 _ 0) -NAMED_CHARACTER_REFERENCE(928, /* d j */ 'c' _ 'y' _ ';', 3, 0x0452 _ 0) -NAMED_CHARACTER_REFERENCE(929, /* d l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231e _ 0) -NAMED_CHARACTER_REFERENCE(930, /* d l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230d _ 0) -NAMED_CHARACTER_REFERENCE(931, /* d o */ 'l' _ 'l' _ 'a' _ 'r' _ ';', 5, 0x0024 _ 0) -NAMED_CHARACTER_REFERENCE(932, /* d o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd55) -NAMED_CHARACTER_REFERENCE(933, /* d o */ 't' _ ';', 2, 0x02d9 _ 0) -NAMED_CHARACTER_REFERENCE(934, /* d o */ 't' _ 'e' _ 'q' _ ';', 4, 0x2250 _ 0) -NAMED_CHARACTER_REFERENCE(935, /* d o */ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 7, 0x2251 _ 0) -NAMED_CHARACTER_REFERENCE(936, /* d o */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2238 _ 0) -NAMED_CHARACTER_REFERENCE(937, /* d o */ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2214 _ 0) -NAMED_CHARACTER_REFERENCE(938, /* d o */ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 8, 0x22a1 _ 0) -NAMED_CHARACTER_REFERENCE(939, /* d o */ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 13, 0x2306 _ 0) -NAMED_CHARACTER_REFERENCE(940, /* d o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2193 _ 0) -NAMED_CHARACTER_REFERENCE(941, /* d o */ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0x21ca _ 0) -NAMED_CHARACTER_REFERENCE(942, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x21c3 _ 0) -NAMED_CHARACTER_REFERENCE(943, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x21c2 _ 0) -NAMED_CHARACTER_REFERENCE(944, /* d r */ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0x2910 _ 0) -NAMED_CHARACTER_REFERENCE(945, /* d r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231f _ 0) -NAMED_CHARACTER_REFERENCE(946, /* d r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230c _ 0) -NAMED_CHARACTER_REFERENCE(947, /* d s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcb9) -NAMED_CHARACTER_REFERENCE(948, /* d s */ 'c' _ 'y' _ ';', 3, 0x0455 _ 0) -NAMED_CHARACTER_REFERENCE(949, /* d s */ 'o' _ 'l' _ ';', 3, 0x29f6 _ 0) -NAMED_CHARACTER_REFERENCE(950, /* d s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0111 _ 0) -NAMED_CHARACTER_REFERENCE(951, /* d t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22f1 _ 0) -NAMED_CHARACTER_REFERENCE(952, /* d t */ 'r' _ 'i' _ ';', 3, 0x25bf _ 0) -NAMED_CHARACTER_REFERENCE(953, /* d t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25be _ 0) -NAMED_CHARACTER_REFERENCE(954, /* d u */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21f5 _ 0) -NAMED_CHARACTER_REFERENCE(955, /* d u */ 'h' _ 'a' _ 'r' _ ';', 4, 0x296f _ 0) -NAMED_CHARACTER_REFERENCE(956, /* d w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0x29a6 _ 0) -NAMED_CHARACTER_REFERENCE(957, /* d z */ 'c' _ 'y' _ ';', 3, 0x045f _ 0) -NAMED_CHARACTER_REFERENCE(958, /* d z */ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0x27ff _ 0) -NAMED_CHARACTER_REFERENCE(959, /* e D */ 'D' _ 'o' _ 't' _ ';', 4, 0x2a77 _ 0) -NAMED_CHARACTER_REFERENCE(960, /* e D */ 'o' _ 't' _ ';', 3, 0x2251 _ 0) -NAMED_CHARACTER_REFERENCE(961, /* e a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00e9 _ 0) -NAMED_CHARACTER_REFERENCE(962, /* e a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00e9 _ 0) -NAMED_CHARACTER_REFERENCE(963, /* e a */ 's' _ 't' _ 'e' _ 'r' _ ';', 5, 0x2a6e _ 0) -NAMED_CHARACTER_REFERENCE(964, /* e c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x011b _ 0) -NAMED_CHARACTER_REFERENCE(965, /* e c */ 'i' _ 'r' _ ';', 3, 0x2256 _ 0) -NAMED_CHARACTER_REFERENCE(966, /* e c */ 'i' _ 'r' _ 'c', 3, 0x00ea _ 0) -NAMED_CHARACTER_REFERENCE(967, /* e c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ea _ 0) -NAMED_CHARACTER_REFERENCE(968, /* e c */ 'o' _ 'l' _ 'o' _ 'n' _ ';', 5, 0x2255 _ 0) -NAMED_CHARACTER_REFERENCE(969, /* e c */ 'y' _ ';', 2, 0x044d _ 0) -NAMED_CHARACTER_REFERENCE(970, /* e d */ 'o' _ 't' _ ';', 3, 0x0117 _ 0) -NAMED_CHARACTER_REFERENCE(971, /* e e */ ';', 1, 0x2147 _ 0) -NAMED_CHARACTER_REFERENCE(972, /* e f */ 'D' _ 'o' _ 't' _ ';', 4, 0x2252 _ 0) -NAMED_CHARACTER_REFERENCE(973, /* e f */ 'r' _ ';', 2, 0xd835 _ 0xdd22) -NAMED_CHARACTER_REFERENCE(974, /* e g */ ';', 1, 0x2a9a _ 0) -NAMED_CHARACTER_REFERENCE(975, /* e g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00e8 _ 0) -NAMED_CHARACTER_REFERENCE(976, /* e g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00e8 _ 0) -NAMED_CHARACTER_REFERENCE(977, /* e g */ 's' _ ';', 2, 0x2a96 _ 0) -NAMED_CHARACTER_REFERENCE(978, /* e g */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a98 _ 0) -NAMED_CHARACTER_REFERENCE(979, /* e l */ ';', 1, 0x2a99 _ 0) -NAMED_CHARACTER_REFERENCE(980, /* e l */ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 7, 0x23e7 _ 0) -NAMED_CHARACTER_REFERENCE(981, /* e l */ 'l' _ ';', 2, 0x2113 _ 0) -NAMED_CHARACTER_REFERENCE(982, /* e l */ 's' _ ';', 2, 0x2a95 _ 0) -NAMED_CHARACTER_REFERENCE(983, /* e l */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a97 _ 0) -NAMED_CHARACTER_REFERENCE(984, /* e m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x0113 _ 0) -NAMED_CHARACTER_REFERENCE(985, /* e m */ 'p' _ 't' _ 'y' _ ';', 4, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(986, /* e m */ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 7, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(987, /* e m */ 'p' _ 't' _ 'y' _ 'v' _ ';', 5, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(988, /* e m */ 's' _ 'p' _ '1' _ '3' _ ';', 5, 0x2004 _ 0) -NAMED_CHARACTER_REFERENCE(989, /* e m */ 's' _ 'p' _ '1' _ '4' _ ';', 5, 0x2005 _ 0) -NAMED_CHARACTER_REFERENCE(990, /* e m */ 's' _ 'p' _ ';', 3, 0x2003 _ 0) -NAMED_CHARACTER_REFERENCE(991, /* e n */ 'g' _ ';', 2, 0x014b _ 0) -NAMED_CHARACTER_REFERENCE(992, /* e n */ 's' _ 'p' _ ';', 3, 0x2002 _ 0) -NAMED_CHARACTER_REFERENCE(993, /* e o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0119 _ 0) -NAMED_CHARACTER_REFERENCE(994, /* e o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd56) -NAMED_CHARACTER_REFERENCE(995, /* e p */ 'a' _ 'r' _ ';', 3, 0x22d5 _ 0) -NAMED_CHARACTER_REFERENCE(996, /* e p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0x29e3 _ 0) -NAMED_CHARACTER_REFERENCE(997, /* e p */ 'l' _ 'u' _ 's' _ ';', 4, 0x2a71 _ 0) -NAMED_CHARACTER_REFERENCE(998, /* e p */ 's' _ 'i' _ ';', 3, 0x03b5 _ 0) -NAMED_CHARACTER_REFERENCE(999, /* e p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x03b5 _ 0) -NAMED_CHARACTER_REFERENCE(1000, /* e p */ 's' _ 'i' _ 'v' _ ';', 4, 0x03f5 _ 0) -NAMED_CHARACTER_REFERENCE(1001, /* e q */ 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0x2256 _ 0) -NAMED_CHARACTER_REFERENCE(1002, /* e q */ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x2255 _ 0) -NAMED_CHARACTER_REFERENCE(1003, /* e q */ 's' _ 'i' _ 'm' _ ';', 4, 0x2242 _ 0) -NAMED_CHARACTER_REFERENCE(1004, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 9, 0x2a96 _ 0) -NAMED_CHARACTER_REFERENCE(1005, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0x2a95 _ 0) -NAMED_CHARACTER_REFERENCE(1006, /* e q */ 'u' _ 'a' _ 'l' _ 's' _ ';', 5, 0x003d _ 0) -NAMED_CHARACTER_REFERENCE(1007, /* e q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0x225f _ 0) -NAMED_CHARACTER_REFERENCE(1008, /* e q */ 'u' _ 'i' _ 'v' _ ';', 4, 0x2261 _ 0) -NAMED_CHARACTER_REFERENCE(1009, /* e q */ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 6, 0x2a78 _ 0) -NAMED_CHARACTER_REFERENCE(1010, /* e q */ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0x29e5 _ 0) -NAMED_CHARACTER_REFERENCE(1011, /* e r */ 'D' _ 'o' _ 't' _ ';', 4, 0x2253 _ 0) -NAMED_CHARACTER_REFERENCE(1012, /* e r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2971 _ 0) -NAMED_CHARACTER_REFERENCE(1013, /* e s */ 'c' _ 'r' _ ';', 3, 0x212f _ 0) -NAMED_CHARACTER_REFERENCE(1014, /* e s */ 'd' _ 'o' _ 't' _ ';', 4, 0x2250 _ 0) -NAMED_CHARACTER_REFERENCE(1015, /* e s */ 'i' _ 'm' _ ';', 3, 0x2242 _ 0) -NAMED_CHARACTER_REFERENCE(1016, /* e t */ 'a' _ ';', 2, 0x03b7 _ 0) -NAMED_CHARACTER_REFERENCE(1017, /* e t */ 'h', 1, 0x00f0 _ 0) -NAMED_CHARACTER_REFERENCE(1018, /* e t */ 'h' _ ';', 2, 0x00f0 _ 0) -NAMED_CHARACTER_REFERENCE(1019, /* e u */ 'm' _ 'l', 2, 0x00eb _ 0) -NAMED_CHARACTER_REFERENCE(1020, /* e u */ 'm' _ 'l' _ ';', 3, 0x00eb _ 0) -NAMED_CHARACTER_REFERENCE(1021, /* e u */ 'r' _ 'o' _ ';', 3, 0x20ac _ 0) -NAMED_CHARACTER_REFERENCE(1022, /* e x */ 'c' _ 'l' _ ';', 3, 0x0021 _ 0) -NAMED_CHARACTER_REFERENCE(1023, /* e x */ 'i' _ 's' _ 't' _ ';', 4, 0x2203 _ 0) -NAMED_CHARACTER_REFERENCE(1024, /* e x */ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 10, 0x2130 _ 0) -NAMED_CHARACTER_REFERENCE(1025, /* e x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', 11, 0x2147 _ 0) -NAMED_CHARACTER_REFERENCE(1026, /* f a */ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 12, 0x2252 _ 0) -NAMED_CHARACTER_REFERENCE(1027, /* f c */ 'y' _ ';', 2, 0x0444 _ 0) -NAMED_CHARACTER_REFERENCE(1028, /* f e */ 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0x2640 _ 0) -NAMED_CHARACTER_REFERENCE(1029, /* f f */ 'i' _ 'l' _ 'i' _ 'g' _ ';', 5, 0xfb03 _ 0) -NAMED_CHARACTER_REFERENCE(1030, /* f f */ 'l' _ 'i' _ 'g' _ ';', 4, 0xfb00 _ 0) -NAMED_CHARACTER_REFERENCE(1031, /* f f */ 'l' _ 'l' _ 'i' _ 'g' _ ';', 5, 0xfb04 _ 0) -NAMED_CHARACTER_REFERENCE(1032, /* f f */ 'r' _ ';', 2, 0xd835 _ 0xdd23) -NAMED_CHARACTER_REFERENCE(1033, /* f i */ 'l' _ 'i' _ 'g' _ ';', 4, 0xfb01 _ 0) -NAMED_CHARACTER_REFERENCE(1034, /* f l */ 'a' _ 't' _ ';', 3, 0x266d _ 0) -NAMED_CHARACTER_REFERENCE(1035, /* f l */ 'l' _ 'i' _ 'g' _ ';', 4, 0xfb02 _ 0) -NAMED_CHARACTER_REFERENCE(1036, /* f l */ 't' _ 'n' _ 's' _ ';', 4, 0x25b1 _ 0) -NAMED_CHARACTER_REFERENCE(1037, /* f n */ 'o' _ 'f' _ ';', 3, 0x0192 _ 0) -NAMED_CHARACTER_REFERENCE(1038, /* f o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd57) -NAMED_CHARACTER_REFERENCE(1039, /* f o */ 'r' _ 'a' _ 'l' _ 'l' _ ';', 5, 0x2200 _ 0) -NAMED_CHARACTER_REFERENCE(1040, /* f o */ 'r' _ 'k' _ ';', 3, 0x22d4 _ 0) -NAMED_CHARACTER_REFERENCE(1041, /* f o */ 'r' _ 'k' _ 'v' _ ';', 4, 0x2ad9 _ 0) -NAMED_CHARACTER_REFERENCE(1042, /* f p */ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a0d _ 0) -NAMED_CHARACTER_REFERENCE(1043, /* f r */ 'a' _ 'c' _ '1' _ '2', 4, 0x00bd _ 0) -NAMED_CHARACTER_REFERENCE(1044, /* f r */ 'a' _ 'c' _ '1' _ '2' _ ';', 5, 0x00bd _ 0) -NAMED_CHARACTER_REFERENCE(1045, /* f r */ 'a' _ 'c' _ '1' _ '3' _ ';', 5, 0x2153 _ 0) -NAMED_CHARACTER_REFERENCE(1046, /* f r */ 'a' _ 'c' _ '1' _ '4', 4, 0x00bc _ 0) -NAMED_CHARACTER_REFERENCE(1047, /* f r */ 'a' _ 'c' _ '1' _ '4' _ ';', 5, 0x00bc _ 0) -NAMED_CHARACTER_REFERENCE(1048, /* f r */ 'a' _ 'c' _ '1' _ '5' _ ';', 5, 0x2155 _ 0) -NAMED_CHARACTER_REFERENCE(1049, /* f r */ 'a' _ 'c' _ '1' _ '6' _ ';', 5, 0x2159 _ 0) -NAMED_CHARACTER_REFERENCE(1050, /* f r */ 'a' _ 'c' _ '1' _ '8' _ ';', 5, 0x215b _ 0) -NAMED_CHARACTER_REFERENCE(1051, /* f r */ 'a' _ 'c' _ '2' _ '3' _ ';', 5, 0x2154 _ 0) -NAMED_CHARACTER_REFERENCE(1052, /* f r */ 'a' _ 'c' _ '2' _ '5' _ ';', 5, 0x2156 _ 0) -NAMED_CHARACTER_REFERENCE(1053, /* f r */ 'a' _ 'c' _ '3' _ '4', 4, 0x00be _ 0) -NAMED_CHARACTER_REFERENCE(1054, /* f r */ 'a' _ 'c' _ '3' _ '4' _ ';', 5, 0x00be _ 0) -NAMED_CHARACTER_REFERENCE(1055, /* f r */ 'a' _ 'c' _ '3' _ '5' _ ';', 5, 0x2157 _ 0) -NAMED_CHARACTER_REFERENCE(1056, /* f r */ 'a' _ 'c' _ '3' _ '8' _ ';', 5, 0x215c _ 0) -NAMED_CHARACTER_REFERENCE(1057, /* f r */ 'a' _ 'c' _ '4' _ '5' _ ';', 5, 0x2158 _ 0) -NAMED_CHARACTER_REFERENCE(1058, /* f r */ 'a' _ 'c' _ '5' _ '6' _ ';', 5, 0x215a _ 0) -NAMED_CHARACTER_REFERENCE(1059, /* f r */ 'a' _ 'c' _ '5' _ '8' _ ';', 5, 0x215d _ 0) -NAMED_CHARACTER_REFERENCE(1060, /* f r */ 'a' _ 'c' _ '7' _ '8' _ ';', 5, 0x215e _ 0) -NAMED_CHARACTER_REFERENCE(1061, /* f r */ 'a' _ 's' _ 'l' _ ';', 4, 0x2044 _ 0) -NAMED_CHARACTER_REFERENCE(1062, /* f r */ 'o' _ 'w' _ 'n' _ ';', 4, 0x2322 _ 0) -NAMED_CHARACTER_REFERENCE(1063, /* f s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbb) -NAMED_CHARACTER_REFERENCE(1064, /* g E */ ';', 1, 0x2267 _ 0) -NAMED_CHARACTER_REFERENCE(1065, /* g E */ 'l' _ ';', 2, 0x2a8c _ 0) -NAMED_CHARACTER_REFERENCE(1066, /* g a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x01f5 _ 0) -NAMED_CHARACTER_REFERENCE(1067, /* g a */ 'm' _ 'm' _ 'a' _ ';', 4, 0x03b3 _ 0) -NAMED_CHARACTER_REFERENCE(1068, /* g a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0x03dd _ 0) -NAMED_CHARACTER_REFERENCE(1069, /* g a */ 'p' _ ';', 2, 0x2a86 _ 0) -NAMED_CHARACTER_REFERENCE(1070, /* g b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x011f _ 0) -NAMED_CHARACTER_REFERENCE(1071, /* g c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x011d _ 0) -NAMED_CHARACTER_REFERENCE(1072, /* g c */ 'y' _ ';', 2, 0x0433 _ 0) -NAMED_CHARACTER_REFERENCE(1073, /* g d */ 'o' _ 't' _ ';', 3, 0x0121 _ 0) -NAMED_CHARACTER_REFERENCE(1074, /* g e */ ';', 1, 0x2265 _ 0) -NAMED_CHARACTER_REFERENCE(1075, /* g e */ 'l' _ ';', 2, 0x22db _ 0) -NAMED_CHARACTER_REFERENCE(1076, /* g e */ 'q' _ ';', 2, 0x2265 _ 0) -NAMED_CHARACTER_REFERENCE(1077, /* g e */ 'q' _ 'q' _ ';', 3, 0x2267 _ 0) -NAMED_CHARACTER_REFERENCE(1078, /* g e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0x2a7e _ 0) -NAMED_CHARACTER_REFERENCE(1079, /* g e */ 's' _ ';', 2, 0x2a7e _ 0) -NAMED_CHARACTER_REFERENCE(1080, /* g e */ 's' _ 'c' _ 'c' _ ';', 4, 0x2aa9 _ 0) -NAMED_CHARACTER_REFERENCE(1081, /* g e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a80 _ 0) -NAMED_CHARACTER_REFERENCE(1082, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0x2a82 _ 0) -NAMED_CHARACTER_REFERENCE(1083, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 7, 0x2a84 _ 0) -NAMED_CHARACTER_REFERENCE(1084, /* g e */ 's' _ 'l' _ 'e' _ 's' _ ';', 5, 0x2a94 _ 0) -NAMED_CHARACTER_REFERENCE(1085, /* g f */ 'r' _ ';', 2, 0xd835 _ 0xdd24) -NAMED_CHARACTER_REFERENCE(1086, /* g g */ ';', 1, 0x226b _ 0) -NAMED_CHARACTER_REFERENCE(1087, /* g g */ 'g' _ ';', 2, 0x22d9 _ 0) -NAMED_CHARACTER_REFERENCE(1088, /* g i */ 'm' _ 'e' _ 'l' _ ';', 4, 0x2137 _ 0) -NAMED_CHARACTER_REFERENCE(1089, /* g j */ 'c' _ 'y' _ ';', 3, 0x0453 _ 0) -NAMED_CHARACTER_REFERENCE(1090, /* g l */ ';', 1, 0x2277 _ 0) -NAMED_CHARACTER_REFERENCE(1091, /* g l */ 'E' _ ';', 2, 0x2a92 _ 0) -NAMED_CHARACTER_REFERENCE(1092, /* g l */ 'a' _ ';', 2, 0x2aa5 _ 0) -NAMED_CHARACTER_REFERENCE(1093, /* g l */ 'j' _ ';', 2, 0x2aa4 _ 0) -NAMED_CHARACTER_REFERENCE(1094, /* g n */ 'E' _ ';', 2, 0x2269 _ 0) -NAMED_CHARACTER_REFERENCE(1095, /* g n */ 'a' _ 'p' _ ';', 3, 0x2a8a _ 0) -NAMED_CHARACTER_REFERENCE(1096, /* g n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0x2a8a _ 0) -NAMED_CHARACTER_REFERENCE(1097, /* g n */ 'e' _ ';', 2, 0x2a88 _ 0) -NAMED_CHARACTER_REFERENCE(1098, /* g n */ 'e' _ 'q' _ ';', 3, 0x2a88 _ 0) -NAMED_CHARACTER_REFERENCE(1099, /* g n */ 'e' _ 'q' _ 'q' _ ';', 4, 0x2269 _ 0) -NAMED_CHARACTER_REFERENCE(1100, /* g n */ 's' _ 'i' _ 'm' _ ';', 4, 0x22e7 _ 0) -NAMED_CHARACTER_REFERENCE(1101, /* g o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd58) -NAMED_CHARACTER_REFERENCE(1102, /* g r */ 'a' _ 'v' _ 'e' _ ';', 4, 0x0060 _ 0) -NAMED_CHARACTER_REFERENCE(1103, /* g s */ 'c' _ 'r' _ ';', 3, 0x210a _ 0) -NAMED_CHARACTER_REFERENCE(1104, /* g s */ 'i' _ 'm' _ ';', 3, 0x2273 _ 0) -NAMED_CHARACTER_REFERENCE(1105, /* g s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2a8e _ 0) -NAMED_CHARACTER_REFERENCE(1106, /* g s */ 'i' _ 'm' _ 'l' _ ';', 4, 0x2a90 _ 0) -NAMED_CHARACTER_REFERENCE(1107, /* g t */ 0, 0, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(1108, /* g t */ ';', 1, 0x003e _ 0) -NAMED_CHARACTER_REFERENCE(1109, /* g t */ 'c' _ 'c' _ ';', 3, 0x2aa7 _ 0) -NAMED_CHARACTER_REFERENCE(1110, /* g t */ 'c' _ 'i' _ 'r' _ ';', 4, 0x2a7a _ 0) -NAMED_CHARACTER_REFERENCE(1111, /* g t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22d7 _ 0) -NAMED_CHARACTER_REFERENCE(1112, /* g t */ 'l' _ 'P' _ 'a' _ 'r' _ ';', 5, 0x2995 _ 0) -NAMED_CHARACTER_REFERENCE(1113, /* g t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0x2a7c _ 0) -NAMED_CHARACTER_REFERENCE(1114, /* g t */ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0x2a86 _ 0) -NAMED_CHARACTER_REFERENCE(1115, /* g t */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2978 _ 0) -NAMED_CHARACTER_REFERENCE(1116, /* g t */ 'r' _ 'd' _ 'o' _ 't' _ ';', 5, 0x22d7 _ 0) -NAMED_CHARACTER_REFERENCE(1117, /* g t */ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0x22db _ 0) -NAMED_CHARACTER_REFERENCE(1118, /* g t */ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 9, 0x2a8c _ 0) -NAMED_CHARACTER_REFERENCE(1119, /* g t */ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0x2277 _ 0) -NAMED_CHARACTER_REFERENCE(1120, /* g t */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2273 _ 0) -NAMED_CHARACTER_REFERENCE(1121, /* h A */ 'r' _ 'r' _ ';', 3, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(1122, /* h a */ 'i' _ 'r' _ 's' _ 'p' _ ';', 5, 0x200a _ 0) -NAMED_CHARACTER_REFERENCE(1123, /* h a */ 'l' _ 'f' _ ';', 3, 0x00bd _ 0) -NAMED_CHARACTER_REFERENCE(1124, /* h a */ 'm' _ 'i' _ 'l' _ 't' _ ';', 5, 0x210b _ 0) -NAMED_CHARACTER_REFERENCE(1125, /* h a */ 'r' _ 'd' _ 'c' _ 'y' _ ';', 5, 0x044a _ 0) -NAMED_CHARACTER_REFERENCE(1126, /* h a */ 'r' _ 'r' _ ';', 3, 0x2194 _ 0) -NAMED_CHARACTER_REFERENCE(1127, /* h a */ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2948 _ 0) -NAMED_CHARACTER_REFERENCE(1128, /* h a */ 'r' _ 'r' _ 'w' _ ';', 4, 0x21ad _ 0) -NAMED_CHARACTER_REFERENCE(1129, /* h b */ 'a' _ 'r' _ ';', 3, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1130, /* h c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0125 _ 0) -NAMED_CHARACTER_REFERENCE(1131, /* h e */ 'a' _ 'r' _ 't' _ 's' _ ';', 5, 0x2665 _ 0) -NAMED_CHARACTER_REFERENCE(1132, /* h e */ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0x2665 _ 0) -NAMED_CHARACTER_REFERENCE(1133, /* h e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0x2026 _ 0) -NAMED_CHARACTER_REFERENCE(1134, /* h e */ 'r' _ 'c' _ 'o' _ 'n' _ ';', 5, 0x22b9 _ 0) -NAMED_CHARACTER_REFERENCE(1135, /* h f */ 'r' _ ';', 2, 0xd835 _ 0xdd25) -NAMED_CHARACTER_REFERENCE(1136, /* h k */ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0x2925 _ 0) -NAMED_CHARACTER_REFERENCE(1137, /* h k */ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0x2926 _ 0) -NAMED_CHARACTER_REFERENCE(1138, /* h o */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ff _ 0) -NAMED_CHARACTER_REFERENCE(1139, /* h o */ 'm' _ 't' _ 'h' _ 't' _ ';', 5, 0x223b _ 0) -NAMED_CHARACTER_REFERENCE(1140, /* h o */ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x21a9 _ 0) -NAMED_CHARACTER_REFERENCE(1141, /* h o */ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x21aa _ 0) -NAMED_CHARACTER_REFERENCE(1142, /* h o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd59) -NAMED_CHARACTER_REFERENCE(1143, /* h o */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x2015 _ 0) -NAMED_CHARACTER_REFERENCE(1144, /* h s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbd) -NAMED_CHARACTER_REFERENCE(1145, /* h s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1146, /* h s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0127 _ 0) -NAMED_CHARACTER_REFERENCE(1147, /* h y */ 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0x2043 _ 0) -NAMED_CHARACTER_REFERENCE(1148, /* h y */ 'p' _ 'h' _ 'e' _ 'n' _ ';', 5, 0x2010 _ 0) -NAMED_CHARACTER_REFERENCE(1149, /* i a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00ed _ 0) -NAMED_CHARACTER_REFERENCE(1150, /* i a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00ed _ 0) -NAMED_CHARACTER_REFERENCE(1151, /* i c */ ';', 1, 0x2063 _ 0) -NAMED_CHARACTER_REFERENCE(1152, /* i c */ 'i' _ 'r' _ 'c', 3, 0x00ee _ 0) -NAMED_CHARACTER_REFERENCE(1153, /* i c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00ee _ 0) -NAMED_CHARACTER_REFERENCE(1154, /* i c */ 'y' _ ';', 2, 0x0438 _ 0) -NAMED_CHARACTER_REFERENCE(1155, /* i e */ 'c' _ 'y' _ ';', 3, 0x0435 _ 0) -NAMED_CHARACTER_REFERENCE(1156, /* i e */ 'x' _ 'c' _ 'l', 3, 0x00a1 _ 0) -NAMED_CHARACTER_REFERENCE(1157, /* i e */ 'x' _ 'c' _ 'l' _ ';', 4, 0x00a1 _ 0) -NAMED_CHARACTER_REFERENCE(1158, /* i f */ 'f' _ ';', 2, 0x21d4 _ 0) -NAMED_CHARACTER_REFERENCE(1159, /* i f */ 'r' _ ';', 2, 0xd835 _ 0xdd26) -NAMED_CHARACTER_REFERENCE(1160, /* i g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00ec _ 0) -NAMED_CHARACTER_REFERENCE(1161, /* i g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00ec _ 0) -NAMED_CHARACTER_REFERENCE(1162, /* i i */ ';', 1, 0x2148 _ 0) -NAMED_CHARACTER_REFERENCE(1163, /* i i */ 'i' _ 'i' _ 'n' _ 't' _ ';', 5, 0x2a0c _ 0) -NAMED_CHARACTER_REFERENCE(1164, /* i i */ 'i' _ 'n' _ 't' _ ';', 4, 0x222d _ 0) -NAMED_CHARACTER_REFERENCE(1165, /* i i */ 'n' _ 'f' _ 'i' _ 'n' _ ';', 5, 0x29dc _ 0) -NAMED_CHARACTER_REFERENCE(1166, /* i i */ 'o' _ 't' _ 'a' _ ';', 4, 0x2129 _ 0) -NAMED_CHARACTER_REFERENCE(1167, /* i j */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0133 _ 0) -NAMED_CHARACTER_REFERENCE(1168, /* i m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x012b _ 0) -NAMED_CHARACTER_REFERENCE(1169, /* i m */ 'a' _ 'g' _ 'e' _ ';', 4, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(1170, /* i m */ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0x2110 _ 0) -NAMED_CHARACTER_REFERENCE(1171, /* i m */ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0x2111 _ 0) -NAMED_CHARACTER_REFERENCE(1172, /* i m */ 'a' _ 't' _ 'h' _ ';', 4, 0x0131 _ 0) -NAMED_CHARACTER_REFERENCE(1173, /* i m */ 'o' _ 'f' _ ';', 3, 0x22b7 _ 0) -NAMED_CHARACTER_REFERENCE(1174, /* i m */ 'p' _ 'e' _ 'd' _ ';', 4, 0x01b5 _ 0) -NAMED_CHARACTER_REFERENCE(1175, /* i n */ ';', 1, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(1176, /* i n */ 'c' _ 'a' _ 'r' _ 'e' _ ';', 5, 0x2105 _ 0) -NAMED_CHARACTER_REFERENCE(1177, /* i n */ 'f' _ 'i' _ 'n' _ ';', 4, 0x221e _ 0) -NAMED_CHARACTER_REFERENCE(1178, /* i n */ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 7, 0x29dd _ 0) -NAMED_CHARACTER_REFERENCE(1179, /* i n */ 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0131 _ 0) -NAMED_CHARACTER_REFERENCE(1180, /* i n */ 't' _ ';', 2, 0x222b _ 0) -NAMED_CHARACTER_REFERENCE(1181, /* i n */ 't' _ 'c' _ 'a' _ 'l' _ ';', 5, 0x22ba _ 0) -NAMED_CHARACTER_REFERENCE(1182, /* i n */ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 7, 0x2124 _ 0) -NAMED_CHARACTER_REFERENCE(1183, /* i n */ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 7, 0x22ba _ 0) -NAMED_CHARACTER_REFERENCE(1184, /* i n */ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0x2a17 _ 0) -NAMED_CHARACTER_REFERENCE(1185, /* i n */ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0x2a3c _ 0) -NAMED_CHARACTER_REFERENCE(1186, /* i o */ 'c' _ 'y' _ ';', 3, 0x0451 _ 0) -NAMED_CHARACTER_REFERENCE(1187, /* i o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x012f _ 0) -NAMED_CHARACTER_REFERENCE(1188, /* i o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5a) -NAMED_CHARACTER_REFERENCE(1189, /* i o */ 't' _ 'a' _ ';', 3, 0x03b9 _ 0) -NAMED_CHARACTER_REFERENCE(1190, /* i p */ 'r' _ 'o' _ 'd' _ ';', 4, 0x2a3c _ 0) -NAMED_CHARACTER_REFERENCE(1191, /* i q */ 'u' _ 'e' _ 's' _ 't', 4, 0x00bf _ 0) -NAMED_CHARACTER_REFERENCE(1192, /* i q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0x00bf _ 0) -NAMED_CHARACTER_REFERENCE(1193, /* i s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbe) -NAMED_CHARACTER_REFERENCE(1194, /* i s */ 'i' _ 'n' _ ';', 3, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(1195, /* i s */ 'i' _ 'n' _ 'E' _ ';', 4, 0x22f9 _ 0) -NAMED_CHARACTER_REFERENCE(1196, /* i s */ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22f5 _ 0) -NAMED_CHARACTER_REFERENCE(1197, /* i s */ 'i' _ 'n' _ 's' _ ';', 4, 0x22f4 _ 0) -NAMED_CHARACTER_REFERENCE(1198, /* i s */ 'i' _ 'n' _ 's' _ 'v' _ ';', 5, 0x22f3 _ 0) -NAMED_CHARACTER_REFERENCE(1199, /* i s */ 'i' _ 'n' _ 'v' _ ';', 4, 0x2208 _ 0) -NAMED_CHARACTER_REFERENCE(1200, /* i t */ ';', 1, 0x2062 _ 0) -NAMED_CHARACTER_REFERENCE(1201, /* i t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0129 _ 0) -NAMED_CHARACTER_REFERENCE(1202, /* i u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0456 _ 0) -NAMED_CHARACTER_REFERENCE(1203, /* i u */ 'm' _ 'l', 2, 0x00ef _ 0) -NAMED_CHARACTER_REFERENCE(1204, /* i u */ 'm' _ 'l' _ ';', 3, 0x00ef _ 0) -NAMED_CHARACTER_REFERENCE(1205, /* j c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0135 _ 0) -NAMED_CHARACTER_REFERENCE(1206, /* j c */ 'y' _ ';', 2, 0x0439 _ 0) -NAMED_CHARACTER_REFERENCE(1207, /* j f */ 'r' _ ';', 2, 0xd835 _ 0xdd27) -NAMED_CHARACTER_REFERENCE(1208, /* j m */ 'a' _ 't' _ 'h' _ ';', 4, 0x0237 _ 0) -NAMED_CHARACTER_REFERENCE(1209, /* j o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5b) -NAMED_CHARACTER_REFERENCE(1210, /* j s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcbf) -NAMED_CHARACTER_REFERENCE(1211, /* j s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0x0458 _ 0) -NAMED_CHARACTER_REFERENCE(1212, /* j u */ 'k' _ 'c' _ 'y' _ ';', 4, 0x0454 _ 0) -NAMED_CHARACTER_REFERENCE(1213, /* k a */ 'p' _ 'p' _ 'a' _ ';', 4, 0x03ba _ 0) -NAMED_CHARACTER_REFERENCE(1214, /* k a */ 'p' _ 'p' _ 'a' _ 'v' _ ';', 5, 0x03f0 _ 0) -NAMED_CHARACTER_REFERENCE(1215, /* k c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0137 _ 0) -NAMED_CHARACTER_REFERENCE(1216, /* k c */ 'y' _ ';', 2, 0x043a _ 0) -NAMED_CHARACTER_REFERENCE(1217, /* k f */ 'r' _ ';', 2, 0xd835 _ 0xdd28) -NAMED_CHARACTER_REFERENCE(1218, /* k g */ 'r' _ 'e' _ 'e' _ 'n' _ ';', 5, 0x0138 _ 0) -NAMED_CHARACTER_REFERENCE(1219, /* k h */ 'c' _ 'y' _ ';', 3, 0x0445 _ 0) -NAMED_CHARACTER_REFERENCE(1220, /* k j */ 'c' _ 'y' _ ';', 3, 0x045c _ 0) -NAMED_CHARACTER_REFERENCE(1221, /* k o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5c) -NAMED_CHARACTER_REFERENCE(1222, /* k s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc0) -NAMED_CHARACTER_REFERENCE(1223, /* l A */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21da _ 0) -NAMED_CHARACTER_REFERENCE(1224, /* l A */ 'r' _ 'r' _ ';', 3, 0x21d0 _ 0) -NAMED_CHARACTER_REFERENCE(1225, /* l A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x291b _ 0) -NAMED_CHARACTER_REFERENCE(1226, /* l B */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290e _ 0) -NAMED_CHARACTER_REFERENCE(1227, /* l E */ ';', 1, 0x2266 _ 0) -NAMED_CHARACTER_REFERENCE(1228, /* l E */ 'g' _ ';', 2, 0x2a8b _ 0) -NAMED_CHARACTER_REFERENCE(1229, /* l H */ 'a' _ 'r' _ ';', 3, 0x2962 _ 0) -NAMED_CHARACTER_REFERENCE(1230, /* l a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x013a _ 0) -NAMED_CHARACTER_REFERENCE(1231, /* l a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0x29b4 _ 0) -NAMED_CHARACTER_REFERENCE(1232, /* l a */ 'g' _ 'r' _ 'a' _ 'n' _ ';', 5, 0x2112 _ 0) -NAMED_CHARACTER_REFERENCE(1233, /* l a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0x03bb _ 0) -NAMED_CHARACTER_REFERENCE(1234, /* l a */ 'n' _ 'g' _ ';', 3, 0x27e8 _ 0) -NAMED_CHARACTER_REFERENCE(1235, /* l a */ 'n' _ 'g' _ 'd' _ ';', 4, 0x2991 _ 0) -NAMED_CHARACTER_REFERENCE(1236, /* l a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0x27e8 _ 0) -NAMED_CHARACTER_REFERENCE(1237, /* l a */ 'p' _ ';', 2, 0x2a85 _ 0) -NAMED_CHARACTER_REFERENCE(1238, /* l a */ 'q' _ 'u' _ 'o', 3, 0x00ab _ 0) -NAMED_CHARACTER_REFERENCE(1239, /* l a */ 'q' _ 'u' _ 'o' _ ';', 4, 0x00ab _ 0) -NAMED_CHARACTER_REFERENCE(1240, /* l a */ 'r' _ 'r' _ ';', 3, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(1241, /* l a */ 'r' _ 'r' _ 'b' _ ';', 4, 0x21e4 _ 0) -NAMED_CHARACTER_REFERENCE(1242, /* l a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0x291f _ 0) -NAMED_CHARACTER_REFERENCE(1243, /* l a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0x291d _ 0) -NAMED_CHARACTER_REFERENCE(1244, /* l a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x21a9 _ 0) -NAMED_CHARACTER_REFERENCE(1245, /* l a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0x21ab _ 0) -NAMED_CHARACTER_REFERENCE(1246, /* l a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0x2939 _ 0) -NAMED_CHARACTER_REFERENCE(1247, /* l a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2973 _ 0) -NAMED_CHARACTER_REFERENCE(1248, /* l a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0x21a2 _ 0) -NAMED_CHARACTER_REFERENCE(1249, /* l a */ 't' _ ';', 2, 0x2aab _ 0) -NAMED_CHARACTER_REFERENCE(1250, /* l a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x2919 _ 0) -NAMED_CHARACTER_REFERENCE(1251, /* l a */ 't' _ 'e' _ ';', 3, 0x2aad _ 0) -NAMED_CHARACTER_REFERENCE(1252, /* l b */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290c _ 0) -NAMED_CHARACTER_REFERENCE(1253, /* l b */ 'b' _ 'r' _ 'k' _ ';', 4, 0x2772 _ 0) -NAMED_CHARACTER_REFERENCE(1254, /* l b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0x007b _ 0) -NAMED_CHARACTER_REFERENCE(1255, /* l b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0x005b _ 0) -NAMED_CHARACTER_REFERENCE(1256, /* l b */ 'r' _ 'k' _ 'e' _ ';', 4, 0x298b _ 0) -NAMED_CHARACTER_REFERENCE(1257, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0x298f _ 0) -NAMED_CHARACTER_REFERENCE(1258, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0x298d _ 0) -NAMED_CHARACTER_REFERENCE(1259, /* l c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x013e _ 0) -NAMED_CHARACTER_REFERENCE(1260, /* l c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x013c _ 0) -NAMED_CHARACTER_REFERENCE(1261, /* l c */ 'e' _ 'i' _ 'l' _ ';', 4, 0x2308 _ 0) -NAMED_CHARACTER_REFERENCE(1262, /* l c */ 'u' _ 'b' _ ';', 3, 0x007b _ 0) -NAMED_CHARACTER_REFERENCE(1263, /* l c */ 'y' _ ';', 2, 0x043b _ 0) -NAMED_CHARACTER_REFERENCE(1264, /* l d */ 'c' _ 'a' _ ';', 3, 0x2936 _ 0) -NAMED_CHARACTER_REFERENCE(1265, /* l d */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201c _ 0) -NAMED_CHARACTER_REFERENCE(1266, /* l d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x201e _ 0) -NAMED_CHARACTER_REFERENCE(1267, /* l d */ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2967 _ 0) -NAMED_CHARACTER_REFERENCE(1268, /* l d */ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0x294b _ 0) -NAMED_CHARACTER_REFERENCE(1269, /* l d */ 's' _ 'h' _ ';', 3, 0x21b2 _ 0) -NAMED_CHARACTER_REFERENCE(1270, /* l e */ ';', 1, 0x2264 _ 0) -NAMED_CHARACTER_REFERENCE(1271, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(1272, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 12, 0x21a2 _ 0) -NAMED_CHARACTER_REFERENCE(1273, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0x21bd _ 0) -NAMED_CHARACTER_REFERENCE(1274, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 12, 0x21bc _ 0) -NAMED_CHARACTER_REFERENCE(1275, /* l e */ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0x21c7 _ 0) -NAMED_CHARACTER_REFERENCE(1276, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x2194 _ 0) -NAMED_CHARACTER_REFERENCE(1277, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0x21c6 _ 0) -NAMED_CHARACTER_REFERENCE(1278, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0x21cb _ 0) -NAMED_CHARACTER_REFERENCE(1279, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0x21ad _ 0) -NAMED_CHARACTER_REFERENCE(1280, /* l e */ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0x22cb _ 0) -NAMED_CHARACTER_REFERENCE(1281, /* l e */ 'g' _ ';', 2, 0x22da _ 0) -NAMED_CHARACTER_REFERENCE(1282, /* l e */ 'q' _ ';', 2, 0x2264 _ 0) -NAMED_CHARACTER_REFERENCE(1283, /* l e */ 'q' _ 'q' _ ';', 3, 0x2266 _ 0) -NAMED_CHARACTER_REFERENCE(1284, /* l e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0x2a7d _ 0) -NAMED_CHARACTER_REFERENCE(1285, /* l e */ 's' _ ';', 2, 0x2a7d _ 0) -NAMED_CHARACTER_REFERENCE(1286, /* l e */ 's' _ 'c' _ 'c' _ ';', 4, 0x2aa8 _ 0) -NAMED_CHARACTER_REFERENCE(1287, /* l e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a7f _ 0) -NAMED_CHARACTER_REFERENCE(1288, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0x2a81 _ 0) -NAMED_CHARACTER_REFERENCE(1289, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 7, 0x2a83 _ 0) -NAMED_CHARACTER_REFERENCE(1290, /* l e */ 's' _ 'g' _ 'e' _ 's' _ ';', 5, 0x2a93 _ 0) -NAMED_CHARACTER_REFERENCE(1291, /* l e */ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2a85 _ 0) -NAMED_CHARACTER_REFERENCE(1292, /* l e */ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0x22d6 _ 0) -NAMED_CHARACTER_REFERENCE(1293, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 8, 0x22da _ 0) -NAMED_CHARACTER_REFERENCE(1294, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 9, 0x2a8b _ 0) -NAMED_CHARACTER_REFERENCE(1295, /* l e */ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 6, 0x2276 _ 0) -NAMED_CHARACTER_REFERENCE(1296, /* l e */ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2272 _ 0) -NAMED_CHARACTER_REFERENCE(1297, /* l f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297c _ 0) -NAMED_CHARACTER_REFERENCE(1298, /* l f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0x230a _ 0) -NAMED_CHARACTER_REFERENCE(1299, /* l f */ 'r' _ ';', 2, 0xd835 _ 0xdd29) -NAMED_CHARACTER_REFERENCE(1300, /* l g */ ';', 1, 0x2276 _ 0) -NAMED_CHARACTER_REFERENCE(1301, /* l g */ 'E' _ ';', 2, 0x2a91 _ 0) -NAMED_CHARACTER_REFERENCE(1302, /* l h */ 'a' _ 'r' _ 'd' _ ';', 4, 0x21bd _ 0) -NAMED_CHARACTER_REFERENCE(1303, /* l h */ 'a' _ 'r' _ 'u' _ ';', 4, 0x21bc _ 0) -NAMED_CHARACTER_REFERENCE(1304, /* l h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0x296a _ 0) -NAMED_CHARACTER_REFERENCE(1305, /* l h */ 'b' _ 'l' _ 'k' _ ';', 4, 0x2584 _ 0) -NAMED_CHARACTER_REFERENCE(1306, /* l j */ 'c' _ 'y' _ ';', 3, 0x0459 _ 0) -NAMED_CHARACTER_REFERENCE(1307, /* l l */ ';', 1, 0x226a _ 0) -NAMED_CHARACTER_REFERENCE(1308, /* l l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c7 _ 0) -NAMED_CHARACTER_REFERENCE(1309, /* l l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231e _ 0) -NAMED_CHARACTER_REFERENCE(1310, /* l l */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0x296b _ 0) -NAMED_CHARACTER_REFERENCE(1311, /* l l */ 't' _ 'r' _ 'i' _ ';', 4, 0x25fa _ 0) -NAMED_CHARACTER_REFERENCE(1312, /* l m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0x0140 _ 0) -NAMED_CHARACTER_REFERENCE(1313, /* l m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0x23b0 _ 0) -NAMED_CHARACTER_REFERENCE(1314, /* l m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0x23b0 _ 0) -NAMED_CHARACTER_REFERENCE(1315, /* l n */ 'E' _ ';', 2, 0x2268 _ 0) -NAMED_CHARACTER_REFERENCE(1316, /* l n */ 'a' _ 'p' _ ';', 3, 0x2a89 _ 0) -NAMED_CHARACTER_REFERENCE(1317, /* l n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0x2a89 _ 0) -NAMED_CHARACTER_REFERENCE(1318, /* l n */ 'e' _ ';', 2, 0x2a87 _ 0) -NAMED_CHARACTER_REFERENCE(1319, /* l n */ 'e' _ 'q' _ ';', 3, 0x2a87 _ 0) -NAMED_CHARACTER_REFERENCE(1320, /* l n */ 'e' _ 'q' _ 'q' _ ';', 4, 0x2268 _ 0) -NAMED_CHARACTER_REFERENCE(1321, /* l n */ 's' _ 'i' _ 'm' _ ';', 4, 0x22e6 _ 0) -NAMED_CHARACTER_REFERENCE(1322, /* l o */ 'a' _ 'n' _ 'g' _ ';', 4, 0x27ec _ 0) -NAMED_CHARACTER_REFERENCE(1323, /* l o */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21fd _ 0) -NAMED_CHARACTER_REFERENCE(1324, /* l o */ 'b' _ 'r' _ 'k' _ ';', 4, 0x27e6 _ 0) -NAMED_CHARACTER_REFERENCE(1325, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0x27f5 _ 0) -NAMED_CHARACTER_REFERENCE(1326, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0x27f7 _ 0) -NAMED_CHARACTER_REFERENCE(1327, /* l o */ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 9, 0x27fc _ 0) -NAMED_CHARACTER_REFERENCE(1328, /* l o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0x27f6 _ 0) -NAMED_CHARACTER_REFERENCE(1329, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0x21ab _ 0) -NAMED_CHARACTER_REFERENCE(1330, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0x21ac _ 0) -NAMED_CHARACTER_REFERENCE(1331, /* l o */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2985 _ 0) -NAMED_CHARACTER_REFERENCE(1332, /* l o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5d) -NAMED_CHARACTER_REFERENCE(1333, /* l o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a2d _ 0) -NAMED_CHARACTER_REFERENCE(1334, /* l o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0x2a34 _ 0) -NAMED_CHARACTER_REFERENCE(1335, /* l o */ 'w' _ 'a' _ 's' _ 't' _ ';', 5, 0x2217 _ 0) -NAMED_CHARACTER_REFERENCE(1336, /* l o */ 'w' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x005f _ 0) -NAMED_CHARACTER_REFERENCE(1337, /* l o */ 'z' _ ';', 2, 0x25ca _ 0) -NAMED_CHARACTER_REFERENCE(1338, /* l o */ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 6, 0x25ca _ 0) -NAMED_CHARACTER_REFERENCE(1339, /* l o */ 'z' _ 'f' _ ';', 3, 0x29eb _ 0) -NAMED_CHARACTER_REFERENCE(1340, /* l p */ 'a' _ 'r' _ ';', 3, 0x0028 _ 0) -NAMED_CHARACTER_REFERENCE(1341, /* l p */ 'a' _ 'r' _ 'l' _ 't' _ ';', 5, 0x2993 _ 0) -NAMED_CHARACTER_REFERENCE(1342, /* l r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c6 _ 0) -NAMED_CHARACTER_REFERENCE(1343, /* l r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231f _ 0) -NAMED_CHARACTER_REFERENCE(1344, /* l r */ 'h' _ 'a' _ 'r' _ ';', 4, 0x21cb _ 0) -NAMED_CHARACTER_REFERENCE(1345, /* l r */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0x296d _ 0) -NAMED_CHARACTER_REFERENCE(1346, /* l r */ 'm' _ ';', 2, 0x200e _ 0) -NAMED_CHARACTER_REFERENCE(1347, /* l r */ 't' _ 'r' _ 'i' _ ';', 4, 0x22bf _ 0) -NAMED_CHARACTER_REFERENCE(1348, /* l s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0x2039 _ 0) -NAMED_CHARACTER_REFERENCE(1349, /* l s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc1) -NAMED_CHARACTER_REFERENCE(1350, /* l s */ 'h' _ ';', 2, 0x21b0 _ 0) -NAMED_CHARACTER_REFERENCE(1351, /* l s */ 'i' _ 'm' _ ';', 3, 0x2272 _ 0) -NAMED_CHARACTER_REFERENCE(1352, /* l s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2a8d _ 0) -NAMED_CHARACTER_REFERENCE(1353, /* l s */ 'i' _ 'm' _ 'g' _ ';', 4, 0x2a8f _ 0) -NAMED_CHARACTER_REFERENCE(1354, /* l s */ 'q' _ 'b' _ ';', 3, 0x005b _ 0) -NAMED_CHARACTER_REFERENCE(1355, /* l s */ 'q' _ 'u' _ 'o' _ ';', 4, 0x2018 _ 0) -NAMED_CHARACTER_REFERENCE(1356, /* l s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x201a _ 0) -NAMED_CHARACTER_REFERENCE(1357, /* l s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0142 _ 0) -NAMED_CHARACTER_REFERENCE(1358, /* l t */ 0, 0, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(1359, /* l t */ ';', 1, 0x003c _ 0) -NAMED_CHARACTER_REFERENCE(1360, /* l t */ 'c' _ 'c' _ ';', 3, 0x2aa6 _ 0) -NAMED_CHARACTER_REFERENCE(1361, /* l t */ 'c' _ 'i' _ 'r' _ ';', 4, 0x2a79 _ 0) -NAMED_CHARACTER_REFERENCE(1362, /* l t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22d6 _ 0) -NAMED_CHARACTER_REFERENCE(1363, /* l t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0x22cb _ 0) -NAMED_CHARACTER_REFERENCE(1364, /* l t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x22c9 _ 0) -NAMED_CHARACTER_REFERENCE(1365, /* l t */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2976 _ 0) -NAMED_CHARACTER_REFERENCE(1366, /* l t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0x2a7b _ 0) -NAMED_CHARACTER_REFERENCE(1367, /* l t */ 'r' _ 'P' _ 'a' _ 'r' _ ';', 5, 0x2996 _ 0) -NAMED_CHARACTER_REFERENCE(1368, /* l t */ 'r' _ 'i' _ ';', 3, 0x25c3 _ 0) -NAMED_CHARACTER_REFERENCE(1369, /* l t */ 'r' _ 'i' _ 'e' _ ';', 4, 0x22b4 _ 0) -NAMED_CHARACTER_REFERENCE(1370, /* l t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25c2 _ 0) -NAMED_CHARACTER_REFERENCE(1371, /* l u */ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0x294a _ 0) -NAMED_CHARACTER_REFERENCE(1372, /* l u */ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2966 _ 0) -NAMED_CHARACTER_REFERENCE(1373, /* m D */ 'D' _ 'o' _ 't' _ ';', 4, 0x223a _ 0) -NAMED_CHARACTER_REFERENCE(1374, /* m a */ 'c' _ 'r', 2, 0x00af _ 0) -NAMED_CHARACTER_REFERENCE(1375, /* m a */ 'c' _ 'r' _ ';', 3, 0x00af _ 0) -NAMED_CHARACTER_REFERENCE(1376, /* m a */ 'l' _ 'e' _ ';', 3, 0x2642 _ 0) -NAMED_CHARACTER_REFERENCE(1377, /* m a */ 'l' _ 't' _ ';', 3, 0x2720 _ 0) -NAMED_CHARACTER_REFERENCE(1378, /* m a */ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 6, 0x2720 _ 0) -NAMED_CHARACTER_REFERENCE(1379, /* m a */ 'p' _ ';', 2, 0x21a6 _ 0) -NAMED_CHARACTER_REFERENCE(1380, /* m a */ 'p' _ 's' _ 't' _ 'o' _ ';', 5, 0x21a6 _ 0) -NAMED_CHARACTER_REFERENCE(1381, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 9, 0x21a7 _ 0) -NAMED_CHARACTER_REFERENCE(1382, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 9, 0x21a4 _ 0) -NAMED_CHARACTER_REFERENCE(1383, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 7, 0x21a5 _ 0) -NAMED_CHARACTER_REFERENCE(1384, /* m a */ 'r' _ 'k' _ 'e' _ 'r' _ ';', 5, 0x25ae _ 0) -NAMED_CHARACTER_REFERENCE(1385, /* m c */ 'o' _ 'm' _ 'm' _ 'a' _ ';', 5, 0x2a29 _ 0) -NAMED_CHARACTER_REFERENCE(1386, /* m c */ 'y' _ ';', 2, 0x043c _ 0) -NAMED_CHARACTER_REFERENCE(1387, /* m d */ 'a' _ 's' _ 'h' _ ';', 4, 0x2014 _ 0) -NAMED_CHARACTER_REFERENCE(1388, /* m e */ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0x2221 _ 0) -NAMED_CHARACTER_REFERENCE(1389, /* m f */ 'r' _ ';', 2, 0xd835 _ 0xdd2a) -NAMED_CHARACTER_REFERENCE(1390, /* m h */ 'o' _ ';', 2, 0x2127 _ 0) -NAMED_CHARACTER_REFERENCE(1391, /* m i */ 'c' _ 'r' _ 'o', 3, 0x00b5 _ 0) -NAMED_CHARACTER_REFERENCE(1392, /* m i */ 'c' _ 'r' _ 'o' _ ';', 4, 0x00b5 _ 0) -NAMED_CHARACTER_REFERENCE(1393, /* m i */ 'd' _ ';', 2, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(1394, /* m i */ 'd' _ 'a' _ 's' _ 't' _ ';', 5, 0x002a _ 0) -NAMED_CHARACTER_REFERENCE(1395, /* m i */ 'd' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2af0 _ 0) -NAMED_CHARACTER_REFERENCE(1396, /* m i */ 'd' _ 'd' _ 'o' _ 't', 4, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(1397, /* m i */ 'd' _ 'd' _ 'o' _ 't' _ ';', 5, 0x00b7 _ 0) -NAMED_CHARACTER_REFERENCE(1398, /* m i */ 'n' _ 'u' _ 's' _ ';', 4, 0x2212 _ 0) -NAMED_CHARACTER_REFERENCE(1399, /* m i */ 'n' _ 'u' _ 's' _ 'b' _ ';', 5, 0x229f _ 0) -NAMED_CHARACTER_REFERENCE(1400, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ ';', 5, 0x2238 _ 0) -NAMED_CHARACTER_REFERENCE(1401, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 6, 0x2a2a _ 0) -NAMED_CHARACTER_REFERENCE(1402, /* m l */ 'c' _ 'p' _ ';', 3, 0x2adb _ 0) -NAMED_CHARACTER_REFERENCE(1403, /* m l */ 'd' _ 'r' _ ';', 3, 0x2026 _ 0) -NAMED_CHARACTER_REFERENCE(1404, /* m n */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2213 _ 0) -NAMED_CHARACTER_REFERENCE(1405, /* m o */ 'd' _ 'e' _ 'l' _ 's' _ ';', 5, 0x22a7 _ 0) -NAMED_CHARACTER_REFERENCE(1406, /* m o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5e) -NAMED_CHARACTER_REFERENCE(1407, /* m p */ ';', 1, 0x2213 _ 0) -NAMED_CHARACTER_REFERENCE(1408, /* m s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc2) -NAMED_CHARACTER_REFERENCE(1409, /* m s */ 't' _ 'p' _ 'o' _ 's' _ ';', 5, 0x223e _ 0) -NAMED_CHARACTER_REFERENCE(1410, /* m u */ ';', 1, 0x03bc _ 0) -NAMED_CHARACTER_REFERENCE(1411, /* m u */ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 7, 0x22b8 _ 0) -NAMED_CHARACTER_REFERENCE(1412, /* m u */ 'm' _ 'a' _ 'p' _ ';', 4, 0x22b8 _ 0) -NAMED_CHARACTER_REFERENCE(1413, /* n L */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x21cd _ 0) -NAMED_CHARACTER_REFERENCE(1414, /* n L */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21ce _ 0) -NAMED_CHARACTER_REFERENCE(1415, /* n R */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x21cf _ 0) -NAMED_CHARACTER_REFERENCE(1416, /* n V */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22af _ 0) -NAMED_CHARACTER_REFERENCE(1417, /* n V */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22ae _ 0) -NAMED_CHARACTER_REFERENCE(1418, /* n a */ 'b' _ 'l' _ 'a' _ ';', 4, 0x2207 _ 0) -NAMED_CHARACTER_REFERENCE(1419, /* n a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0144 _ 0) -NAMED_CHARACTER_REFERENCE(1420, /* n a */ 'p' _ ';', 2, 0x2249 _ 0) -NAMED_CHARACTER_REFERENCE(1421, /* n a */ 'p' _ 'o' _ 's' _ ';', 4, 0x0149 _ 0) -NAMED_CHARACTER_REFERENCE(1422, /* n a */ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 6, 0x2249 _ 0) -NAMED_CHARACTER_REFERENCE(1423, /* n a */ 't' _ 'u' _ 'r' _ ';', 4, 0x266e _ 0) -NAMED_CHARACTER_REFERENCE(1424, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 6, 0x266e _ 0) -NAMED_CHARACTER_REFERENCE(1425, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 7, 0x2115 _ 0) -NAMED_CHARACTER_REFERENCE(1426, /* n b */ 's' _ 'p', 2, 0x00a0 _ 0) -NAMED_CHARACTER_REFERENCE(1427, /* n b */ 's' _ 'p' _ ';', 3, 0x00a0 _ 0) -NAMED_CHARACTER_REFERENCE(1428, /* n c */ 'a' _ 'p' _ ';', 3, 0x2a43 _ 0) -NAMED_CHARACTER_REFERENCE(1429, /* n c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0148 _ 0) -NAMED_CHARACTER_REFERENCE(1430, /* n c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0146 _ 0) -NAMED_CHARACTER_REFERENCE(1431, /* n c */ 'o' _ 'n' _ 'g' _ ';', 4, 0x2247 _ 0) -NAMED_CHARACTER_REFERENCE(1432, /* n c */ 'u' _ 'p' _ ';', 3, 0x2a42 _ 0) -NAMED_CHARACTER_REFERENCE(1433, /* n c */ 'y' _ ';', 2, 0x043d _ 0) -NAMED_CHARACTER_REFERENCE(1434, /* n d */ 'a' _ 's' _ 'h' _ ';', 4, 0x2013 _ 0) -NAMED_CHARACTER_REFERENCE(1435, /* n e */ ';', 1, 0x2260 _ 0) -NAMED_CHARACTER_REFERENCE(1436, /* n e */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d7 _ 0) -NAMED_CHARACTER_REFERENCE(1437, /* n e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2924 _ 0) -NAMED_CHARACTER_REFERENCE(1438, /* n e */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2197 _ 0) -NAMED_CHARACTER_REFERENCE(1439, /* n e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2197 _ 0) -NAMED_CHARACTER_REFERENCE(1440, /* n e */ 'q' _ 'u' _ 'i' _ 'v' _ ';', 5, 0x2262 _ 0) -NAMED_CHARACTER_REFERENCE(1441, /* n e */ 's' _ 'e' _ 'a' _ 'r' _ ';', 5, 0x2928 _ 0) -NAMED_CHARACTER_REFERENCE(1442, /* n e */ 'x' _ 'i' _ 's' _ 't' _ ';', 5, 0x2204 _ 0) -NAMED_CHARACTER_REFERENCE(1443, /* n e */ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 6, 0x2204 _ 0) -NAMED_CHARACTER_REFERENCE(1444, /* n f */ 'r' _ ';', 2, 0xd835 _ 0xdd2b) -NAMED_CHARACTER_REFERENCE(1445, /* n g */ 'e' _ ';', 2, 0x2271 _ 0) -NAMED_CHARACTER_REFERENCE(1446, /* n g */ 'e' _ 'q' _ ';', 3, 0x2271 _ 0) -NAMED_CHARACTER_REFERENCE(1447, /* n g */ 's' _ 'i' _ 'm' _ ';', 4, 0x2275 _ 0) -NAMED_CHARACTER_REFERENCE(1448, /* n g */ 't' _ ';', 2, 0x226f _ 0) -NAMED_CHARACTER_REFERENCE(1449, /* n g */ 't' _ 'r' _ ';', 3, 0x226f _ 0) -NAMED_CHARACTER_REFERENCE(1450, /* n h */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21ce _ 0) -NAMED_CHARACTER_REFERENCE(1451, /* n h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ae _ 0) -NAMED_CHARACTER_REFERENCE(1452, /* n h */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2af2 _ 0) -NAMED_CHARACTER_REFERENCE(1453, /* n i */ ';', 1, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(1454, /* n i */ 's' _ ';', 2, 0x22fc _ 0) -NAMED_CHARACTER_REFERENCE(1455, /* n i */ 's' _ 'd' _ ';', 3, 0x22fa _ 0) -NAMED_CHARACTER_REFERENCE(1456, /* n i */ 'v' _ ';', 2, 0x220b _ 0) -NAMED_CHARACTER_REFERENCE(1457, /* n j */ 'c' _ 'y' _ ';', 3, 0x045a _ 0) -NAMED_CHARACTER_REFERENCE(1458, /* n l */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21cd _ 0) -NAMED_CHARACTER_REFERENCE(1459, /* n l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x219a _ 0) -NAMED_CHARACTER_REFERENCE(1460, /* n l */ 'd' _ 'r' _ ';', 3, 0x2025 _ 0) -NAMED_CHARACTER_REFERENCE(1461, /* n l */ 'e' _ ';', 2, 0x2270 _ 0) -NAMED_CHARACTER_REFERENCE(1462, /* n l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x219a _ 0) -NAMED_CHARACTER_REFERENCE(1463, /* n l */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x21ae _ 0) -NAMED_CHARACTER_REFERENCE(1464, /* n l */ 'e' _ 'q' _ ';', 3, 0x2270 _ 0) -NAMED_CHARACTER_REFERENCE(1465, /* n l */ 'e' _ 's' _ 's' _ ';', 4, 0x226e _ 0) -NAMED_CHARACTER_REFERENCE(1466, /* n l */ 's' _ 'i' _ 'm' _ ';', 4, 0x2274 _ 0) -NAMED_CHARACTER_REFERENCE(1467, /* n l */ 't' _ ';', 2, 0x226e _ 0) -NAMED_CHARACTER_REFERENCE(1468, /* n l */ 't' _ 'r' _ 'i' _ ';', 4, 0x22ea _ 0) -NAMED_CHARACTER_REFERENCE(1469, /* n l */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0x22ec _ 0) -NAMED_CHARACTER_REFERENCE(1470, /* n m */ 'i' _ 'd' _ ';', 3, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(1471, /* n o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd5f) -NAMED_CHARACTER_REFERENCE(1472, /* n o */ 't', 1, 0x00ac _ 0) -NAMED_CHARACTER_REFERENCE(1473, /* n o */ 't' _ ';', 2, 0x00ac _ 0) -NAMED_CHARACTER_REFERENCE(1474, /* n o */ 't' _ 'i' _ 'n' _ ';', 4, 0x2209 _ 0) -NAMED_CHARACTER_REFERENCE(1475, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 6, 0x2209 _ 0) -NAMED_CHARACTER_REFERENCE(1476, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 6, 0x22f7 _ 0) -NAMED_CHARACTER_REFERENCE(1477, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 6, 0x22f6 _ 0) -NAMED_CHARACTER_REFERENCE(1478, /* n o */ 't' _ 'n' _ 'i' _ ';', 4, 0x220c _ 0) -NAMED_CHARACTER_REFERENCE(1479, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 6, 0x220c _ 0) -NAMED_CHARACTER_REFERENCE(1480, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 6, 0x22fe _ 0) -NAMED_CHARACTER_REFERENCE(1481, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 6, 0x22fd _ 0) -NAMED_CHARACTER_REFERENCE(1482, /* n p */ 'a' _ 'r' _ ';', 3, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1483, /* n p */ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 8, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1484, /* n p */ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2a14 _ 0) -NAMED_CHARACTER_REFERENCE(1485, /* n p */ 'r' _ ';', 2, 0x2280 _ 0) -NAMED_CHARACTER_REFERENCE(1486, /* n p */ 'r' _ 'c' _ 'u' _ 'e' _ ';', 5, 0x22e0 _ 0) -NAMED_CHARACTER_REFERENCE(1487, /* n p */ 'r' _ 'e' _ 'c' _ ';', 4, 0x2280 _ 0) -NAMED_CHARACTER_REFERENCE(1488, /* n r */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21cf _ 0) -NAMED_CHARACTER_REFERENCE(1489, /* n r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x219b _ 0) -NAMED_CHARACTER_REFERENCE(1490, /* n r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x219b _ 0) -NAMED_CHARACTER_REFERENCE(1491, /* n r */ 't' _ 'r' _ 'i' _ ';', 4, 0x22eb _ 0) -NAMED_CHARACTER_REFERENCE(1492, /* n r */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0x22ed _ 0) -NAMED_CHARACTER_REFERENCE(1493, /* n s */ 'c' _ ';', 2, 0x2281 _ 0) -NAMED_CHARACTER_REFERENCE(1494, /* n s */ 'c' _ 'c' _ 'u' _ 'e' _ ';', 5, 0x22e1 _ 0) -NAMED_CHARACTER_REFERENCE(1495, /* n s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc3) -NAMED_CHARACTER_REFERENCE(1496, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 8, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(1497, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 13, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1498, /* n s */ 'i' _ 'm' _ ';', 3, 0x2241 _ 0) -NAMED_CHARACTER_REFERENCE(1499, /* n s */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2244 _ 0) -NAMED_CHARACTER_REFERENCE(1500, /* n s */ 'i' _ 'm' _ 'e' _ 'q' _ ';', 5, 0x2244 _ 0) -NAMED_CHARACTER_REFERENCE(1501, /* n s */ 'm' _ 'i' _ 'd' _ ';', 4, 0x2224 _ 0) -NAMED_CHARACTER_REFERENCE(1502, /* n s */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2226 _ 0) -NAMED_CHARACTER_REFERENCE(1503, /* n s */ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0x22e2 _ 0) -NAMED_CHARACTER_REFERENCE(1504, /* n s */ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0x22e3 _ 0) -NAMED_CHARACTER_REFERENCE(1505, /* n s */ 'u' _ 'b' _ ';', 3, 0x2284 _ 0) -NAMED_CHARACTER_REFERENCE(1506, /* n s */ 'u' _ 'b' _ 'e' _ ';', 4, 0x2288 _ 0) -NAMED_CHARACTER_REFERENCE(1507, /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0x2288 _ 0) -NAMED_CHARACTER_REFERENCE(1508, /* n s */ 'u' _ 'c' _ 'c' _ ';', 4, 0x2281 _ 0) -NAMED_CHARACTER_REFERENCE(1509, /* n s */ 'u' _ 'p' _ ';', 3, 0x2285 _ 0) -NAMED_CHARACTER_REFERENCE(1510, /* n s */ 'u' _ 'p' _ 'e' _ ';', 4, 0x2289 _ 0) -NAMED_CHARACTER_REFERENCE(1511, /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0x2289 _ 0) -NAMED_CHARACTER_REFERENCE(1512, /* n t */ 'g' _ 'l' _ ';', 3, 0x2279 _ 0) -NAMED_CHARACTER_REFERENCE(1513, /* n t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00f1 _ 0) -NAMED_CHARACTER_REFERENCE(1514, /* n t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00f1 _ 0) -NAMED_CHARACTER_REFERENCE(1515, /* n t */ 'l' _ 'g' _ ';', 3, 0x2278 _ 0) -NAMED_CHARACTER_REFERENCE(1516, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0x22ea _ 0) -NAMED_CHARACTER_REFERENCE(1517, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 14, 0x22ec _ 0) -NAMED_CHARACTER_REFERENCE(1518, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0x22eb _ 0) -NAMED_CHARACTER_REFERENCE(1519, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 15, 0x22ed _ 0) -NAMED_CHARACTER_REFERENCE(1520, /* n u */ ';', 1, 0x03bd _ 0) -NAMED_CHARACTER_REFERENCE(1521, /* n u */ 'm' _ ';', 2, 0x0023 _ 0) -NAMED_CHARACTER_REFERENCE(1522, /* n u */ 'm' _ 'e' _ 'r' _ 'o' _ ';', 5, 0x2116 _ 0) -NAMED_CHARACTER_REFERENCE(1523, /* n u */ 'm' _ 's' _ 'p' _ ';', 4, 0x2007 _ 0) -NAMED_CHARACTER_REFERENCE(1524, /* n v */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22ad _ 0) -NAMED_CHARACTER_REFERENCE(1525, /* n v */ 'H' _ 'a' _ 'r' _ 'r' _ ';', 5, 0x2904 _ 0) -NAMED_CHARACTER_REFERENCE(1526, /* n v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0x22ac _ 0) -NAMED_CHARACTER_REFERENCE(1527, /* n v */ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0x29de _ 0) -NAMED_CHARACTER_REFERENCE(1528, /* n v */ 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x2902 _ 0) -NAMED_CHARACTER_REFERENCE(1529, /* n v */ 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0x2903 _ 0) -NAMED_CHARACTER_REFERENCE(1530, /* n w */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d6 _ 0) -NAMED_CHARACTER_REFERENCE(1531, /* n w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2923 _ 0) -NAMED_CHARACTER_REFERENCE(1532, /* n w */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2196 _ 0) -NAMED_CHARACTER_REFERENCE(1533, /* n w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2196 _ 0) -NAMED_CHARACTER_REFERENCE(1534, /* n w */ 'n' _ 'e' _ 'a' _ 'r' _ ';', 5, 0x2927 _ 0) -NAMED_CHARACTER_REFERENCE(1535, /* o S */ ';', 1, 0x24c8 _ 0) -NAMED_CHARACTER_REFERENCE(1536, /* o a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00f3 _ 0) -NAMED_CHARACTER_REFERENCE(1537, /* o a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00f3 _ 0) -NAMED_CHARACTER_REFERENCE(1538, /* o a */ 's' _ 't' _ ';', 3, 0x229b _ 0) -NAMED_CHARACTER_REFERENCE(1539, /* o c */ 'i' _ 'r' _ ';', 3, 0x229a _ 0) -NAMED_CHARACTER_REFERENCE(1540, /* o c */ 'i' _ 'r' _ 'c', 3, 0x00f4 _ 0) -NAMED_CHARACTER_REFERENCE(1541, /* o c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00f4 _ 0) -NAMED_CHARACTER_REFERENCE(1542, /* o c */ 'y' _ ';', 2, 0x043e _ 0) -NAMED_CHARACTER_REFERENCE(1543, /* o d */ 'a' _ 's' _ 'h' _ ';', 4, 0x229d _ 0) -NAMED_CHARACTER_REFERENCE(1544, /* o d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0151 _ 0) -NAMED_CHARACTER_REFERENCE(1545, /* o d */ 'i' _ 'v' _ ';', 3, 0x2a38 _ 0) -NAMED_CHARACTER_REFERENCE(1546, /* o d */ 'o' _ 't' _ ';', 3, 0x2299 _ 0) -NAMED_CHARACTER_REFERENCE(1547, /* o d */ 's' _ 'o' _ 'l' _ 'd' _ ';', 5, 0x29bc _ 0) -NAMED_CHARACTER_REFERENCE(1548, /* o e */ 'l' _ 'i' _ 'g' _ ';', 4, 0x0153 _ 0) -NAMED_CHARACTER_REFERENCE(1549, /* o f */ 'c' _ 'i' _ 'r' _ ';', 4, 0x29bf _ 0) -NAMED_CHARACTER_REFERENCE(1550, /* o f */ 'r' _ ';', 2, 0xd835 _ 0xdd2c) -NAMED_CHARACTER_REFERENCE(1551, /* o g */ 'o' _ 'n' _ ';', 3, 0x02db _ 0) -NAMED_CHARACTER_REFERENCE(1552, /* o g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00f2 _ 0) -NAMED_CHARACTER_REFERENCE(1553, /* o g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00f2 _ 0) -NAMED_CHARACTER_REFERENCE(1554, /* o g */ 't' _ ';', 2, 0x29c1 _ 0) -NAMED_CHARACTER_REFERENCE(1555, /* o h */ 'b' _ 'a' _ 'r' _ ';', 4, 0x29b5 _ 0) -NAMED_CHARACTER_REFERENCE(1556, /* o h */ 'm' _ ';', 2, 0x03a9 _ 0) -NAMED_CHARACTER_REFERENCE(1557, /* o i */ 'n' _ 't' _ ';', 3, 0x222e _ 0) -NAMED_CHARACTER_REFERENCE(1558, /* o l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21ba _ 0) -NAMED_CHARACTER_REFERENCE(1559, /* o l */ 'c' _ 'i' _ 'r' _ ';', 4, 0x29be _ 0) -NAMED_CHARACTER_REFERENCE(1560, /* o l */ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0x29bb _ 0) -NAMED_CHARACTER_REFERENCE(1561, /* o l */ 'i' _ 'n' _ 'e' _ ';', 4, 0x203e _ 0) -NAMED_CHARACTER_REFERENCE(1562, /* o l */ 't' _ ';', 2, 0x29c0 _ 0) -NAMED_CHARACTER_REFERENCE(1563, /* o m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x014d _ 0) -NAMED_CHARACTER_REFERENCE(1564, /* o m */ 'e' _ 'g' _ 'a' _ ';', 4, 0x03c9 _ 0) -NAMED_CHARACTER_REFERENCE(1565, /* o m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0x03bf _ 0) -NAMED_CHARACTER_REFERENCE(1566, /* o m */ 'i' _ 'd' _ ';', 3, 0x29b6 _ 0) -NAMED_CHARACTER_REFERENCE(1567, /* o m */ 'i' _ 'n' _ 'u' _ 's' _ ';', 5, 0x2296 _ 0) -NAMED_CHARACTER_REFERENCE(1568, /* o o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd60) -NAMED_CHARACTER_REFERENCE(1569, /* o p */ 'a' _ 'r' _ ';', 3, 0x29b7 _ 0) -NAMED_CHARACTER_REFERENCE(1570, /* o p */ 'e' _ 'r' _ 'p' _ ';', 4, 0x29b9 _ 0) -NAMED_CHARACTER_REFERENCE(1571, /* o p */ 'l' _ 'u' _ 's' _ ';', 4, 0x2295 _ 0) -NAMED_CHARACTER_REFERENCE(1572, /* o r */ ';', 1, 0x2228 _ 0) -NAMED_CHARACTER_REFERENCE(1573, /* o r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21bb _ 0) -NAMED_CHARACTER_REFERENCE(1574, /* o r */ 'd' _ ';', 2, 0x2a5d _ 0) -NAMED_CHARACTER_REFERENCE(1575, /* o r */ 'd' _ 'e' _ 'r' _ ';', 4, 0x2134 _ 0) -NAMED_CHARACTER_REFERENCE(1576, /* o r */ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 6, 0x2134 _ 0) -NAMED_CHARACTER_REFERENCE(1577, /* o r */ 'd' _ 'f', 2, 0x00aa _ 0) -NAMED_CHARACTER_REFERENCE(1578, /* o r */ 'd' _ 'f' _ ';', 3, 0x00aa _ 0) -NAMED_CHARACTER_REFERENCE(1579, /* o r */ 'd' _ 'm', 2, 0x00ba _ 0) -NAMED_CHARACTER_REFERENCE(1580, /* o r */ 'd' _ 'm' _ ';', 3, 0x00ba _ 0) -NAMED_CHARACTER_REFERENCE(1581, /* o r */ 'i' _ 'g' _ 'o' _ 'f' _ ';', 5, 0x22b6 _ 0) -NAMED_CHARACTER_REFERENCE(1582, /* o r */ 'o' _ 'r' _ ';', 3, 0x2a56 _ 0) -NAMED_CHARACTER_REFERENCE(1583, /* o r */ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 6, 0x2a57 _ 0) -NAMED_CHARACTER_REFERENCE(1584, /* o r */ 'v' _ ';', 2, 0x2a5b _ 0) -NAMED_CHARACTER_REFERENCE(1585, /* o s */ 'c' _ 'r' _ ';', 3, 0x2134 _ 0) -NAMED_CHARACTER_REFERENCE(1586, /* o s */ 'l' _ 'a' _ 's' _ 'h', 4, 0x00f8 _ 0) -NAMED_CHARACTER_REFERENCE(1587, /* o s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0x00f8 _ 0) -NAMED_CHARACTER_REFERENCE(1588, /* o s */ 'o' _ 'l' _ ';', 3, 0x2298 _ 0) -NAMED_CHARACTER_REFERENCE(1589, /* o t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0x00f5 _ 0) -NAMED_CHARACTER_REFERENCE(1590, /* o t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x00f5 _ 0) -NAMED_CHARACTER_REFERENCE(1591, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x2297 _ 0) -NAMED_CHARACTER_REFERENCE(1592, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 7, 0x2a36 _ 0) -NAMED_CHARACTER_REFERENCE(1593, /* o u */ 'm' _ 'l', 2, 0x00f6 _ 0) -NAMED_CHARACTER_REFERENCE(1594, /* o u */ 'm' _ 'l' _ ';', 3, 0x00f6 _ 0) -NAMED_CHARACTER_REFERENCE(1595, /* o v */ 'b' _ 'a' _ 'r' _ ';', 4, 0x233d _ 0) -NAMED_CHARACTER_REFERENCE(1596, /* p a */ 'r' _ ';', 2, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1597, /* p a */ 'r' _ 'a', 2, 0x00b6 _ 0) -NAMED_CHARACTER_REFERENCE(1598, /* p a */ 'r' _ 'a' _ ';', 3, 0x00b6 _ 0) -NAMED_CHARACTER_REFERENCE(1599, /* p a */ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 7, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1600, /* p a */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2af3 _ 0) -NAMED_CHARACTER_REFERENCE(1601, /* p a */ 'r' _ 's' _ 'l' _ ';', 4, 0x2afd _ 0) -NAMED_CHARACTER_REFERENCE(1602, /* p a */ 'r' _ 't' _ ';', 3, 0x2202 _ 0) -NAMED_CHARACTER_REFERENCE(1603, /* p c */ 'y' _ ';', 2, 0x043f _ 0) -NAMED_CHARACTER_REFERENCE(1604, /* p e */ 'r' _ 'c' _ 'n' _ 't' _ ';', 5, 0x0025 _ 0) -NAMED_CHARACTER_REFERENCE(1605, /* p e */ 'r' _ 'i' _ 'o' _ 'd' _ ';', 5, 0x002e _ 0) -NAMED_CHARACTER_REFERENCE(1606, /* p e */ 'r' _ 'm' _ 'i' _ 'l' _ ';', 5, 0x2030 _ 0) -NAMED_CHARACTER_REFERENCE(1607, /* p e */ 'r' _ 'p' _ ';', 3, 0x22a5 _ 0) -NAMED_CHARACTER_REFERENCE(1608, /* p e */ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 6, 0x2031 _ 0) -NAMED_CHARACTER_REFERENCE(1609, /* p f */ 'r' _ ';', 2, 0xd835 _ 0xdd2d) -NAMED_CHARACTER_REFERENCE(1610, /* p h */ 'i' _ ';', 2, 0x03c6 _ 0) -NAMED_CHARACTER_REFERENCE(1611, /* p h */ 'i' _ 'v' _ ';', 3, 0x03d5 _ 0) -NAMED_CHARACTER_REFERENCE(1612, /* p h */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0x2133 _ 0) -NAMED_CHARACTER_REFERENCE(1613, /* p h */ 'o' _ 'n' _ 'e' _ ';', 4, 0x260e _ 0) -NAMED_CHARACTER_REFERENCE(1614, /* p i */ ';', 1, 0x03c0 _ 0) -NAMED_CHARACTER_REFERENCE(1615, /* p i */ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0x22d4 _ 0) -NAMED_CHARACTER_REFERENCE(1616, /* p i */ 'v' _ ';', 2, 0x03d6 _ 0) -NAMED_CHARACTER_REFERENCE(1617, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ ';', 5, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1618, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 6, 0x210e _ 0) -NAMED_CHARACTER_REFERENCE(1619, /* p l */ 'a' _ 'n' _ 'k' _ 'v' _ ';', 5, 0x210f _ 0) -NAMED_CHARACTER_REFERENCE(1620, /* p l */ 'u' _ 's' _ ';', 3, 0x002b _ 0) -NAMED_CHARACTER_REFERENCE(1621, /* p l */ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 7, 0x2a23 _ 0) -NAMED_CHARACTER_REFERENCE(1622, /* p l */ 'u' _ 's' _ 'b' _ ';', 4, 0x229e _ 0) -NAMED_CHARACTER_REFERENCE(1623, /* p l */ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0x2a22 _ 0) -NAMED_CHARACTER_REFERENCE(1624, /* p l */ 'u' _ 's' _ 'd' _ 'o' _ ';', 5, 0x2214 _ 0) -NAMED_CHARACTER_REFERENCE(1625, /* p l */ 'u' _ 's' _ 'd' _ 'u' _ ';', 5, 0x2a25 _ 0) -NAMED_CHARACTER_REFERENCE(1626, /* p l */ 'u' _ 's' _ 'e' _ ';', 4, 0x2a72 _ 0) -NAMED_CHARACTER_REFERENCE(1627, /* p l */ 'u' _ 's' _ 'm' _ 'n', 4, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(1628, /* p l */ 'u' _ 's' _ 'm' _ 'n' _ ';', 5, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(1629, /* p l */ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2a26 _ 0) -NAMED_CHARACTER_REFERENCE(1630, /* p l */ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 6, 0x2a27 _ 0) -NAMED_CHARACTER_REFERENCE(1631, /* p m */ ';', 1, 0x00b1 _ 0) -NAMED_CHARACTER_REFERENCE(1632, /* p o */ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a15 _ 0) -NAMED_CHARACTER_REFERENCE(1633, /* p o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd61) -NAMED_CHARACTER_REFERENCE(1634, /* p o */ 'u' _ 'n' _ 'd', 3, 0x00a3 _ 0) -NAMED_CHARACTER_REFERENCE(1635, /* p o */ 'u' _ 'n' _ 'd' _ ';', 4, 0x00a3 _ 0) -NAMED_CHARACTER_REFERENCE(1636, /* p r */ ';', 1, 0x227a _ 0) -NAMED_CHARACTER_REFERENCE(1637, /* p r */ 'E' _ ';', 2, 0x2ab3 _ 0) -NAMED_CHARACTER_REFERENCE(1638, /* p r */ 'a' _ 'p' _ ';', 3, 0x2ab7 _ 0) -NAMED_CHARACTER_REFERENCE(1639, /* p r */ 'c' _ 'u' _ 'e' _ ';', 4, 0x227c _ 0) -NAMED_CHARACTER_REFERENCE(1640, /* p r */ 'e' _ ';', 2, 0x2aaf _ 0) -NAMED_CHARACTER_REFERENCE(1641, /* p r */ 'e' _ 'c' _ ';', 3, 0x227a _ 0) -NAMED_CHARACTER_REFERENCE(1642, /* p r */ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2ab7 _ 0) -NAMED_CHARACTER_REFERENCE(1643, /* p r */ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0x227c _ 0) -NAMED_CHARACTER_REFERENCE(1644, /* p r */ 'e' _ 'c' _ 'e' _ 'q' _ ';', 5, 0x2aaf _ 0) -NAMED_CHARACTER_REFERENCE(1645, /* p r */ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2ab9 _ 0) -NAMED_CHARACTER_REFERENCE(1646, /* p r */ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0x2ab5 _ 0) -NAMED_CHARACTER_REFERENCE(1647, /* p r */ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0x22e8 _ 0) -NAMED_CHARACTER_REFERENCE(1648, /* p r */ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0x227e _ 0) -NAMED_CHARACTER_REFERENCE(1649, /* p r */ 'i' _ 'm' _ 'e' _ ';', 4, 0x2032 _ 0) -NAMED_CHARACTER_REFERENCE(1650, /* p r */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x2119 _ 0) -NAMED_CHARACTER_REFERENCE(1651, /* p r */ 'n' _ 'E' _ ';', 3, 0x2ab5 _ 0) -NAMED_CHARACTER_REFERENCE(1652, /* p r */ 'n' _ 'a' _ 'p' _ ';', 4, 0x2ab9 _ 0) -NAMED_CHARACTER_REFERENCE(1653, /* p r */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0x22e8 _ 0) -NAMED_CHARACTER_REFERENCE(1654, /* p r */ 'o' _ 'd' _ ';', 3, 0x220f _ 0) -NAMED_CHARACTER_REFERENCE(1655, /* p r */ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 7, 0x232e _ 0) -NAMED_CHARACTER_REFERENCE(1656, /* p r */ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0x2312 _ 0) -NAMED_CHARACTER_REFERENCE(1657, /* p r */ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 7, 0x2313 _ 0) -NAMED_CHARACTER_REFERENCE(1658, /* p r */ 'o' _ 'p' _ ';', 3, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(1659, /* p r */ 'o' _ 'p' _ 't' _ 'o' _ ';', 5, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(1660, /* p r */ 's' _ 'i' _ 'm' _ ';', 4, 0x227e _ 0) -NAMED_CHARACTER_REFERENCE(1661, /* p r */ 'u' _ 'r' _ 'e' _ 'l' _ ';', 5, 0x22b0 _ 0) -NAMED_CHARACTER_REFERENCE(1662, /* p s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc5) -NAMED_CHARACTER_REFERENCE(1663, /* p s */ 'i' _ ';', 2, 0x03c8 _ 0) -NAMED_CHARACTER_REFERENCE(1664, /* p u */ 'n' _ 'c' _ 's' _ 'p' _ ';', 5, 0x2008 _ 0) -NAMED_CHARACTER_REFERENCE(1665, /* q f */ 'r' _ ';', 2, 0xd835 _ 0xdd2e) -NAMED_CHARACTER_REFERENCE(1666, /* q i */ 'n' _ 't' _ ';', 3, 0x2a0c _ 0) -NAMED_CHARACTER_REFERENCE(1667, /* q o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd62) -NAMED_CHARACTER_REFERENCE(1668, /* q p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2057 _ 0) -NAMED_CHARACTER_REFERENCE(1669, /* q s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc6) -NAMED_CHARACTER_REFERENCE(1670, /* q u */ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 10, 0x210d _ 0) -NAMED_CHARACTER_REFERENCE(1671, /* q u */ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 6, 0x2a16 _ 0) -NAMED_CHARACTER_REFERENCE(1672, /* q u */ 'e' _ 's' _ 't' _ ';', 4, 0x003f _ 0) -NAMED_CHARACTER_REFERENCE(1673, /* q u */ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 6, 0x225f _ 0) -NAMED_CHARACTER_REFERENCE(1674, /* q u */ 'o' _ 't', 2, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(1675, /* q u */ 'o' _ 't' _ ';', 3, 0x0022 _ 0) -NAMED_CHARACTER_REFERENCE(1676, /* r A */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21db _ 0) -NAMED_CHARACTER_REFERENCE(1677, /* r A */ 'r' _ 'r' _ ';', 3, 0x21d2 _ 0) -NAMED_CHARACTER_REFERENCE(1678, /* r A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x291c _ 0) -NAMED_CHARACTER_REFERENCE(1679, /* r B */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290f _ 0) -NAMED_CHARACTER_REFERENCE(1680, /* r H */ 'a' _ 'r' _ ';', 3, 0x2964 _ 0) -NAMED_CHARACTER_REFERENCE(1681, /* r a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x0155 _ 0) -NAMED_CHARACTER_REFERENCE(1682, /* r a */ 'd' _ 'i' _ 'c' _ ';', 4, 0x221a _ 0) -NAMED_CHARACTER_REFERENCE(1683, /* r a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0x29b3 _ 0) -NAMED_CHARACTER_REFERENCE(1684, /* r a */ 'n' _ 'g' _ ';', 3, 0x27e9 _ 0) -NAMED_CHARACTER_REFERENCE(1685, /* r a */ 'n' _ 'g' _ 'd' _ ';', 4, 0x2992 _ 0) -NAMED_CHARACTER_REFERENCE(1686, /* r a */ 'n' _ 'g' _ 'e' _ ';', 4, 0x29a5 _ 0) -NAMED_CHARACTER_REFERENCE(1687, /* r a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0x27e9 _ 0) -NAMED_CHARACTER_REFERENCE(1688, /* r a */ 'q' _ 'u' _ 'o', 3, 0x00bb _ 0) -NAMED_CHARACTER_REFERENCE(1689, /* r a */ 'q' _ 'u' _ 'o' _ ';', 4, 0x00bb _ 0) -NAMED_CHARACTER_REFERENCE(1690, /* r a */ 'r' _ 'r' _ ';', 3, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(1691, /* r a */ 'r' _ 'r' _ 'a' _ 'p' _ ';', 5, 0x2975 _ 0) -NAMED_CHARACTER_REFERENCE(1692, /* r a */ 'r' _ 'r' _ 'b' _ ';', 4, 0x21e5 _ 0) -NAMED_CHARACTER_REFERENCE(1693, /* r a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0x2920 _ 0) -NAMED_CHARACTER_REFERENCE(1694, /* r a */ 'r' _ 'r' _ 'c' _ ';', 4, 0x2933 _ 0) -NAMED_CHARACTER_REFERENCE(1695, /* r a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0x291e _ 0) -NAMED_CHARACTER_REFERENCE(1696, /* r a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x21aa _ 0) -NAMED_CHARACTER_REFERENCE(1697, /* r a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0x21ac _ 0) -NAMED_CHARACTER_REFERENCE(1698, /* r a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0x2945 _ 0) -NAMED_CHARACTER_REFERENCE(1699, /* r a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0x2974 _ 0) -NAMED_CHARACTER_REFERENCE(1700, /* r a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0x21a3 _ 0) -NAMED_CHARACTER_REFERENCE(1701, /* r a */ 'r' _ 'r' _ 'w' _ ';', 4, 0x219d _ 0) -NAMED_CHARACTER_REFERENCE(1702, /* r a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0x291a _ 0) -NAMED_CHARACTER_REFERENCE(1703, /* r a */ 't' _ 'i' _ 'o' _ ';', 4, 0x2236 _ 0) -NAMED_CHARACTER_REFERENCE(1704, /* r a */ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ 's' _ ';', 8, 0x211a _ 0) -NAMED_CHARACTER_REFERENCE(1705, /* r b */ 'a' _ 'r' _ 'r' _ ';', 4, 0x290d _ 0) -NAMED_CHARACTER_REFERENCE(1706, /* r b */ 'b' _ 'r' _ 'k' _ ';', 4, 0x2773 _ 0) -NAMED_CHARACTER_REFERENCE(1707, /* r b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0x007d _ 0) -NAMED_CHARACTER_REFERENCE(1708, /* r b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0x005d _ 0) -NAMED_CHARACTER_REFERENCE(1709, /* r b */ 'r' _ 'k' _ 'e' _ ';', 4, 0x298c _ 0) -NAMED_CHARACTER_REFERENCE(1710, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0x298e _ 0) -NAMED_CHARACTER_REFERENCE(1711, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0x2990 _ 0) -NAMED_CHARACTER_REFERENCE(1712, /* r c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0159 _ 0) -NAMED_CHARACTER_REFERENCE(1713, /* r c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0157 _ 0) -NAMED_CHARACTER_REFERENCE(1714, /* r c */ 'e' _ 'i' _ 'l' _ ';', 4, 0x2309 _ 0) -NAMED_CHARACTER_REFERENCE(1715, /* r c */ 'u' _ 'b' _ ';', 3, 0x007d _ 0) -NAMED_CHARACTER_REFERENCE(1716, /* r c */ 'y' _ ';', 2, 0x0440 _ 0) -NAMED_CHARACTER_REFERENCE(1717, /* r d */ 'c' _ 'a' _ ';', 3, 0x2937 _ 0) -NAMED_CHARACTER_REFERENCE(1718, /* r d */ 'l' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2969 _ 0) -NAMED_CHARACTER_REFERENCE(1719, /* r d */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201d _ 0) -NAMED_CHARACTER_REFERENCE(1720, /* r d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x201d _ 0) -NAMED_CHARACTER_REFERENCE(1721, /* r d */ 's' _ 'h' _ ';', 3, 0x21b3 _ 0) -NAMED_CHARACTER_REFERENCE(1722, /* r e */ 'a' _ 'l' _ ';', 3, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(1723, /* r e */ 'a' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0x211b _ 0) -NAMED_CHARACTER_REFERENCE(1724, /* r e */ 'a' _ 'l' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0x211c _ 0) -NAMED_CHARACTER_REFERENCE(1725, /* r e */ 'a' _ 'l' _ 's' _ ';', 4, 0x211d _ 0) -NAMED_CHARACTER_REFERENCE(1726, /* r e */ 'c' _ 't' _ ';', 3, 0x25ad _ 0) -NAMED_CHARACTER_REFERENCE(1727, /* r e */ 'g', 1, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(1728, /* r e */ 'g' _ ';', 2, 0x00ae _ 0) -NAMED_CHARACTER_REFERENCE(1729, /* r f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297d _ 0) -NAMED_CHARACTER_REFERENCE(1730, /* r f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0x230b _ 0) -NAMED_CHARACTER_REFERENCE(1731, /* r f */ 'r' _ ';', 2, 0xd835 _ 0xdd2f) -NAMED_CHARACTER_REFERENCE(1732, /* r h */ 'a' _ 'r' _ 'd' _ ';', 4, 0x21c1 _ 0) -NAMED_CHARACTER_REFERENCE(1733, /* r h */ 'a' _ 'r' _ 'u' _ ';', 4, 0x21c0 _ 0) -NAMED_CHARACTER_REFERENCE(1734, /* r h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0x296c _ 0) -NAMED_CHARACTER_REFERENCE(1735, /* r h */ 'o' _ ';', 2, 0x03c1 _ 0) -NAMED_CHARACTER_REFERENCE(1736, /* r h */ 'o' _ 'v' _ ';', 3, 0x03f1 _ 0) -NAMED_CHARACTER_REFERENCE(1737, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(1738, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 13, 0x21a3 _ 0) -NAMED_CHARACTER_REFERENCE(1739, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 15, 0x21c1 _ 0) -NAMED_CHARACTER_REFERENCE(1740, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 13, 0x21c0 _ 0) -NAMED_CHARACTER_REFERENCE(1741, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0x21c4 _ 0) -NAMED_CHARACTER_REFERENCE(1742, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0x21cc _ 0) -NAMED_CHARACTER_REFERENCE(1743, /* r i */ 'g' _ 'h' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0x21c9 _ 0) -NAMED_CHARACTER_REFERENCE(1744, /* r i */ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0x219d _ 0) -NAMED_CHARACTER_REFERENCE(1745, /* r i */ 'g' _ 'h' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 14, 0x22cc _ 0) -NAMED_CHARACTER_REFERENCE(1746, /* r i */ 'n' _ 'g' _ ';', 3, 0x02da _ 0) -NAMED_CHARACTER_REFERENCE(1747, /* r i */ 's' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 11, 0x2253 _ 0) -NAMED_CHARACTER_REFERENCE(1748, /* r l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c4 _ 0) -NAMED_CHARACTER_REFERENCE(1749, /* r l */ 'h' _ 'a' _ 'r' _ ';', 4, 0x21cc _ 0) -NAMED_CHARACTER_REFERENCE(1750, /* r l */ 'm' _ ';', 2, 0x200f _ 0) -NAMED_CHARACTER_REFERENCE(1751, /* r m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0x23b1 _ 0) -NAMED_CHARACTER_REFERENCE(1752, /* r m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0x23b1 _ 0) -NAMED_CHARACTER_REFERENCE(1753, /* r n */ 'm' _ 'i' _ 'd' _ ';', 4, 0x2aee _ 0) -NAMED_CHARACTER_REFERENCE(1754, /* r o */ 'a' _ 'n' _ 'g' _ ';', 4, 0x27ed _ 0) -NAMED_CHARACTER_REFERENCE(1755, /* r o */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21fe _ 0) -NAMED_CHARACTER_REFERENCE(1756, /* r o */ 'b' _ 'r' _ 'k' _ ';', 4, 0x27e7 _ 0) -NAMED_CHARACTER_REFERENCE(1757, /* r o */ 'p' _ 'a' _ 'r' _ ';', 4, 0x2986 _ 0) -NAMED_CHARACTER_REFERENCE(1758, /* r o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd63) -NAMED_CHARACTER_REFERENCE(1759, /* r o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a2e _ 0) -NAMED_CHARACTER_REFERENCE(1760, /* r o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0x2a35 _ 0) -NAMED_CHARACTER_REFERENCE(1761, /* r p */ 'a' _ 'r' _ ';', 3, 0x0029 _ 0) -NAMED_CHARACTER_REFERENCE(1762, /* r p */ 'a' _ 'r' _ 'g' _ 't' _ ';', 5, 0x2994 _ 0) -NAMED_CHARACTER_REFERENCE(1763, /* r p */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a12 _ 0) -NAMED_CHARACTER_REFERENCE(1764, /* r r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c9 _ 0) -NAMED_CHARACTER_REFERENCE(1765, /* r s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0x203a _ 0) -NAMED_CHARACTER_REFERENCE(1766, /* r s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc7) -NAMED_CHARACTER_REFERENCE(1767, /* r s */ 'h' _ ';', 2, 0x21b1 _ 0) -NAMED_CHARACTER_REFERENCE(1768, /* r s */ 'q' _ 'b' _ ';', 3, 0x005d _ 0) -NAMED_CHARACTER_REFERENCE(1769, /* r s */ 'q' _ 'u' _ 'o' _ ';', 4, 0x2019 _ 0) -NAMED_CHARACTER_REFERENCE(1770, /* r s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0x2019 _ 0) -NAMED_CHARACTER_REFERENCE(1771, /* r t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0x22cc _ 0) -NAMED_CHARACTER_REFERENCE(1772, /* r t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0x22ca _ 0) -NAMED_CHARACTER_REFERENCE(1773, /* r t */ 'r' _ 'i' _ ';', 3, 0x25b9 _ 0) -NAMED_CHARACTER_REFERENCE(1774, /* r t */ 'r' _ 'i' _ 'e' _ ';', 4, 0x22b5 _ 0) -NAMED_CHARACTER_REFERENCE(1775, /* r t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25b8 _ 0) -NAMED_CHARACTER_REFERENCE(1776, /* r t */ 'r' _ 'i' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 7, 0x29ce _ 0) -NAMED_CHARACTER_REFERENCE(1777, /* r u */ 'l' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0x2968 _ 0) -NAMED_CHARACTER_REFERENCE(1778, /* r x */ ';', 1, 0x211e _ 0) -NAMED_CHARACTER_REFERENCE(1779, /* s a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x015b _ 0) -NAMED_CHARACTER_REFERENCE(1780, /* s b */ 'q' _ 'u' _ 'o' _ ';', 4, 0x201a _ 0) -NAMED_CHARACTER_REFERENCE(1781, /* s c */ ';', 1, 0x227b _ 0) -NAMED_CHARACTER_REFERENCE(1782, /* s c */ 'E' _ ';', 2, 0x2ab4 _ 0) -NAMED_CHARACTER_REFERENCE(1783, /* s c */ 'a' _ 'p' _ ';', 3, 0x2ab8 _ 0) -NAMED_CHARACTER_REFERENCE(1784, /* s c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0161 _ 0) -NAMED_CHARACTER_REFERENCE(1785, /* s c */ 'c' _ 'u' _ 'e' _ ';', 4, 0x227d _ 0) -NAMED_CHARACTER_REFERENCE(1786, /* s c */ 'e' _ ';', 2, 0x2ab0 _ 0) -NAMED_CHARACTER_REFERENCE(1787, /* s c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x015f _ 0) -NAMED_CHARACTER_REFERENCE(1788, /* s c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x015d _ 0) -NAMED_CHARACTER_REFERENCE(1789, /* s c */ 'n' _ 'E' _ ';', 3, 0x2ab6 _ 0) -NAMED_CHARACTER_REFERENCE(1790, /* s c */ 'n' _ 'a' _ 'p' _ ';', 4, 0x2aba _ 0) -NAMED_CHARACTER_REFERENCE(1791, /* s c */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0x22e9 _ 0) -NAMED_CHARACTER_REFERENCE(1792, /* s c */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0x2a13 _ 0) -NAMED_CHARACTER_REFERENCE(1793, /* s c */ 's' _ 'i' _ 'm' _ ';', 4, 0x227f _ 0) -NAMED_CHARACTER_REFERENCE(1794, /* s c */ 'y' _ ';', 2, 0x0441 _ 0) -NAMED_CHARACTER_REFERENCE(1795, /* s d */ 'o' _ 't' _ ';', 3, 0x22c5 _ 0) -NAMED_CHARACTER_REFERENCE(1796, /* s d */ 'o' _ 't' _ 'b' _ ';', 4, 0x22a1 _ 0) -NAMED_CHARACTER_REFERENCE(1797, /* s d */ 'o' _ 't' _ 'e' _ ';', 4, 0x2a66 _ 0) -NAMED_CHARACTER_REFERENCE(1798, /* s e */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d8 _ 0) -NAMED_CHARACTER_REFERENCE(1799, /* s e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2925 _ 0) -NAMED_CHARACTER_REFERENCE(1800, /* s e */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2198 _ 0) -NAMED_CHARACTER_REFERENCE(1801, /* s e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2198 _ 0) -NAMED_CHARACTER_REFERENCE(1802, /* s e */ 'c' _ 't', 2, 0x00a7 _ 0) -NAMED_CHARACTER_REFERENCE(1803, /* s e */ 'c' _ 't' _ ';', 3, 0x00a7 _ 0) -NAMED_CHARACTER_REFERENCE(1804, /* s e */ 'm' _ 'i' _ ';', 3, 0x003b _ 0) -NAMED_CHARACTER_REFERENCE(1805, /* s e */ 's' _ 'w' _ 'a' _ 'r' _ ';', 5, 0x2929 _ 0) -NAMED_CHARACTER_REFERENCE(1806, /* s e */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1807, /* s e */ 't' _ 'm' _ 'n' _ ';', 4, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1808, /* s e */ 'x' _ 't' _ ';', 3, 0x2736 _ 0) -NAMED_CHARACTER_REFERENCE(1809, /* s f */ 'r' _ ';', 2, 0xd835 _ 0xdd30) -NAMED_CHARACTER_REFERENCE(1810, /* s f */ 'r' _ 'o' _ 'w' _ 'n' _ ';', 5, 0x2322 _ 0) -NAMED_CHARACTER_REFERENCE(1811, /* s h */ 'a' _ 'r' _ 'p' _ ';', 4, 0x266f _ 0) -NAMED_CHARACTER_REFERENCE(1812, /* s h */ 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0x0449 _ 0) -NAMED_CHARACTER_REFERENCE(1813, /* s h */ 'c' _ 'y' _ ';', 3, 0x0448 _ 0) -NAMED_CHARACTER_REFERENCE(1814, /* s h */ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 7, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(1815, /* s h */ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 12, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1816, /* s h */ 'y', 1, 0x00ad _ 0) -NAMED_CHARACTER_REFERENCE(1817, /* s h */ 'y' _ ';', 2, 0x00ad _ 0) -NAMED_CHARACTER_REFERENCE(1818, /* s i */ 'g' _ 'm' _ 'a' _ ';', 4, 0x03c3 _ 0) -NAMED_CHARACTER_REFERENCE(1819, /* s i */ 'g' _ 'm' _ 'a' _ 'f' _ ';', 5, 0x03c2 _ 0) -NAMED_CHARACTER_REFERENCE(1820, /* s i */ 'g' _ 'm' _ 'a' _ 'v' _ ';', 5, 0x03c2 _ 0) -NAMED_CHARACTER_REFERENCE(1821, /* s i */ 'm' _ ';', 2, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(1822, /* s i */ 'm' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2a6a _ 0) -NAMED_CHARACTER_REFERENCE(1823, /* s i */ 'm' _ 'e' _ ';', 3, 0x2243 _ 0) -NAMED_CHARACTER_REFERENCE(1824, /* s i */ 'm' _ 'e' _ 'q' _ ';', 4, 0x2243 _ 0) -NAMED_CHARACTER_REFERENCE(1825, /* s i */ 'm' _ 'g' _ ';', 3, 0x2a9e _ 0) -NAMED_CHARACTER_REFERENCE(1826, /* s i */ 'm' _ 'g' _ 'E' _ ';', 4, 0x2aa0 _ 0) -NAMED_CHARACTER_REFERENCE(1827, /* s i */ 'm' _ 'l' _ ';', 3, 0x2a9d _ 0) -NAMED_CHARACTER_REFERENCE(1828, /* s i */ 'm' _ 'l' _ 'E' _ ';', 4, 0x2a9f _ 0) -NAMED_CHARACTER_REFERENCE(1829, /* s i */ 'm' _ 'n' _ 'e' _ ';', 4, 0x2246 _ 0) -NAMED_CHARACTER_REFERENCE(1830, /* s i */ 'm' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2a24 _ 0) -NAMED_CHARACTER_REFERENCE(1831, /* s i */ 'm' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2972 _ 0) -NAMED_CHARACTER_REFERENCE(1832, /* s l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2190 _ 0) -NAMED_CHARACTER_REFERENCE(1833, /* s m */ 'a' _ 'l' _ 'l' _ 's' _ 'e' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 12, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1834, /* s m */ 'a' _ 's' _ 'h' _ 'p' _ ';', 5, 0x2a33 _ 0) -NAMED_CHARACTER_REFERENCE(1835, /* s m */ 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0x29e4 _ 0) -NAMED_CHARACTER_REFERENCE(1836, /* s m */ 'i' _ 'd' _ ';', 3, 0x2223 _ 0) -NAMED_CHARACTER_REFERENCE(1837, /* s m */ 'i' _ 'l' _ 'e' _ ';', 4, 0x2323 _ 0) -NAMED_CHARACTER_REFERENCE(1838, /* s m */ 't' _ ';', 2, 0x2aaa _ 0) -NAMED_CHARACTER_REFERENCE(1839, /* s m */ 't' _ 'e' _ ';', 3, 0x2aac _ 0) -NAMED_CHARACTER_REFERENCE(1840, /* s o */ 'f' _ 't' _ 'c' _ 'y' _ ';', 5, 0x044c _ 0) -NAMED_CHARACTER_REFERENCE(1841, /* s o */ 'l' _ ';', 2, 0x002f _ 0) -NAMED_CHARACTER_REFERENCE(1842, /* s o */ 'l' _ 'b' _ ';', 3, 0x29c4 _ 0) -NAMED_CHARACTER_REFERENCE(1843, /* s o */ 'l' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x233f _ 0) -NAMED_CHARACTER_REFERENCE(1844, /* s o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd64) -NAMED_CHARACTER_REFERENCE(1845, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ ';', 5, 0x2660 _ 0) -NAMED_CHARACTER_REFERENCE(1846, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0x2660 _ 0) -NAMED_CHARACTER_REFERENCE(1847, /* s p */ 'a' _ 'r' _ ';', 3, 0x2225 _ 0) -NAMED_CHARACTER_REFERENCE(1848, /* s q */ 'c' _ 'a' _ 'p' _ ';', 4, 0x2293 _ 0) -NAMED_CHARACTER_REFERENCE(1849, /* s q */ 'c' _ 'u' _ 'p' _ ';', 4, 0x2294 _ 0) -NAMED_CHARACTER_REFERENCE(1850, /* s q */ 's' _ 'u' _ 'b' _ ';', 4, 0x228f _ 0) -NAMED_CHARACTER_REFERENCE(1851, /* s q */ 's' _ 'u' _ 'b' _ 'e' _ ';', 5, 0x2291 _ 0) -NAMED_CHARACTER_REFERENCE(1852, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 7, 0x228f _ 0) -NAMED_CHARACTER_REFERENCE(1853, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0x2291 _ 0) -NAMED_CHARACTER_REFERENCE(1854, /* s q */ 's' _ 'u' _ 'p' _ ';', 4, 0x2290 _ 0) -NAMED_CHARACTER_REFERENCE(1855, /* s q */ 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0x2292 _ 0) -NAMED_CHARACTER_REFERENCE(1856, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, 0x2290 _ 0) -NAMED_CHARACTER_REFERENCE(1857, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0x2292 _ 0) -NAMED_CHARACTER_REFERENCE(1858, /* s q */ 'u' _ ';', 2, 0x25a1 _ 0) -NAMED_CHARACTER_REFERENCE(1859, /* s q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0x25a1 _ 0) -NAMED_CHARACTER_REFERENCE(1860, /* s q */ 'u' _ 'a' _ 'r' _ 'f' _ ';', 5, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(1861, /* s q */ 'u' _ 'f' _ ';', 3, 0x25aa _ 0) -NAMED_CHARACTER_REFERENCE(1862, /* s r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2192 _ 0) -NAMED_CHARACTER_REFERENCE(1863, /* s s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc8) -NAMED_CHARACTER_REFERENCE(1864, /* s s */ 'e' _ 't' _ 'm' _ 'n' _ ';', 5, 0x2216 _ 0) -NAMED_CHARACTER_REFERENCE(1865, /* s s */ 'm' _ 'i' _ 'l' _ 'e' _ ';', 5, 0x2323 _ 0) -NAMED_CHARACTER_REFERENCE(1866, /* s s */ 't' _ 'a' _ 'r' _ 'f' _ ';', 5, 0x22c6 _ 0) -NAMED_CHARACTER_REFERENCE(1867, /* s t */ 'a' _ 'r' _ ';', 3, 0x2606 _ 0) -NAMED_CHARACTER_REFERENCE(1868, /* s t */ 'a' _ 'r' _ 'f' _ ';', 4, 0x2605 _ 0) -NAMED_CHARACTER_REFERENCE(1869, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 14, 0x03f5 _ 0) -NAMED_CHARACTER_REFERENCE(1870, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'p' _ 'h' _ 'i' _ ';', 10, 0x03d5 _ 0) -NAMED_CHARACTER_REFERENCE(1871, /* s t */ 'r' _ 'n' _ 's' _ ';', 4, 0x00af _ 0) -NAMED_CHARACTER_REFERENCE(1872, /* s u */ 'b' _ ';', 2, 0x2282 _ 0) -NAMED_CHARACTER_REFERENCE(1873, /* s u */ 'b' _ 'E' _ ';', 3, 0x2ac5 _ 0) -NAMED_CHARACTER_REFERENCE(1874, /* s u */ 'b' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2abd _ 0) -NAMED_CHARACTER_REFERENCE(1875, /* s u */ 'b' _ 'e' _ ';', 3, 0x2286 _ 0) -NAMED_CHARACTER_REFERENCE(1876, /* s u */ 'b' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2ac3 _ 0) -NAMED_CHARACTER_REFERENCE(1877, /* s u */ 'b' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0x2ac1 _ 0) -NAMED_CHARACTER_REFERENCE(1878, /* s u */ 'b' _ 'n' _ 'E' _ ';', 4, 0x2acb _ 0) -NAMED_CHARACTER_REFERENCE(1879, /* s u */ 'b' _ 'n' _ 'e' _ ';', 4, 0x228a _ 0) -NAMED_CHARACTER_REFERENCE(1880, /* s u */ 'b' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2abf _ 0) -NAMED_CHARACTER_REFERENCE(1881, /* s u */ 'b' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x2979 _ 0) -NAMED_CHARACTER_REFERENCE(1882, /* s u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0x2282 _ 0) -NAMED_CHARACTER_REFERENCE(1883, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0x2286 _ 0) -NAMED_CHARACTER_REFERENCE(1884, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0x2ac5 _ 0) -NAMED_CHARACTER_REFERENCE(1885, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0x228a _ 0) -NAMED_CHARACTER_REFERENCE(1886, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0x2acb _ 0) -NAMED_CHARACTER_REFERENCE(1887, /* s u */ 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2ac7 _ 0) -NAMED_CHARACTER_REFERENCE(1888, /* s u */ 'b' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2ad5 _ 0) -NAMED_CHARACTER_REFERENCE(1889, /* s u */ 'b' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2ad3 _ 0) -NAMED_CHARACTER_REFERENCE(1890, /* s u */ 'c' _ 'c' _ ';', 3, 0x227b _ 0) -NAMED_CHARACTER_REFERENCE(1891, /* s u */ 'c' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0x2ab8 _ 0) -NAMED_CHARACTER_REFERENCE(1892, /* s u */ 'c' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0x227d _ 0) -NAMED_CHARACTER_REFERENCE(1893, /* s u */ 'c' _ 'c' _ 'e' _ 'q' _ ';', 5, 0x2ab0 _ 0) -NAMED_CHARACTER_REFERENCE(1894, /* s u */ 'c' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2aba _ 0) -NAMED_CHARACTER_REFERENCE(1895, /* s u */ 'c' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0x2ab6 _ 0) -NAMED_CHARACTER_REFERENCE(1896, /* s u */ 'c' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0x22e9 _ 0) -NAMED_CHARACTER_REFERENCE(1897, /* s u */ 'c' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0x227f _ 0) -NAMED_CHARACTER_REFERENCE(1898, /* s u */ 'm' _ ';', 2, 0x2211 _ 0) -NAMED_CHARACTER_REFERENCE(1899, /* s u */ 'n' _ 'g' _ ';', 3, 0x266a _ 0) -NAMED_CHARACTER_REFERENCE(1900, /* s u */ 'p' _ '1', 2, 0x00b9 _ 0) -NAMED_CHARACTER_REFERENCE(1901, /* s u */ 'p' _ '1' _ ';', 3, 0x00b9 _ 0) -NAMED_CHARACTER_REFERENCE(1902, /* s u */ 'p' _ '2', 2, 0x00b2 _ 0) -NAMED_CHARACTER_REFERENCE(1903, /* s u */ 'p' _ '2' _ ';', 3, 0x00b2 _ 0) -NAMED_CHARACTER_REFERENCE(1904, /* s u */ 'p' _ '3', 2, 0x00b3 _ 0) -NAMED_CHARACTER_REFERENCE(1905, /* s u */ 'p' _ '3' _ ';', 3, 0x00b3 _ 0) -NAMED_CHARACTER_REFERENCE(1906, /* s u */ 'p' _ ';', 2, 0x2283 _ 0) -NAMED_CHARACTER_REFERENCE(1907, /* s u */ 'p' _ 'E' _ ';', 3, 0x2ac6 _ 0) -NAMED_CHARACTER_REFERENCE(1908, /* s u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0x2abe _ 0) -NAMED_CHARACTER_REFERENCE(1909, /* s u */ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 6, 0x2ad8 _ 0) -NAMED_CHARACTER_REFERENCE(1910, /* s u */ 'p' _ 'e' _ ';', 3, 0x2287 _ 0) -NAMED_CHARACTER_REFERENCE(1911, /* s u */ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0x2ac4 _ 0) -NAMED_CHARACTER_REFERENCE(1912, /* s u */ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 6, 0x27c9 _ 0) -NAMED_CHARACTER_REFERENCE(1913, /* s u */ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 6, 0x2ad7 _ 0) -NAMED_CHARACTER_REFERENCE(1914, /* s u */ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x297b _ 0) -NAMED_CHARACTER_REFERENCE(1915, /* s u */ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0x2ac2 _ 0) -NAMED_CHARACTER_REFERENCE(1916, /* s u */ 'p' _ 'n' _ 'E' _ ';', 4, 0x2acc _ 0) -NAMED_CHARACTER_REFERENCE(1917, /* s u */ 'p' _ 'n' _ 'e' _ ';', 4, 0x228b _ 0) -NAMED_CHARACTER_REFERENCE(1918, /* s u */ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2ac0 _ 0) -NAMED_CHARACTER_REFERENCE(1919, /* s u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0x2283 _ 0) -NAMED_CHARACTER_REFERENCE(1920, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0x2287 _ 0) -NAMED_CHARACTER_REFERENCE(1921, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0x2ac6 _ 0) -NAMED_CHARACTER_REFERENCE(1922, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0x228b _ 0) -NAMED_CHARACTER_REFERENCE(1923, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0x2acc _ 0) -NAMED_CHARACTER_REFERENCE(1924, /* s u */ 'p' _ 's' _ 'i' _ 'm' _ ';', 5, 0x2ac8 _ 0) -NAMED_CHARACTER_REFERENCE(1925, /* s u */ 'p' _ 's' _ 'u' _ 'b' _ ';', 5, 0x2ad4 _ 0) -NAMED_CHARACTER_REFERENCE(1926, /* s u */ 'p' _ 's' _ 'u' _ 'p' _ ';', 5, 0x2ad6 _ 0) -NAMED_CHARACTER_REFERENCE(1927, /* s w */ 'A' _ 'r' _ 'r' _ ';', 4, 0x21d9 _ 0) -NAMED_CHARACTER_REFERENCE(1928, /* s w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0x2926 _ 0) -NAMED_CHARACTER_REFERENCE(1929, /* s w */ 'a' _ 'r' _ 'r' _ ';', 4, 0x2199 _ 0) -NAMED_CHARACTER_REFERENCE(1930, /* s w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2199 _ 0) -NAMED_CHARACTER_REFERENCE(1931, /* s w */ 'n' _ 'w' _ 'a' _ 'r' _ ';', 5, 0x292a _ 0) -NAMED_CHARACTER_REFERENCE(1932, /* s z */ 'l' _ 'i' _ 'g', 3, 0x00df _ 0) -NAMED_CHARACTER_REFERENCE(1933, /* s z */ 'l' _ 'i' _ 'g' _ ';', 4, 0x00df _ 0) -NAMED_CHARACTER_REFERENCE(1934, /* t a */ 'r' _ 'g' _ 'e' _ 't' _ ';', 5, 0x2316 _ 0) -NAMED_CHARACTER_REFERENCE(1935, /* t a */ 'u' _ ';', 2, 0x03c4 _ 0) -NAMED_CHARACTER_REFERENCE(1936, /* t b */ 'r' _ 'k' _ ';', 3, 0x23b4 _ 0) -NAMED_CHARACTER_REFERENCE(1937, /* t c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x0165 _ 0) -NAMED_CHARACTER_REFERENCE(1938, /* t c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0x0163 _ 0) -NAMED_CHARACTER_REFERENCE(1939, /* t c */ 'y' _ ';', 2, 0x0442 _ 0) -NAMED_CHARACTER_REFERENCE(1940, /* t d */ 'o' _ 't' _ ';', 3, 0x20db _ 0) -NAMED_CHARACTER_REFERENCE(1941, /* t e */ 'l' _ 'r' _ 'e' _ 'c' _ ';', 5, 0x2315 _ 0) -NAMED_CHARACTER_REFERENCE(1942, /* t f */ 'r' _ ';', 2, 0xd835 _ 0xdd31) -NAMED_CHARACTER_REFERENCE(1943, /* t h */ 'e' _ 'r' _ 'e' _ '4' _ ';', 5, 0x2234 _ 0) -NAMED_CHARACTER_REFERENCE(1944, /* t h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0x2234 _ 0) -NAMED_CHARACTER_REFERENCE(1945, /* t h */ 'e' _ 't' _ 'a' _ ';', 4, 0x03b8 _ 0) -NAMED_CHARACTER_REFERENCE(1946, /* t h */ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 7, 0x03d1 _ 0) -NAMED_CHARACTER_REFERENCE(1947, /* t h */ 'e' _ 't' _ 'a' _ 'v' _ ';', 5, 0x03d1 _ 0) -NAMED_CHARACTER_REFERENCE(1948, /* t h */ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(1949, /* t h */ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(1950, /* t h */ 'i' _ 'n' _ 's' _ 'p' _ ';', 5, 0x2009 _ 0) -NAMED_CHARACTER_REFERENCE(1951, /* t h */ 'k' _ 'a' _ 'p' _ ';', 4, 0x2248 _ 0) -NAMED_CHARACTER_REFERENCE(1952, /* t h */ 'k' _ 's' _ 'i' _ 'm' _ ';', 5, 0x223c _ 0) -NAMED_CHARACTER_REFERENCE(1953, /* t h */ 'o' _ 'r' _ 'n', 3, 0x00fe _ 0) -NAMED_CHARACTER_REFERENCE(1954, /* t h */ 'o' _ 'r' _ 'n' _ ';', 4, 0x00fe _ 0) -NAMED_CHARACTER_REFERENCE(1955, /* t i */ 'l' _ 'd' _ 'e' _ ';', 4, 0x02dc _ 0) -NAMED_CHARACTER_REFERENCE(1956, /* t i */ 'm' _ 'e' _ 's', 3, 0x00d7 _ 0) -NAMED_CHARACTER_REFERENCE(1957, /* t i */ 'm' _ 'e' _ 's' _ ';', 4, 0x00d7 _ 0) -NAMED_CHARACTER_REFERENCE(1958, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ ';', 5, 0x22a0 _ 0) -NAMED_CHARACTER_REFERENCE(1959, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 7, 0x2a31 _ 0) -NAMED_CHARACTER_REFERENCE(1960, /* t i */ 'm' _ 'e' _ 's' _ 'd' _ ';', 5, 0x2a30 _ 0) -NAMED_CHARACTER_REFERENCE(1961, /* t i */ 'n' _ 't' _ ';', 3, 0x222d _ 0) -NAMED_CHARACTER_REFERENCE(1962, /* t o */ 'e' _ 'a' _ ';', 3, 0x2928 _ 0) -NAMED_CHARACTER_REFERENCE(1963, /* t o */ 'p' _ ';', 2, 0x22a4 _ 0) -NAMED_CHARACTER_REFERENCE(1964, /* t o */ 'p' _ 'b' _ 'o' _ 't' _ ';', 5, 0x2336 _ 0) -NAMED_CHARACTER_REFERENCE(1965, /* t o */ 'p' _ 'c' _ 'i' _ 'r' _ ';', 5, 0x2af1 _ 0) -NAMED_CHARACTER_REFERENCE(1966, /* t o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd65) -NAMED_CHARACTER_REFERENCE(1967, /* t o */ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 6, 0x2ada _ 0) -NAMED_CHARACTER_REFERENCE(1968, /* t o */ 's' _ 'a' _ ';', 3, 0x2929 _ 0) -NAMED_CHARACTER_REFERENCE(1969, /* t p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2034 _ 0) -NAMED_CHARACTER_REFERENCE(1970, /* t r */ 'a' _ 'd' _ 'e' _ ';', 4, 0x2122 _ 0) -NAMED_CHARACTER_REFERENCE(1971, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, 0x25b5 _ 0) -NAMED_CHARACTER_REFERENCE(1972, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 11, 0x25bf _ 0) -NAMED_CHARACTER_REFERENCE(1973, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 11, 0x25c3 _ 0) -NAMED_CHARACTER_REFERENCE(1974, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 13, 0x22b4 _ 0) -NAMED_CHARACTER_REFERENCE(1975, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 8, 0x225c _ 0) -NAMED_CHARACTER_REFERENCE(1976, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 12, 0x25b9 _ 0) -NAMED_CHARACTER_REFERENCE(1977, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 14, 0x22b5 _ 0) -NAMED_CHARACTER_REFERENCE(1978, /* t r */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0x25ec _ 0) -NAMED_CHARACTER_REFERENCE(1979, /* t r */ 'i' _ 'e' _ ';', 3, 0x225c _ 0) -NAMED_CHARACTER_REFERENCE(1980, /* t r */ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0x2a3a _ 0) -NAMED_CHARACTER_REFERENCE(1981, /* t r */ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0x2a39 _ 0) -NAMED_CHARACTER_REFERENCE(1982, /* t r */ 'i' _ 's' _ 'b' _ ';', 4, 0x29cd _ 0) -NAMED_CHARACTER_REFERENCE(1983, /* t r */ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 6, 0x2a3b _ 0) -NAMED_CHARACTER_REFERENCE(1984, /* t r */ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 7, 0x23e2 _ 0) -NAMED_CHARACTER_REFERENCE(1985, /* t s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcc9) -NAMED_CHARACTER_REFERENCE(1986, /* t s */ 'c' _ 'y' _ ';', 3, 0x0446 _ 0) -NAMED_CHARACTER_REFERENCE(1987, /* t s */ 'h' _ 'c' _ 'y' _ ';', 4, 0x045b _ 0) -NAMED_CHARACTER_REFERENCE(1988, /* t s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0x0167 _ 0) -NAMED_CHARACTER_REFERENCE(1989, /* t w */ 'i' _ 'x' _ 't' _ ';', 4, 0x226c _ 0) -NAMED_CHARACTER_REFERENCE(1990, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0x219e _ 0) -NAMED_CHARACTER_REFERENCE(1991, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0x21a0 _ 0) -NAMED_CHARACTER_REFERENCE(1992, /* u A */ 'r' _ 'r' _ ';', 3, 0x21d1 _ 0) -NAMED_CHARACTER_REFERENCE(1993, /* u H */ 'a' _ 'r' _ ';', 3, 0x2963 _ 0) -NAMED_CHARACTER_REFERENCE(1994, /* u a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00fa _ 0) -NAMED_CHARACTER_REFERENCE(1995, /* u a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00fa _ 0) -NAMED_CHARACTER_REFERENCE(1996, /* u a */ 'r' _ 'r' _ ';', 3, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(1997, /* u b */ 'r' _ 'c' _ 'y' _ ';', 4, 0x045e _ 0) -NAMED_CHARACTER_REFERENCE(1998, /* u b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0x016d _ 0) -NAMED_CHARACTER_REFERENCE(1999, /* u c */ 'i' _ 'r' _ 'c', 3, 0x00fb _ 0) -NAMED_CHARACTER_REFERENCE(2000, /* u c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x00fb _ 0) -NAMED_CHARACTER_REFERENCE(2001, /* u c */ 'y' _ ';', 2, 0x0443 _ 0) -NAMED_CHARACTER_REFERENCE(2002, /* u d */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c5 _ 0) -NAMED_CHARACTER_REFERENCE(2003, /* u d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0x0171 _ 0) -NAMED_CHARACTER_REFERENCE(2004, /* u d */ 'h' _ 'a' _ 'r' _ ';', 4, 0x296e _ 0) -NAMED_CHARACTER_REFERENCE(2005, /* u f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0x297e _ 0) -NAMED_CHARACTER_REFERENCE(2006, /* u f */ 'r' _ ';', 2, 0xd835 _ 0xdd32) -NAMED_CHARACTER_REFERENCE(2007, /* u g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0x00f9 _ 0) -NAMED_CHARACTER_REFERENCE(2008, /* u g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0x00f9 _ 0) -NAMED_CHARACTER_REFERENCE(2009, /* u h */ 'a' _ 'r' _ 'l' _ ';', 4, 0x21bf _ 0) -NAMED_CHARACTER_REFERENCE(2010, /* u h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21be _ 0) -NAMED_CHARACTER_REFERENCE(2011, /* u h */ 'b' _ 'l' _ 'k' _ ';', 4, 0x2580 _ 0) -NAMED_CHARACTER_REFERENCE(2012, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231c _ 0) -NAMED_CHARACTER_REFERENCE(2013, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231c _ 0) -NAMED_CHARACTER_REFERENCE(2014, /* u l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230f _ 0) -NAMED_CHARACTER_REFERENCE(2015, /* u l */ 't' _ 'r' _ 'i' _ ';', 4, 0x25f8 _ 0) -NAMED_CHARACTER_REFERENCE(2016, /* u m */ 'a' _ 'c' _ 'r' _ ';', 4, 0x016b _ 0) -NAMED_CHARACTER_REFERENCE(2017, /* u m */ 'l', 1, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(2018, /* u m */ 'l' _ ';', 2, 0x00a8 _ 0) -NAMED_CHARACTER_REFERENCE(2019, /* u o */ 'g' _ 'o' _ 'n' _ ';', 4, 0x0173 _ 0) -NAMED_CHARACTER_REFERENCE(2020, /* u o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd66) -NAMED_CHARACTER_REFERENCE(2021, /* u p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0x2191 _ 0) -NAMED_CHARACTER_REFERENCE(2022, /* u p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0x2195 _ 0) -NAMED_CHARACTER_REFERENCE(2023, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0x21bf _ 0) -NAMED_CHARACTER_REFERENCE(2024, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0x21be _ 0) -NAMED_CHARACTER_REFERENCE(2025, /* u p */ 'l' _ 'u' _ 's' _ ';', 4, 0x228e _ 0) -NAMED_CHARACTER_REFERENCE(2026, /* u p */ 's' _ 'i' _ ';', 3, 0x03c5 _ 0) -NAMED_CHARACTER_REFERENCE(2027, /* u p */ 's' _ 'i' _ 'h' _ ';', 4, 0x03d2 _ 0) -NAMED_CHARACTER_REFERENCE(2028, /* u p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0x03c5 _ 0) -NAMED_CHARACTER_REFERENCE(2029, /* u p */ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 9, 0x21c8 _ 0) -NAMED_CHARACTER_REFERENCE(2030, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0x231d _ 0) -NAMED_CHARACTER_REFERENCE(2031, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0x231d _ 0) -NAMED_CHARACTER_REFERENCE(2032, /* u r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0x230e _ 0) -NAMED_CHARACTER_REFERENCE(2033, /* u r */ 'i' _ 'n' _ 'g' _ ';', 4, 0x016f _ 0) -NAMED_CHARACTER_REFERENCE(2034, /* u r */ 't' _ 'r' _ 'i' _ ';', 4, 0x25f9 _ 0) -NAMED_CHARACTER_REFERENCE(2035, /* u s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcca) -NAMED_CHARACTER_REFERENCE(2036, /* u t */ 'd' _ 'o' _ 't' _ ';', 4, 0x22f0 _ 0) -NAMED_CHARACTER_REFERENCE(2037, /* u t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0x0169 _ 0) -NAMED_CHARACTER_REFERENCE(2038, /* u t */ 'r' _ 'i' _ ';', 3, 0x25b5 _ 0) -NAMED_CHARACTER_REFERENCE(2039, /* u t */ 'r' _ 'i' _ 'f' _ ';', 4, 0x25b4 _ 0) -NAMED_CHARACTER_REFERENCE(2040, /* u u */ 'a' _ 'r' _ 'r' _ ';', 4, 0x21c8 _ 0) -NAMED_CHARACTER_REFERENCE(2041, /* u u */ 'm' _ 'l', 2, 0x00fc _ 0) -NAMED_CHARACTER_REFERENCE(2042, /* u u */ 'm' _ 'l' _ ';', 3, 0x00fc _ 0) -NAMED_CHARACTER_REFERENCE(2043, /* u w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0x29a7 _ 0) -NAMED_CHARACTER_REFERENCE(2044, /* v A */ 'r' _ 'r' _ ';', 3, 0x21d5 _ 0) -NAMED_CHARACTER_REFERENCE(2045, /* v B */ 'a' _ 'r' _ ';', 3, 0x2ae8 _ 0) -NAMED_CHARACTER_REFERENCE(2046, /* v B */ 'a' _ 'r' _ 'v' _ ';', 4, 0x2ae9 _ 0) -NAMED_CHARACTER_REFERENCE(2047, /* v D */ 'a' _ 's' _ 'h' _ ';', 4, 0x22a8 _ 0) -NAMED_CHARACTER_REFERENCE(2048, /* v a */ 'n' _ 'g' _ 'r' _ 't' _ ';', 5, 0x299c _ 0) -NAMED_CHARACTER_REFERENCE(2049, /* v a */ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 9, 0x03f5 _ 0) -NAMED_CHARACTER_REFERENCE(2050, /* v a */ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 7, 0x03f0 _ 0) -NAMED_CHARACTER_REFERENCE(2051, /* v a */ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 9, 0x2205 _ 0) -NAMED_CHARACTER_REFERENCE(2052, /* v a */ 'r' _ 'p' _ 'h' _ 'i' _ ';', 5, 0x03d5 _ 0) -NAMED_CHARACTER_REFERENCE(2053, /* v a */ 'r' _ 'p' _ 'i' _ ';', 4, 0x03d6 _ 0) -NAMED_CHARACTER_REFERENCE(2054, /* v a */ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 8, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(2055, /* v a */ 'r' _ 'r' _ ';', 3, 0x2195 _ 0) -NAMED_CHARACTER_REFERENCE(2056, /* v a */ 'r' _ 'r' _ 'h' _ 'o' _ ';', 5, 0x03f1 _ 0) -NAMED_CHARACTER_REFERENCE(2057, /* v a */ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 7, 0x03c2 _ 0) -NAMED_CHARACTER_REFERENCE(2058, /* v a */ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 7, 0x03d1 _ 0) -NAMED_CHARACTER_REFERENCE(2059, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0x22b2 _ 0) -NAMED_CHARACTER_REFERENCE(2060, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0x22b3 _ 0) -NAMED_CHARACTER_REFERENCE(2061, /* v c */ 'y' _ ';', 2, 0x0432 _ 0) -NAMED_CHARACTER_REFERENCE(2062, /* v d */ 'a' _ 's' _ 'h' _ ';', 4, 0x22a2 _ 0) -NAMED_CHARACTER_REFERENCE(2063, /* v e */ 'e' _ ';', 2, 0x2228 _ 0) -NAMED_CHARACTER_REFERENCE(2064, /* v e */ 'e' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x22bb _ 0) -NAMED_CHARACTER_REFERENCE(2065, /* v e */ 'e' _ 'e' _ 'q' _ ';', 4, 0x225a _ 0) -NAMED_CHARACTER_REFERENCE(2066, /* v e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0x22ee _ 0) -NAMED_CHARACTER_REFERENCE(2067, /* v e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x007c _ 0) -NAMED_CHARACTER_REFERENCE(2068, /* v e */ 'r' _ 't' _ ';', 3, 0x007c _ 0) -NAMED_CHARACTER_REFERENCE(2069, /* v f */ 'r' _ ';', 2, 0xd835 _ 0xdd33) -NAMED_CHARACTER_REFERENCE(2070, /* v l */ 't' _ 'r' _ 'i' _ ';', 4, 0x22b2 _ 0) -NAMED_CHARACTER_REFERENCE(2071, /* v o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd67) -NAMED_CHARACTER_REFERENCE(2072, /* v p */ 'r' _ 'o' _ 'p' _ ';', 4, 0x221d _ 0) -NAMED_CHARACTER_REFERENCE(2073, /* v r */ 't' _ 'r' _ 'i' _ ';', 4, 0x22b3 _ 0) -NAMED_CHARACTER_REFERENCE(2074, /* v s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccb) -NAMED_CHARACTER_REFERENCE(2075, /* v z */ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 6, 0x299a _ 0) -NAMED_CHARACTER_REFERENCE(2076, /* w c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0175 _ 0) -NAMED_CHARACTER_REFERENCE(2077, /* w e */ 'd' _ 'b' _ 'a' _ 'r' _ ';', 5, 0x2a5f _ 0) -NAMED_CHARACTER_REFERENCE(2078, /* w e */ 'd' _ 'g' _ 'e' _ ';', 4, 0x2227 _ 0) -NAMED_CHARACTER_REFERENCE(2079, /* w e */ 'd' _ 'g' _ 'e' _ 'q' _ ';', 5, 0x2259 _ 0) -NAMED_CHARACTER_REFERENCE(2080, /* w e */ 'i' _ 'e' _ 'r' _ 'p' _ ';', 5, 0x2118 _ 0) -NAMED_CHARACTER_REFERENCE(2081, /* w f */ 'r' _ ';', 2, 0xd835 _ 0xdd34) -NAMED_CHARACTER_REFERENCE(2082, /* w o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd68) -NAMED_CHARACTER_REFERENCE(2083, /* w p */ ';', 1, 0x2118 _ 0) -NAMED_CHARACTER_REFERENCE(2084, /* w r */ ';', 1, 0x2240 _ 0) -NAMED_CHARACTER_REFERENCE(2085, /* w r */ 'e' _ 'a' _ 't' _ 'h' _ ';', 5, 0x2240 _ 0) -NAMED_CHARACTER_REFERENCE(2086, /* w s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccc) -NAMED_CHARACTER_REFERENCE(2087, /* x c */ 'a' _ 'p' _ ';', 3, 0x22c2 _ 0) -NAMED_CHARACTER_REFERENCE(2088, /* x c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x25ef _ 0) -NAMED_CHARACTER_REFERENCE(2089, /* x c */ 'u' _ 'p' _ ';', 3, 0x22c3 _ 0) -NAMED_CHARACTER_REFERENCE(2090, /* x d */ 't' _ 'r' _ 'i' _ ';', 4, 0x25bd _ 0) -NAMED_CHARACTER_REFERENCE(2091, /* x f */ 'r' _ ';', 2, 0xd835 _ 0xdd35) -NAMED_CHARACTER_REFERENCE(2092, /* x h */ 'A' _ 'r' _ 'r' _ ';', 4, 0x27fa _ 0) -NAMED_CHARACTER_REFERENCE(2093, /* x h */ 'a' _ 'r' _ 'r' _ ';', 4, 0x27f7 _ 0) -NAMED_CHARACTER_REFERENCE(2094, /* x i */ ';', 1, 0x03be _ 0) -NAMED_CHARACTER_REFERENCE(2095, /* x l */ 'A' _ 'r' _ 'r' _ ';', 4, 0x27f8 _ 0) -NAMED_CHARACTER_REFERENCE(2096, /* x l */ 'a' _ 'r' _ 'r' _ ';', 4, 0x27f5 _ 0) -NAMED_CHARACTER_REFERENCE(2097, /* x m */ 'a' _ 'p' _ ';', 3, 0x27fc _ 0) -NAMED_CHARACTER_REFERENCE(2098, /* x n */ 'i' _ 's' _ ';', 3, 0x22fb _ 0) -NAMED_CHARACTER_REFERENCE(2099, /* x o */ 'd' _ 'o' _ 't' _ ';', 4, 0x2a00 _ 0) -NAMED_CHARACTER_REFERENCE(2100, /* x o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd69) -NAMED_CHARACTER_REFERENCE(2101, /* x o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a01 _ 0) -NAMED_CHARACTER_REFERENCE(2102, /* x o */ 't' _ 'i' _ 'm' _ 'e' _ ';', 5, 0x2a02 _ 0) -NAMED_CHARACTER_REFERENCE(2103, /* x r */ 'A' _ 'r' _ 'r' _ ';', 4, 0x27f9 _ 0) -NAMED_CHARACTER_REFERENCE(2104, /* x r */ 'a' _ 'r' _ 'r' _ ';', 4, 0x27f6 _ 0) -NAMED_CHARACTER_REFERENCE(2105, /* x s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccd) -NAMED_CHARACTER_REFERENCE(2106, /* x s */ 'q' _ 'c' _ 'u' _ 'p' _ ';', 5, 0x2a06 _ 0) -NAMED_CHARACTER_REFERENCE(2107, /* x u */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0x2a04 _ 0) -NAMED_CHARACTER_REFERENCE(2108, /* x u */ 't' _ 'r' _ 'i' _ ';', 4, 0x25b3 _ 0) -NAMED_CHARACTER_REFERENCE(2109, /* x v */ 'e' _ 'e' _ ';', 3, 0x22c1 _ 0) -NAMED_CHARACTER_REFERENCE(2110, /* x w */ 'e' _ 'd' _ 'g' _ 'e' _ ';', 5, 0x22c0 _ 0) -NAMED_CHARACTER_REFERENCE(2111, /* y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0x00fd _ 0) -NAMED_CHARACTER_REFERENCE(2112, /* y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x00fd _ 0) -NAMED_CHARACTER_REFERENCE(2113, /* y a */ 'c' _ 'y' _ ';', 3, 0x044f _ 0) -NAMED_CHARACTER_REFERENCE(2114, /* y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0x0177 _ 0) -NAMED_CHARACTER_REFERENCE(2115, /* y c */ 'y' _ ';', 2, 0x044b _ 0) -NAMED_CHARACTER_REFERENCE(2116, /* y e */ 'n', 1, 0x00a5 _ 0) -NAMED_CHARACTER_REFERENCE(2117, /* y e */ 'n' _ ';', 2, 0x00a5 _ 0) -NAMED_CHARACTER_REFERENCE(2118, /* y f */ 'r' _ ';', 2, 0xd835 _ 0xdd36) -NAMED_CHARACTER_REFERENCE(2119, /* y i */ 'c' _ 'y' _ ';', 3, 0x0457 _ 0) -NAMED_CHARACTER_REFERENCE(2120, /* y o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd6a) -NAMED_CHARACTER_REFERENCE(2121, /* y s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdcce) -NAMED_CHARACTER_REFERENCE(2122, /* y u */ 'c' _ 'y' _ ';', 3, 0x044e _ 0) -NAMED_CHARACTER_REFERENCE(2123, /* y u */ 'm' _ 'l', 2, 0x00ff _ 0) -NAMED_CHARACTER_REFERENCE(2124, /* y u */ 'm' _ 'l' _ ';', 3, 0x00ff _ 0) -NAMED_CHARACTER_REFERENCE(2125, /* z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0x017a _ 0) -NAMED_CHARACTER_REFERENCE(2126, /* z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0x017e _ 0) -NAMED_CHARACTER_REFERENCE(2127, /* z c */ 'y' _ ';', 2, 0x0437 _ 0) -NAMED_CHARACTER_REFERENCE(2128, /* z d */ 'o' _ 't' _ ';', 3, 0x017c _ 0) -NAMED_CHARACTER_REFERENCE(2129, /* z e */ 'e' _ 't' _ 'r' _ 'f' _ ';', 5, 0x2128 _ 0) -NAMED_CHARACTER_REFERENCE(2130, /* z e */ 't' _ 'a' _ ';', 3, 0x03b6 _ 0) -NAMED_CHARACTER_REFERENCE(2131, /* z f */ 'r' _ ';', 2, 0xd835 _ 0xdd37) -NAMED_CHARACTER_REFERENCE(2132, /* z h */ 'c' _ 'y' _ ';', 3, 0x0436 _ 0) -NAMED_CHARACTER_REFERENCE(2133, /* z i */ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0x21dd _ 0) -NAMED_CHARACTER_REFERENCE(2134, /* z o */ 'p' _ 'f' _ ';', 3, 0xd835 _ 0xdd6b) -NAMED_CHARACTER_REFERENCE(2135, /* z s */ 'c' _ 'r' _ ';', 3, 0xd835 _ 0xdccf) -NAMED_CHARACTER_REFERENCE(2136, /* z w */ 'j' _ ';', 2, 0x200d _ 0) -NAMED_CHARACTER_REFERENCE(2137, /* z w */ 'n' _ 'j' _ ';', 3, 0x200c _ 0) +NAMED_CHARACTER_REFERENCE(0, /* A E */ 'l' _ 'i' _ 'g', 3, 0, 0x00c6 _ 0) +NAMED_CHARACTER_REFERENCE(1, /* A E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00c6 _ 0) +NAMED_CHARACTER_REFERENCE(2, /* A M */ 'P', 1, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(3, /* A M */ 'P' _ ';', 2, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(4, /* A a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c1 _ 0) +NAMED_CHARACTER_REFERENCE(5, /* A a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00c1 _ 0) +NAMED_CHARACTER_REFERENCE(6, /* A b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x0102 _ 0) +NAMED_CHARACTER_REFERENCE(7, /* A c */ 'i' _ 'r' _ 'c', 3, 0, 0x00c2 _ 0) +NAMED_CHARACTER_REFERENCE(8, /* A c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00c2 _ 0) +NAMED_CHARACTER_REFERENCE(9, /* A c */ 'y' _ ';', 2, 0, 0x0410 _ 0) +NAMED_CHARACTER_REFERENCE(10, /* A f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd04) +NAMED_CHARACTER_REFERENCE(11, /* A g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c0 _ 0) +NAMED_CHARACTER_REFERENCE(12, /* A g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00c0 _ 0) +NAMED_CHARACTER_REFERENCE(13, /* A l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x0391 _ 0) +NAMED_CHARACTER_REFERENCE(14, /* A m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0100 _ 0) +NAMED_CHARACTER_REFERENCE(15, /* A n */ 'd' _ ';', 2, 0, 0x2a53 _ 0) +NAMED_CHARACTER_REFERENCE(16, /* A o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0104 _ 0) +NAMED_CHARACTER_REFERENCE(17, /* A o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd38) +NAMED_CHARACTER_REFERENCE(18, /* A p */ 'p' _ 'l' _ 'y' _ 'F' _ 'u' _ 'n' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12, 0, 0x2061 _ 0) +NAMED_CHARACTER_REFERENCE(19, /* A r */ 'i' _ 'n' _ 'g', 3, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(20, /* A r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(21, /* A s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9c) +NAMED_CHARACTER_REFERENCE(22, /* A s */ 's' _ 'i' _ 'g' _ 'n' _ ';', 5, 0, 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(23, /* A t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00c3 _ 0) +NAMED_CHARACTER_REFERENCE(24, /* A t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00c3 _ 0) +NAMED_CHARACTER_REFERENCE(25, /* A u */ 'm' _ 'l', 2, 0, 0x00c4 _ 0) +NAMED_CHARACTER_REFERENCE(26, /* A u */ 'm' _ 'l' _ ';', 3, 0, 0x00c4 _ 0) +NAMED_CHARACTER_REFERENCE(27, /* B a */ 'c' _ 'k' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 8, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(28, /* B a */ 'r' _ 'v' _ ';', 3, 0, 0x2ae7 _ 0) +NAMED_CHARACTER_REFERENCE(29, /* B a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0, 0x2306 _ 0) +NAMED_CHARACTER_REFERENCE(30, /* B c */ 'y' _ ';', 2, 0, 0x0411 _ 0) +NAMED_CHARACTER_REFERENCE(31, /* B e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0, 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(32, /* B e */ 'r' _ 'n' _ 'o' _ 'u' _ 'l' _ 'l' _ 'i' _ 's' _ ';', 9, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(33, /* B e */ 't' _ 'a' _ ';', 3, 0, 0x0392 _ 0) +NAMED_CHARACTER_REFERENCE(34, /* B f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd05) +NAMED_CHARACTER_REFERENCE(35, /* B o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd39) +NAMED_CHARACTER_REFERENCE(36, /* B r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0) +NAMED_CHARACTER_REFERENCE(37, /* B s */ 'c' _ 'r' _ ';', 3, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(38, /* B u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(39, /* C H */ 'c' _ 'y' _ ';', 3, 0, 0x0427 _ 0) +NAMED_CHARACTER_REFERENCE(40, /* C O */ 'P' _ 'Y', 2, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(41, /* C O */ 'P' _ 'Y' _ ';', 3, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(42, /* C a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0106 _ 0) +NAMED_CHARACTER_REFERENCE(43, /* C a */ 'p' _ ';', 2, 0, 0x22d2 _ 0) +NAMED_CHARACTER_REFERENCE(44, /* C a */ 'p' _ 'i' _ 't' _ 'a' _ 'l' _ 'D' _ 'i' _ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 19, 0, 0x2145 _ 0) +NAMED_CHARACTER_REFERENCE(45, /* C a */ 'y' _ 'l' _ 'e' _ 'y' _ 's' _ ';', 6, 0, 0x212d _ 0) +NAMED_CHARACTER_REFERENCE(46, /* C c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010c _ 0) +NAMED_CHARACTER_REFERENCE(47, /* C c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00c7 _ 0) +NAMED_CHARACTER_REFERENCE(48, /* C c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x00c7 _ 0) +NAMED_CHARACTER_REFERENCE(49, /* C c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0108 _ 0) +NAMED_CHARACTER_REFERENCE(50, /* C c */ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 6, 0, 0x2230 _ 0) +NAMED_CHARACTER_REFERENCE(51, /* C d */ 'o' _ 't' _ ';', 3, 0, 0x010a _ 0) +NAMED_CHARACTER_REFERENCE(52, /* C e */ 'd' _ 'i' _ 'l' _ 'l' _ 'a' _ ';', 6, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(53, /* C e */ 'n' _ 't' _ 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(54, /* C f */ 'r' _ ';', 2, 0, 0x212d _ 0) +NAMED_CHARACTER_REFERENCE(55, /* C h */ 'i' _ ';', 2, 0, 0x03a7 _ 0) +NAMED_CHARACTER_REFERENCE(56, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x2299 _ 0) +NAMED_CHARACTER_REFERENCE(57, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 10, 0, 0x2296 _ 0) +NAMED_CHARACTER_REFERENCE(58, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 9, 0, 0x2295 _ 0) +NAMED_CHARACTER_REFERENCE(59, /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 10, 0, 0x2297 _ 0) +NAMED_CHARACTER_REFERENCE(60, /* C l */ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 23, 0, 0x2232 _ 0) +NAMED_CHARACTER_REFERENCE(61, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 20, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(62, /* C l */ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 14, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(63, /* C o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x2237 _ 0) +NAMED_CHARACTER_REFERENCE(64, /* C o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0, 0x2a74 _ 0) +NAMED_CHARACTER_REFERENCE(65, /* C o */ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 8, 0, 0x2261 _ 0) +NAMED_CHARACTER_REFERENCE(66, /* C o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0, 0x222f _ 0) +NAMED_CHARACTER_REFERENCE(67, /* C o */ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 14, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(68, /* C o */ 'p' _ 'f' _ ';', 3, 0, 0x2102 _ 0) +NAMED_CHARACTER_REFERENCE(69, /* C o */ 'p' _ 'r' _ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 8, 0, 0x2210 _ 0) +NAMED_CHARACTER_REFERENCE(70, /* C o */ 'u' _ 'n' _ 't' _ 'e' _ 'r' _ 'C' _ 'l' _ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 30, 0, 0x2233 _ 0) +NAMED_CHARACTER_REFERENCE(71, /* C r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2a2f _ 0) +NAMED_CHARACTER_REFERENCE(72, /* C s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9e) +NAMED_CHARACTER_REFERENCE(73, /* C u */ 'p' _ ';', 2, 0, 0x22d3 _ 0) +NAMED_CHARACTER_REFERENCE(74, /* C u */ 'p' _ 'C' _ 'a' _ 'p' _ ';', 5, 0, 0x224d _ 0) +NAMED_CHARACTER_REFERENCE(75, /* D D */ ';', 1, 0, 0x2145 _ 0) +NAMED_CHARACTER_REFERENCE(76, /* D D */ 'o' _ 't' _ 'r' _ 'a' _ 'h' _ 'd' _ ';', 7, 0, 0x2911 _ 0) +NAMED_CHARACTER_REFERENCE(77, /* D J */ 'c' _ 'y' _ ';', 3, 0, 0x0402 _ 0) +NAMED_CHARACTER_REFERENCE(78, /* D S */ 'c' _ 'y' _ ';', 3, 0, 0x0405 _ 0) +NAMED_CHARACTER_REFERENCE(79, /* D Z */ 'c' _ 'y' _ ';', 3, 0, 0x040f _ 0) +NAMED_CHARACTER_REFERENCE(80, /* D a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0, 0x2021 _ 0) +NAMED_CHARACTER_REFERENCE(81, /* D a */ 'r' _ 'r' _ ';', 3, 0, 0x21a1 _ 0) +NAMED_CHARACTER_REFERENCE(82, /* D a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x2ae4 _ 0) +NAMED_CHARACTER_REFERENCE(83, /* D c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010e _ 0) +NAMED_CHARACTER_REFERENCE(84, /* D c */ 'y' _ ';', 2, 0, 0x0414 _ 0) +NAMED_CHARACTER_REFERENCE(85, /* D e */ 'l' _ ';', 2, 0, 0x2207 _ 0) +NAMED_CHARACTER_REFERENCE(86, /* D e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x0394 _ 0) +NAMED_CHARACTER_REFERENCE(87, /* D f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd07) +NAMED_CHARACTER_REFERENCE(88, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 15, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(89, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 't' _ ';', 13, 0, 0x02d9 _ 0) +NAMED_CHARACTER_REFERENCE(90, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';', 21, 0, 0x02dd _ 0) +NAMED_CHARACTER_REFERENCE(91, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'G' _ 'r' _ 'a' _ 'v' _ 'e' _ ';', 15, 0, 0x0060 _ 0) +NAMED_CHARACTER_REFERENCE(92, /* D i */ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 15, 0, 0x02dc _ 0) +NAMED_CHARACTER_REFERENCE(93, /* D i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(94, /* D i */ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 12, 0, 0x2146 _ 0) +NAMED_CHARACTER_REFERENCE(95, /* D o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3b) +NAMED_CHARACTER_REFERENCE(96, /* D o */ 't' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(97, /* D o */ 't' _ 'D' _ 'o' _ 't' _ ';', 5, 0, 0x20dc _ 0) +NAMED_CHARACTER_REFERENCE(98, /* D o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(99, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 20, 0, 0x222f _ 0) +NAMED_CHARACTER_REFERENCE(100, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(101, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(102, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(103, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(104, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 12, 0, 0x2ae4 _ 0) +NAMED_CHARACTER_REFERENCE(105, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(106, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 23, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(107, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 19, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(108, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(109, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 13, 0, 0x22a8 _ 0) +NAMED_CHARACTER_REFERENCE(110, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(111, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(112, /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 16, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(113, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(114, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0, 0x2913 _ 0) +NAMED_CHARACTER_REFERENCE(115, /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x21f5 _ 0) +NAMED_CHARACTER_REFERENCE(116, /* D o */ 'w' _ 'n' _ 'B' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 8, 0, 0x0311 _ 0) +NAMED_CHARACTER_REFERENCE(117, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 18, 0, 0x2950 _ 0) +NAMED_CHARACTER_REFERENCE(118, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x295e _ 0) +NAMED_CHARACTER_REFERENCE(119, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(120, /* D o */ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0, 0x2956 _ 0) +NAMED_CHARACTER_REFERENCE(121, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0, 0x295f _ 0) +NAMED_CHARACTER_REFERENCE(122, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(123, /* D o */ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0, 0x2957 _ 0) +NAMED_CHARACTER_REFERENCE(124, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ ';', 6, 0, 0x22a4 _ 0) +NAMED_CHARACTER_REFERENCE(125, /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0, 0x21a7 _ 0) +NAMED_CHARACTER_REFERENCE(126, /* D o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(127, /* D s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9f) +NAMED_CHARACTER_REFERENCE(128, /* D s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0110 _ 0) +NAMED_CHARACTER_REFERENCE(129, /* E N */ 'G' _ ';', 2, 0, 0x014a _ 0) +NAMED_CHARACTER_REFERENCE(130, /* E T */ 'H', 1, 0, 0x00d0 _ 0) +NAMED_CHARACTER_REFERENCE(131, /* E T */ 'H' _ ';', 2, 0, 0x00d0 _ 0) +NAMED_CHARACTER_REFERENCE(132, /* E a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c9 _ 0) +NAMED_CHARACTER_REFERENCE(133, /* E a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00c9 _ 0) +NAMED_CHARACTER_REFERENCE(134, /* E c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x011a _ 0) +NAMED_CHARACTER_REFERENCE(135, /* E c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ca _ 0) +NAMED_CHARACTER_REFERENCE(136, /* E c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ca _ 0) +NAMED_CHARACTER_REFERENCE(137, /* E c */ 'y' _ ';', 2, 0, 0x042d _ 0) +NAMED_CHARACTER_REFERENCE(138, /* E d */ 'o' _ 't' _ ';', 3, 0, 0x0116 _ 0) +NAMED_CHARACTER_REFERENCE(139, /* E f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd08) +NAMED_CHARACTER_REFERENCE(140, /* E g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c8 _ 0) +NAMED_CHARACTER_REFERENCE(141, /* E g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00c8 _ 0) +NAMED_CHARACTER_REFERENCE(142, /* E l */ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 6, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(143, /* E m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0112 _ 0) +NAMED_CHARACTER_REFERENCE(144, /* E m */ 'p' _ 't' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 15, 0, 0x25fb _ 0) +NAMED_CHARACTER_REFERENCE(145, /* E m */ 'p' _ 't' _ 'y' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 19, 0, 0x25ab _ 0) +NAMED_CHARACTER_REFERENCE(146, /* E o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0118 _ 0) +NAMED_CHARACTER_REFERENCE(147, /* E o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3c) +NAMED_CHARACTER_REFERENCE(148, /* E p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x0395 _ 0) +NAMED_CHARACTER_REFERENCE(149, /* E q */ 'u' _ 'a' _ 'l' _ ';', 4, 0, 0x2a75 _ 0) +NAMED_CHARACTER_REFERENCE(150, /* E q */ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(151, /* E q */ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 10, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(152, /* E s */ 'c' _ 'r' _ ';', 3, 0, 0x2130 _ 0) +NAMED_CHARACTER_REFERENCE(153, /* E s */ 'i' _ 'm' _ ';', 3, 0, 0x2a73 _ 0) +NAMED_CHARACTER_REFERENCE(154, /* E t */ 'a' _ ';', 2, 0, 0x0397 _ 0) +NAMED_CHARACTER_REFERENCE(155, /* E u */ 'm' _ 'l', 2, 0, 0x00cb _ 0) +NAMED_CHARACTER_REFERENCE(156, /* E u */ 'm' _ 'l' _ ';', 3, 0, 0x00cb _ 0) +NAMED_CHARACTER_REFERENCE(157, /* E x */ 'i' _ 's' _ 't' _ 's' _ ';', 5, 0, 0x2203 _ 0) +NAMED_CHARACTER_REFERENCE(158, /* E x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'E' _ ';', 11, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(159, /* F c */ 'y' _ ';', 2, 0, 0x0424 _ 0) +NAMED_CHARACTER_REFERENCE(160, /* F f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd09) +NAMED_CHARACTER_REFERENCE(161, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 16, 0, 0x25fc _ 0) +NAMED_CHARACTER_REFERENCE(162, /* F i */ 'l' _ 'l' _ 'e' _ 'd' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 20, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(163, /* F o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3d) +NAMED_CHARACTER_REFERENCE(164, /* F o */ 'r' _ 'A' _ 'l' _ 'l' _ ';', 5, 0, 0x2200 _ 0) +NAMED_CHARACTER_REFERENCE(165, /* F o */ 'u' _ 'r' _ 'i' _ 'e' _ 'r' _ 't' _ 'r' _ 'f' _ ';', 9, 0, 0x2131 _ 0) +NAMED_CHARACTER_REFERENCE(166, /* F s */ 'c' _ 'r' _ ';', 3, 0, 0x2131 _ 0) +NAMED_CHARACTER_REFERENCE(167, /* G J */ 'c' _ 'y' _ ';', 3, 0, 0x0403 _ 0) +NAMED_CHARACTER_REFERENCE(168, /* G T */ 0, 0, 1, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(169, /* G T */ ';', 1, 0, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(170, /* G a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x0393 _ 0) +NAMED_CHARACTER_REFERENCE(171, /* G a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0, 0x03dc _ 0) +NAMED_CHARACTER_REFERENCE(172, /* G b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x011e _ 0) +NAMED_CHARACTER_REFERENCE(173, /* G c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0122 _ 0) +NAMED_CHARACTER_REFERENCE(174, /* G c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011c _ 0) +NAMED_CHARACTER_REFERENCE(175, /* G c */ 'y' _ ';', 2, 0, 0x0413 _ 0) +NAMED_CHARACTER_REFERENCE(176, /* G d */ 'o' _ 't' _ ';', 3, 0, 0x0120 _ 0) +NAMED_CHARACTER_REFERENCE(177, /* G f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0a) +NAMED_CHARACTER_REFERENCE(178, /* G g */ ';', 1, 0, 0x22d9 _ 0) +NAMED_CHARACTER_REFERENCE(179, /* G o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3e) +NAMED_CHARACTER_REFERENCE(180, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(181, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'L' _ 'e' _ 's' _ 's' _ ';', 15, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(182, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(183, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0, 0x2aa2 _ 0) +NAMED_CHARACTER_REFERENCE(184, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(185, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(186, /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(187, /* G s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca2) +NAMED_CHARACTER_REFERENCE(188, /* G t */ ';', 1, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(189, /* H A */ 'R' _ 'D' _ 'c' _ 'y' _ ';', 5, 0, 0x042a _ 0) +NAMED_CHARACTER_REFERENCE(190, /* H a */ 'c' _ 'e' _ 'k' _ ';', 4, 0, 0x02c7 _ 0) +NAMED_CHARACTER_REFERENCE(191, /* H a */ 't' _ ';', 2, 0, 0x005e _ 0) +NAMED_CHARACTER_REFERENCE(192, /* H c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0124 _ 0) +NAMED_CHARACTER_REFERENCE(193, /* H f */ 'r' _ ';', 2, 0, 0x210c _ 0) +NAMED_CHARACTER_REFERENCE(194, /* H i */ 'l' _ 'b' _ 'e' _ 'r' _ 't' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 11, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(195, /* H o */ 'p' _ 'f' _ ';', 3, 0, 0x210d _ 0) +NAMED_CHARACTER_REFERENCE(196, /* H o */ 'r' _ 'i' _ 'z' _ 'o' _ 'n' _ 't' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 13, 0, 0x2500 _ 0) +NAMED_CHARACTER_REFERENCE(197, /* H s */ 'c' _ 'r' _ ';', 3, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(198, /* H s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0126 _ 0) +NAMED_CHARACTER_REFERENCE(199, /* H u */ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';', 11, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(200, /* H u */ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 8, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(201, /* I E */ 'c' _ 'y' _ ';', 3, 0, 0x0415 _ 0) +NAMED_CHARACTER_REFERENCE(202, /* I J */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0132 _ 0) +NAMED_CHARACTER_REFERENCE(203, /* I O */ 'c' _ 'y' _ ';', 3, 0, 0x0401 _ 0) +NAMED_CHARACTER_REFERENCE(204, /* I a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00cd _ 0) +NAMED_CHARACTER_REFERENCE(205, /* I a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00cd _ 0) +NAMED_CHARACTER_REFERENCE(206, /* I c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ce _ 0) +NAMED_CHARACTER_REFERENCE(207, /* I c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ce _ 0) +NAMED_CHARACTER_REFERENCE(208, /* I c */ 'y' _ ';', 2, 0, 0x0418 _ 0) +NAMED_CHARACTER_REFERENCE(209, /* I d */ 'o' _ 't' _ ';', 3, 0, 0x0130 _ 0) +NAMED_CHARACTER_REFERENCE(210, /* I f */ 'r' _ ';', 2, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(211, /* I g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00cc _ 0) +NAMED_CHARACTER_REFERENCE(212, /* I g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00cc _ 0) +NAMED_CHARACTER_REFERENCE(213, /* I m */ ';', 1, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(214, /* I m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012a _ 0) +NAMED_CHARACTER_REFERENCE(215, /* I m */ 'a' _ 'g' _ 'i' _ 'n' _ 'a' _ 'r' _ 'y' _ 'I' _ ';', 9, 0, 0x2148 _ 0) +NAMED_CHARACTER_REFERENCE(216, /* I m */ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 6, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(217, /* I n */ 't' _ ';', 2, 0, 0x222c _ 0) +NAMED_CHARACTER_REFERENCE(218, /* I n */ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 7, 0, 0x222b _ 0) +NAMED_CHARACTER_REFERENCE(219, /* I n */ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 11, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(220, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'm' _ 'm' _ 'a' _ ';', 13, 0, 0x2063 _ 0) +NAMED_CHARACTER_REFERENCE(221, /* I n */ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0, 0x2062 _ 0) +NAMED_CHARACTER_REFERENCE(222, /* I o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012e _ 0) +NAMED_CHARACTER_REFERENCE(223, /* I o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd40) +NAMED_CHARACTER_REFERENCE(224, /* I o */ 't' _ 'a' _ ';', 3, 0, 0x0399 _ 0) +NAMED_CHARACTER_REFERENCE(225, /* I s */ 'c' _ 'r' _ ';', 3, 0, 0x2110 _ 0) +NAMED_CHARACTER_REFERENCE(226, /* I t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0128 _ 0) +NAMED_CHARACTER_REFERENCE(227, /* I u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0406 _ 0) +NAMED_CHARACTER_REFERENCE(228, /* I u */ 'm' _ 'l', 2, 0, 0x00cf _ 0) +NAMED_CHARACTER_REFERENCE(229, /* I u */ 'm' _ 'l' _ ';', 3, 0, 0x00cf _ 0) +NAMED_CHARACTER_REFERENCE(230, /* J c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0134 _ 0) +NAMED_CHARACTER_REFERENCE(231, /* J c */ 'y' _ ';', 2, 0, 0x0419 _ 0) +NAMED_CHARACTER_REFERENCE(232, /* J f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0d) +NAMED_CHARACTER_REFERENCE(233, /* J o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd41) +NAMED_CHARACTER_REFERENCE(234, /* J s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca5) +NAMED_CHARACTER_REFERENCE(235, /* J s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0, 0x0408 _ 0) +NAMED_CHARACTER_REFERENCE(236, /* J u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0404 _ 0) +NAMED_CHARACTER_REFERENCE(237, /* K H */ 'c' _ 'y' _ ';', 3, 0, 0x0425 _ 0) +NAMED_CHARACTER_REFERENCE(238, /* K J */ 'c' _ 'y' _ ';', 3, 0, 0x040c _ 0) +NAMED_CHARACTER_REFERENCE(239, /* K a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x039a _ 0) +NAMED_CHARACTER_REFERENCE(240, /* K c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0136 _ 0) +NAMED_CHARACTER_REFERENCE(241, /* K c */ 'y' _ ';', 2, 0, 0x041a _ 0) +NAMED_CHARACTER_REFERENCE(242, /* K f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0e) +NAMED_CHARACTER_REFERENCE(243, /* K o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd42) +NAMED_CHARACTER_REFERENCE(244, /* K s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca6) +NAMED_CHARACTER_REFERENCE(245, /* L J */ 'c' _ 'y' _ ';', 3, 0, 0x0409 _ 0) +NAMED_CHARACTER_REFERENCE(246, /* L T */ 0, 0, 1, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(247, /* L T */ ';', 1, 0, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(248, /* L a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0139 _ 0) +NAMED_CHARACTER_REFERENCE(249, /* L a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0, 0x039b _ 0) +NAMED_CHARACTER_REFERENCE(250, /* L a */ 'n' _ 'g' _ ';', 3, 0, 0x27ea _ 0) +NAMED_CHARACTER_REFERENCE(251, /* L a */ 'p' _ 'l' _ 'a' _ 'c' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 9, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(252, /* L a */ 'r' _ 'r' _ ';', 3, 0, 0x219e _ 0) +NAMED_CHARACTER_REFERENCE(253, /* L c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x013d _ 0) +NAMED_CHARACTER_REFERENCE(254, /* L c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x013b _ 0) +NAMED_CHARACTER_REFERENCE(255, /* L c */ 'y' _ ';', 2, 0, 0x041b _ 0) +NAMED_CHARACTER_REFERENCE(256, /* L e */ 'f' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 15, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(257, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(258, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 11, 0, 0x21e4 _ 0) +NAMED_CHARACTER_REFERENCE(259, /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(260, /* L e */ 'f' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 10, 0, 0x2308 _ 0) +NAMED_CHARACTER_REFERENCE(261, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0, 0x27e6 _ 0) +NAMED_CHARACTER_REFERENCE(262, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x2961 _ 0) +NAMED_CHARACTER_REFERENCE(263, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(264, /* L e */ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 16, 0, 0x2959 _ 0) +NAMED_CHARACTER_REFERENCE(265, /* L e */ 'f' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 8, 0, 0x230a _ 0) +NAMED_CHARACTER_REFERENCE(266, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(267, /* L e */ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x294e _ 0) +NAMED_CHARACTER_REFERENCE(268, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 6, 0, 0x22a3 _ 0) +NAMED_CHARACTER_REFERENCE(269, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0, 0x21a4 _ 0) +NAMED_CHARACTER_REFERENCE(270, /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0, 0x295a _ 0) +NAMED_CHARACTER_REFERENCE(271, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 11, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(272, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 14, 0, 0x29cf _ 0) +NAMED_CHARACTER_REFERENCE(273, /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(274, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0, 0x2951 _ 0) +NAMED_CHARACTER_REFERENCE(275, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x2960 _ 0) +NAMED_CHARACTER_REFERENCE(276, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 11, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(277, /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 14, 0, 0x2958 _ 0) +NAMED_CHARACTER_REFERENCE(278, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 9, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(279, /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 12, 0, 0x2952 _ 0) +NAMED_CHARACTER_REFERENCE(280, /* L e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(281, /* L e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(282, /* L e */ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 15, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(283, /* L e */ 's' _ 's' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(284, /* L e */ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 10, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(285, /* L e */ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 7, 0, 0x2aa1 _ 0) +NAMED_CHARACTER_REFERENCE(286, /* L e */ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(287, /* L e */ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 8, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(288, /* L f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0f) +NAMED_CHARACTER_REFERENCE(289, /* L l */ ';', 1, 0, 0x22d8 _ 0) +NAMED_CHARACTER_REFERENCE(290, /* L l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21da _ 0) +NAMED_CHARACTER_REFERENCE(291, /* L m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x013f _ 0) +NAMED_CHARACTER_REFERENCE(292, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(293, /* L o */ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(294, /* L o */ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(295, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(296, /* L o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(297, /* L o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(298, /* L o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd43) +NAMED_CHARACTER_REFERENCE(299, /* L o */ 'w' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(300, /* L o */ 'w' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(301, /* L s */ 'c' _ 'r' _ ';', 3, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(302, /* L s */ 'h' _ ';', 2, 0, 0x21b0 _ 0) +NAMED_CHARACTER_REFERENCE(303, /* L s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0141 _ 0) +NAMED_CHARACTER_REFERENCE(304, /* L t */ ';', 1, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(305, /* M a */ 'p' _ ';', 2, 0, 0x2905 _ 0) +NAMED_CHARACTER_REFERENCE(306, /* M c */ 'y' _ ';', 2, 0, 0x041c _ 0) +NAMED_CHARACTER_REFERENCE(307, /* M e */ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 10, 0, 0x205f _ 0) +NAMED_CHARACTER_REFERENCE(308, /* M e */ 'l' _ 'l' _ 'i' _ 'n' _ 't' _ 'r' _ 'f' _ ';', 8, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(309, /* M f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd10) +NAMED_CHARACTER_REFERENCE(310, /* M i */ 'n' _ 'u' _ 's' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(311, /* M o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd44) +NAMED_CHARACTER_REFERENCE(312, /* M s */ 'c' _ 'r' _ ';', 3, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(313, /* M u */ ';', 1, 0, 0x039c _ 0) +NAMED_CHARACTER_REFERENCE(314, /* N J */ 'c' _ 'y' _ ';', 3, 0, 0x040a _ 0) +NAMED_CHARACTER_REFERENCE(315, /* N a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0143 _ 0) +NAMED_CHARACTER_REFERENCE(316, /* N c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0147 _ 0) +NAMED_CHARACTER_REFERENCE(317, /* N c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0145 _ 0) +NAMED_CHARACTER_REFERENCE(318, /* N c */ 'y' _ ';', 2, 0, 0x041d _ 0) +NAMED_CHARACTER_REFERENCE(319, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'M' _ 'e' _ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 18, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(320, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 17, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(321, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 16, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(322, /* N e */ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'V' _ 'e' _ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 20, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(323, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 19, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(324, /* N e */ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(325, /* N e */ 'w' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 6, 0, 0x000a _ 0) +NAMED_CHARACTER_REFERENCE(326, /* N f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd11) +NAMED_CHARACTER_REFERENCE(327, /* N o */ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ ';', 6, 0, 0x2060 _ 0) +NAMED_CHARACTER_REFERENCE(328, /* N o */ 'n' _ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ 'i' _ 'n' _ 'g' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 15, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(329, /* N o */ 'p' _ 'f' _ ';', 3, 0, 0x2115 _ 0) +NAMED_CHARACTER_REFERENCE(330, /* N o */ 't' _ ';', 2, 0, 0x2aec _ 0) +NAMED_CHARACTER_REFERENCE(331, /* N o */ 't' _ 'C' _ 'o' _ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 11, 0, 0x2262 _ 0) +NAMED_CHARACTER_REFERENCE(332, /* N o */ 't' _ 'C' _ 'u' _ 'p' _ 'C' _ 'a' _ 'p' _ ';', 8, 0, 0x226d _ 0) +NAMED_CHARACTER_REFERENCE(333, /* N o */ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 19, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(334, /* N o */ 't' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(335, /* N o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7, 0, 0x2260 _ 0) +NAMED_CHARACTER_REFERENCE(336, /* N o */ 't' _ 'E' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(337, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 9, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(338, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 14, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(339, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 13, 0, 0x2279 _ 0) +NAMED_CHARACTER_REFERENCE(340, /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 14, 0, 0x2275 _ 0) +NAMED_CHARACTER_REFERENCE(341, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 14, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(342, /* N o */ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(343, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ ';', 6, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(344, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 11, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(345, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 13, 0, 0x2278 _ 0) +NAMED_CHARACTER_REFERENCE(346, /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 11, 0, 0x2274 _ 0) +NAMED_CHARACTER_REFERENCE(347, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 10, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(348, /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0, 0x22e0 _ 0) +NAMED_CHARACTER_REFERENCE(349, /* N o */ 't' _ 'R' _ 'e' _ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 16, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(350, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 15, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(351, /* N o */ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(352, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 19, 0, 0x22e2 _ 0) +NAMED_CHARACTER_REFERENCE(353, /* N o */ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 21, 0, 0x22e3 _ 0) +NAMED_CHARACTER_REFERENCE(354, /* N o */ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(355, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 10, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(356, /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 20, 0, 0x22e1 _ 0) +NAMED_CHARACTER_REFERENCE(357, /* N o */ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 15, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(358, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7, 0, 0x2241 _ 0) +NAMED_CHARACTER_REFERENCE(359, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(360, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x2247 _ 0) +NAMED_CHARACTER_REFERENCE(361, /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(362, /* N o */ 't' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 13, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(363, /* N s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca9) +NAMED_CHARACTER_REFERENCE(364, /* N t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d1 _ 0) +NAMED_CHARACTER_REFERENCE(365, /* N t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00d1 _ 0) +NAMED_CHARACTER_REFERENCE(366, /* N u */ ';', 1, 0, 0x039d _ 0) +NAMED_CHARACTER_REFERENCE(367, /* O E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0152 _ 0) +NAMED_CHARACTER_REFERENCE(368, /* O a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00d3 _ 0) +NAMED_CHARACTER_REFERENCE(369, /* O a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00d3 _ 0) +NAMED_CHARACTER_REFERENCE(370, /* O c */ 'i' _ 'r' _ 'c', 3, 0, 0x00d4 _ 0) +NAMED_CHARACTER_REFERENCE(371, /* O c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00d4 _ 0) +NAMED_CHARACTER_REFERENCE(372, /* O c */ 'y' _ ';', 2, 0, 0x041e _ 0) +NAMED_CHARACTER_REFERENCE(373, /* O d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0150 _ 0) +NAMED_CHARACTER_REFERENCE(374, /* O f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd12) +NAMED_CHARACTER_REFERENCE(375, /* O g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d2 _ 0) +NAMED_CHARACTER_REFERENCE(376, /* O g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00d2 _ 0) +NAMED_CHARACTER_REFERENCE(377, /* O m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014c _ 0) +NAMED_CHARACTER_REFERENCE(378, /* O m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03a9 _ 0) +NAMED_CHARACTER_REFERENCE(379, /* O m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0, 0x039f _ 0) +NAMED_CHARACTER_REFERENCE(380, /* O o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd46) +NAMED_CHARACTER_REFERENCE(381, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 19, 0, 0x201c _ 0) +NAMED_CHARACTER_REFERENCE(382, /* O p */ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';', 13, 0, 0x2018 _ 0) +NAMED_CHARACTER_REFERENCE(383, /* O r */ ';', 1, 0, 0x2a54 _ 0) +NAMED_CHARACTER_REFERENCE(384, /* O s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaa) +NAMED_CHARACTER_REFERENCE(385, /* O s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00d8 _ 0) +NAMED_CHARACTER_REFERENCE(386, /* O s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x00d8 _ 0) +NAMED_CHARACTER_REFERENCE(387, /* O t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d5 _ 0) +NAMED_CHARACTER_REFERENCE(388, /* O t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00d5 _ 0) +NAMED_CHARACTER_REFERENCE(389, /* O t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x2a37 _ 0) +NAMED_CHARACTER_REFERENCE(390, /* O u */ 'm' _ 'l', 2, 0, 0x00d6 _ 0) +NAMED_CHARACTER_REFERENCE(391, /* O u */ 'm' _ 'l' _ ';', 3, 0, 0x00d6 _ 0) +NAMED_CHARACTER_REFERENCE(392, /* O v */ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 6, 0, 0x203e _ 0) +NAMED_CHARACTER_REFERENCE(393, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x23de _ 0) +NAMED_CHARACTER_REFERENCE(394, /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 10, 0, 0x23b4 _ 0) +NAMED_CHARACTER_REFERENCE(395, /* O v */ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 14, 0, 0x23dc _ 0) +NAMED_CHARACTER_REFERENCE(396, /* P a */ 'r' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 7, 0, 0x2202 _ 0) +NAMED_CHARACTER_REFERENCE(397, /* P c */ 'y' _ ';', 2, 0, 0x041f _ 0) +NAMED_CHARACTER_REFERENCE(398, /* P f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd13) +NAMED_CHARACTER_REFERENCE(399, /* P h */ 'i' _ ';', 2, 0, 0x03a6 _ 0) +NAMED_CHARACTER_REFERENCE(400, /* P i */ ';', 1, 0, 0x03a0 _ 0) +NAMED_CHARACTER_REFERENCE(401, /* P l */ 'u' _ 's' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 8, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(402, /* P o */ 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ 'p' _ 'l' _ 'a' _ 'n' _ 'e' _ ';', 12, 0, 0x210c _ 0) +NAMED_CHARACTER_REFERENCE(403, /* P o */ 'p' _ 'f' _ ';', 3, 0, 0x2119 _ 0) +NAMED_CHARACTER_REFERENCE(404, /* P r */ ';', 1, 0, 0x2abb _ 0) +NAMED_CHARACTER_REFERENCE(405, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 7, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(406, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(407, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(408, /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(409, /* P r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2033 _ 0) +NAMED_CHARACTER_REFERENCE(410, /* P r */ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 6, 0, 0x220f _ 0) +NAMED_CHARACTER_REFERENCE(411, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 9, 0, 0x2237 _ 0) +NAMED_CHARACTER_REFERENCE(412, /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ ';', 11, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(413, /* P s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcab) +NAMED_CHARACTER_REFERENCE(414, /* P s */ 'i' _ ';', 2, 0, 0x03a8 _ 0) +NAMED_CHARACTER_REFERENCE(415, /* Q U */ 'O' _ 'T', 2, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(416, /* Q U */ 'O' _ 'T' _ ';', 3, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(417, /* Q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd14) +NAMED_CHARACTER_REFERENCE(418, /* Q o */ 'p' _ 'f' _ ';', 3, 0, 0x211a _ 0) +NAMED_CHARACTER_REFERENCE(419, /* Q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcac) +NAMED_CHARACTER_REFERENCE(420, /* R B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2910 _ 0) +NAMED_CHARACTER_REFERENCE(421, /* R E */ 'G', 1, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(422, /* R E */ 'G' _ ';', 2, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(423, /* R a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0154 _ 0) +NAMED_CHARACTER_REFERENCE(424, /* R a */ 'n' _ 'g' _ ';', 3, 0, 0x27eb _ 0) +NAMED_CHARACTER_REFERENCE(425, /* R a */ 'r' _ 'r' _ ';', 3, 0, 0x21a0 _ 0) +NAMED_CHARACTER_REFERENCE(426, /* R a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, 0x2916 _ 0) +NAMED_CHARACTER_REFERENCE(427, /* R c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0158 _ 0) +NAMED_CHARACTER_REFERENCE(428, /* R c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0156 _ 0) +NAMED_CHARACTER_REFERENCE(429, /* R c */ 'y' _ ';', 2, 0, 0x0420 _ 0) +NAMED_CHARACTER_REFERENCE(430, /* R e */ ';', 1, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(431, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 13, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(432, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 17, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(433, /* R e */ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'U' _ 'p' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 19, 0, 0x296f _ 0) +NAMED_CHARACTER_REFERENCE(434, /* R f */ 'r' _ ';', 2, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(435, /* R h */ 'o' _ ';', 2, 0, 0x03a1 _ 0) +NAMED_CHARACTER_REFERENCE(436, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 16, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(437, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(438, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 12, 0, 0x21e5 _ 0) +NAMED_CHARACTER_REFERENCE(439, /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(440, /* R i */ 'g' _ 'h' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 11, 0, 0x2309 _ 0) +NAMED_CHARACTER_REFERENCE(441, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 17, 0, 0x27e7 _ 0) +NAMED_CHARACTER_REFERENCE(442, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 17, 0, 0x295d _ 0) +NAMED_CHARACTER_REFERENCE(443, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 14, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(444, /* R i */ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 17, 0, 0x2955 _ 0) +NAMED_CHARACTER_REFERENCE(445, /* R i */ 'g' _ 'h' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 9, 0, 0x230b _ 0) +NAMED_CHARACTER_REFERENCE(446, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 7, 0, 0x22a2 _ 0) +NAMED_CHARACTER_REFERENCE(447, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(448, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 13, 0, 0x295b _ 0) +NAMED_CHARACTER_REFERENCE(449, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(450, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';', 15, 0, 0x29d0 _ 0) +NAMED_CHARACTER_REFERENCE(451, /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(452, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x294f _ 0) +NAMED_CHARACTER_REFERENCE(453, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 15, 0, 0x295c _ 0) +NAMED_CHARACTER_REFERENCE(454, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(455, /* R i */ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 15, 0, 0x2954 _ 0) +NAMED_CHARACTER_REFERENCE(456, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 10, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(457, /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 13, 0, 0x2953 _ 0) +NAMED_CHARACTER_REFERENCE(458, /* R i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(459, /* R o */ 'p' _ 'f' _ ';', 3, 0, 0x211d _ 0) +NAMED_CHARACTER_REFERENCE(460, /* R o */ 'u' _ 'n' _ 'd' _ 'I' _ 'm' _ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 11, 0, 0x2970 _ 0) +NAMED_CHARACTER_REFERENCE(461, /* R r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x21db _ 0) +NAMED_CHARACTER_REFERENCE(462, /* R s */ 'c' _ 'r' _ ';', 3, 0, 0x211b _ 0) +NAMED_CHARACTER_REFERENCE(463, /* R s */ 'h' _ ';', 2, 0, 0x21b1 _ 0) +NAMED_CHARACTER_REFERENCE(464, /* R u */ 'l' _ 'e' _ 'D' _ 'e' _ 'l' _ 'a' _ 'y' _ 'e' _ 'd' _ ';', 10, 0, 0x29f4 _ 0) +NAMED_CHARACTER_REFERENCE(465, /* S H */ 'C' _ 'H' _ 'c' _ 'y' _ ';', 5, 0, 0x0429 _ 0) +NAMED_CHARACTER_REFERENCE(466, /* S H */ 'c' _ 'y' _ ';', 3, 0, 0x0428 _ 0) +NAMED_CHARACTER_REFERENCE(467, /* S O */ 'F' _ 'T' _ 'c' _ 'y' _ ';', 5, 0, 0x042c _ 0) +NAMED_CHARACTER_REFERENCE(468, /* S a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x015a _ 0) +NAMED_CHARACTER_REFERENCE(469, /* S c */ ';', 1, 0, 0x2abc _ 0) +NAMED_CHARACTER_REFERENCE(470, /* S c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0160 _ 0) +NAMED_CHARACTER_REFERENCE(471, /* S c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x015e _ 0) +NAMED_CHARACTER_REFERENCE(472, /* S c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015c _ 0) +NAMED_CHARACTER_REFERENCE(473, /* S c */ 'y' _ ';', 2, 0, 0x0421 _ 0) +NAMED_CHARACTER_REFERENCE(474, /* S f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd16) +NAMED_CHARACTER_REFERENCE(475, /* S h */ 'o' _ 'r' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(476, /* S h */ 'o' _ 'r' _ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(477, /* S h */ 'o' _ 'r' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(478, /* S h */ 'o' _ 'r' _ 't' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 11, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(479, /* S i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03a3 _ 0) +NAMED_CHARACTER_REFERENCE(480, /* S m */ 'a' _ 'l' _ 'l' _ 'C' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ ';', 10, 0, 0x2218 _ 0) +NAMED_CHARACTER_REFERENCE(481, /* S o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4a) +NAMED_CHARACTER_REFERENCE(482, /* S q */ 'r' _ 't' _ ';', 3, 0, 0x221a _ 0) +NAMED_CHARACTER_REFERENCE(483, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(484, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'I' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 17, 0, 0x2293 _ 0) +NAMED_CHARACTER_REFERENCE(485, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 11, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(486, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 16, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(487, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 13, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(488, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 18, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(489, /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'U' _ 'n' _ 'i' _ 'o' _ 'n' _ ';', 10, 0, 0x2294 _ 0) +NAMED_CHARACTER_REFERENCE(490, /* S s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcae) +NAMED_CHARACTER_REFERENCE(491, /* S t */ 'a' _ 'r' _ ';', 3, 0, 0x22c6 _ 0) +NAMED_CHARACTER_REFERENCE(492, /* S u */ 'b' _ ';', 2, 0, 0x22d0 _ 0) +NAMED_CHARACTER_REFERENCE(493, /* S u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x22d0 _ 0) +NAMED_CHARACTER_REFERENCE(494, /* S u */ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 10, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(495, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 7, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(496, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(497, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 17, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(498, /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(499, /* S u */ 'c' _ 'h' _ 'T' _ 'h' _ 'a' _ 't' _ ';', 7, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(500, /* S u */ 'm' _ ';', 2, 0, 0x2211 _ 0) +NAMED_CHARACTER_REFERENCE(501, /* S u */ 'p' _ ';', 2, 0, 0x22d1 _ 0) +NAMED_CHARACTER_REFERENCE(502, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(503, /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(504, /* S u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x22d1 _ 0) +NAMED_CHARACTER_REFERENCE(505, /* T H */ 'O' _ 'R' _ 'N', 3, 0, 0x00de _ 0) +NAMED_CHARACTER_REFERENCE(506, /* T H */ 'O' _ 'R' _ 'N' _ ';', 4, 0, 0x00de _ 0) +NAMED_CHARACTER_REFERENCE(507, /* T R */ 'A' _ 'D' _ 'E' _ ';', 4, 0, 0x2122 _ 0) +NAMED_CHARACTER_REFERENCE(508, /* T S */ 'H' _ 'c' _ 'y' _ ';', 4, 0, 0x040b _ 0) +NAMED_CHARACTER_REFERENCE(509, /* T S */ 'c' _ 'y' _ ';', 3, 0, 0x0426 _ 0) +NAMED_CHARACTER_REFERENCE(510, /* T a */ 'b' _ ';', 2, 0, 0x0009 _ 0) +NAMED_CHARACTER_REFERENCE(511, /* T a */ 'u' _ ';', 2, 0, 0x03a4 _ 0) +NAMED_CHARACTER_REFERENCE(512, /* T c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0164 _ 0) +NAMED_CHARACTER_REFERENCE(513, /* T c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0162 _ 0) +NAMED_CHARACTER_REFERENCE(514, /* T c */ 'y' _ ';', 2, 0, 0x0422 _ 0) +NAMED_CHARACTER_REFERENCE(515, /* T f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd17) +NAMED_CHARACTER_REFERENCE(516, /* T h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(517, /* T h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x0398 _ 0) +NAMED_CHARACTER_REFERENCE(518, /* T h */ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x2009 _ 0) +NAMED_CHARACTER_REFERENCE(519, /* T i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(520, /* T i */ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 9, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(521, /* T i */ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 13, 0, 0x2245 _ 0) +NAMED_CHARACTER_REFERENCE(522, /* T i */ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(523, /* T o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4b) +NAMED_CHARACTER_REFERENCE(524, /* T r */ 'i' _ 'p' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x20db _ 0) +NAMED_CHARACTER_REFERENCE(525, /* T s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaf) +NAMED_CHARACTER_REFERENCE(526, /* T s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0166 _ 0) +NAMED_CHARACTER_REFERENCE(527, /* U a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00da _ 0) +NAMED_CHARACTER_REFERENCE(528, /* U a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00da _ 0) +NAMED_CHARACTER_REFERENCE(529, /* U a */ 'r' _ 'r' _ ';', 3, 0, 0x219f _ 0) +NAMED_CHARACTER_REFERENCE(530, /* U a */ 'r' _ 'r' _ 'o' _ 'c' _ 'i' _ 'r' _ ';', 7, 0, 0x2949 _ 0) +NAMED_CHARACTER_REFERENCE(531, /* U b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x040e _ 0) +NAMED_CHARACTER_REFERENCE(532, /* U b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x016c _ 0) +NAMED_CHARACTER_REFERENCE(533, /* U c */ 'i' _ 'r' _ 'c', 3, 0, 0x00db _ 0) +NAMED_CHARACTER_REFERENCE(534, /* U c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00db _ 0) +NAMED_CHARACTER_REFERENCE(535, /* U c */ 'y' _ ';', 2, 0, 0x0423 _ 0) +NAMED_CHARACTER_REFERENCE(536, /* U d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0170 _ 0) +NAMED_CHARACTER_REFERENCE(537, /* U f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd18) +NAMED_CHARACTER_REFERENCE(538, /* U g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d9 _ 0) +NAMED_CHARACTER_REFERENCE(539, /* U g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00d9 _ 0) +NAMED_CHARACTER_REFERENCE(540, /* U m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016a _ 0) +NAMED_CHARACTER_REFERENCE(541, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 7, 0, 0x005f _ 0) +NAMED_CHARACTER_REFERENCE(542, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 9, 0, 0x23df _ 0) +NAMED_CHARACTER_REFERENCE(543, /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 11, 0, 0x23b5 _ 0) +NAMED_CHARACTER_REFERENCE(544, /* U n */ 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';', 15, 0, 0x23dd _ 0) +NAMED_CHARACTER_REFERENCE(545, /* U n */ 'i' _ 'o' _ 'n' _ ';', 4, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(546, /* U n */ 'i' _ 'o' _ 'n' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x228e _ 0) +NAMED_CHARACTER_REFERENCE(547, /* U o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0172 _ 0) +NAMED_CHARACTER_REFERENCE(548, /* U o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4c) +NAMED_CHARACTER_REFERENCE(549, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(550, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 9, 0, 0x2912 _ 0) +NAMED_CHARACTER_REFERENCE(551, /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x21c5 _ 0) +NAMED_CHARACTER_REFERENCE(552, /* U p */ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(553, /* U p */ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 12, 0, 0x296e _ 0) +NAMED_CHARACTER_REFERENCE(554, /* U p */ 'T' _ 'e' _ 'e' _ ';', 4, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(555, /* U p */ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21a5 _ 0) +NAMED_CHARACTER_REFERENCE(556, /* U p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(557, /* U p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(558, /* U p */ 'p' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(559, /* U p */ 'p' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(560, /* U p */ 's' _ 'i' _ ';', 3, 0, 0x03d2 _ 0) +NAMED_CHARACTER_REFERENCE(561, /* U p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x03a5 _ 0) +NAMED_CHARACTER_REFERENCE(562, /* U r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016e _ 0) +NAMED_CHARACTER_REFERENCE(563, /* U s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb0) +NAMED_CHARACTER_REFERENCE(564, /* U t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0168 _ 0) +NAMED_CHARACTER_REFERENCE(565, /* U u */ 'm' _ 'l', 2, 0, 0x00dc _ 0) +NAMED_CHARACTER_REFERENCE(566, /* U u */ 'm' _ 'l' _ ';', 3, 0, 0x00dc _ 0) +NAMED_CHARACTER_REFERENCE(567, /* V D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22ab _ 0) +NAMED_CHARACTER_REFERENCE(568, /* V b */ 'a' _ 'r' _ ';', 3, 0, 0x2aeb _ 0) +NAMED_CHARACTER_REFERENCE(569, /* V c */ 'y' _ ';', 2, 0, 0x0412 _ 0) +NAMED_CHARACTER_REFERENCE(570, /* V d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a9 _ 0) +NAMED_CHARACTER_REFERENCE(571, /* V d */ 'a' _ 's' _ 'h' _ 'l' _ ';', 5, 0, 0x2ae6 _ 0) +NAMED_CHARACTER_REFERENCE(572, /* V e */ 'e' _ ';', 2, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(573, /* V e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x2016 _ 0) +NAMED_CHARACTER_REFERENCE(574, /* V e */ 'r' _ 't' _ ';', 3, 0, 0x2016 _ 0) +NAMED_CHARACTER_REFERENCE(575, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 10, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(576, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 11, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(577, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'S' _ 'e' _ 'p' _ 'a' _ 'r' _ 'a' _ 't' _ 'o' _ 'r' _ ';', 16, 0, 0x2758 _ 0) +NAMED_CHARACTER_REFERENCE(578, /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(579, /* V e */ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 12, 0, 0x200a _ 0) +NAMED_CHARACTER_REFERENCE(580, /* V f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd19) +NAMED_CHARACTER_REFERENCE(581, /* V o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4d) +NAMED_CHARACTER_REFERENCE(582, /* V s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb1) +NAMED_CHARACTER_REFERENCE(583, /* V v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22aa _ 0) +NAMED_CHARACTER_REFERENCE(584, /* W c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0174 _ 0) +NAMED_CHARACTER_REFERENCE(585, /* W e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(586, /* W f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1a) +NAMED_CHARACTER_REFERENCE(587, /* W o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4e) +NAMED_CHARACTER_REFERENCE(588, /* W s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb2) +NAMED_CHARACTER_REFERENCE(589, /* X f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1b) +NAMED_CHARACTER_REFERENCE(590, /* X i */ ';', 1, 0, 0x039e _ 0) +NAMED_CHARACTER_REFERENCE(591, /* X o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4f) +NAMED_CHARACTER_REFERENCE(592, /* X s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb3) +NAMED_CHARACTER_REFERENCE(593, /* Y A */ 'c' _ 'y' _ ';', 3, 0, 0x042f _ 0) +NAMED_CHARACTER_REFERENCE(594, /* Y I */ 'c' _ 'y' _ ';', 3, 0, 0x0407 _ 0) +NAMED_CHARACTER_REFERENCE(595, /* Y U */ 'c' _ 'y' _ ';', 3, 0, 0x042e _ 0) +NAMED_CHARACTER_REFERENCE(596, /* Y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00dd _ 0) +NAMED_CHARACTER_REFERENCE(597, /* Y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00dd _ 0) +NAMED_CHARACTER_REFERENCE(598, /* Y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0176 _ 0) +NAMED_CHARACTER_REFERENCE(599, /* Y c */ 'y' _ ';', 2, 0, 0x042b _ 0) +NAMED_CHARACTER_REFERENCE(600, /* Y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1c) +NAMED_CHARACTER_REFERENCE(601, /* Y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd50) +NAMED_CHARACTER_REFERENCE(602, /* Y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb4) +NAMED_CHARACTER_REFERENCE(603, /* Y u */ 'm' _ 'l' _ ';', 3, 0, 0x0178 _ 0) +NAMED_CHARACTER_REFERENCE(604, /* Z H */ 'c' _ 'y' _ ';', 3, 0, 0x0416 _ 0) +NAMED_CHARACTER_REFERENCE(605, /* Z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0179 _ 0) +NAMED_CHARACTER_REFERENCE(606, /* Z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x017d _ 0) +NAMED_CHARACTER_REFERENCE(607, /* Z c */ 'y' _ ';', 2, 0, 0x0417 _ 0) +NAMED_CHARACTER_REFERENCE(608, /* Z d */ 'o' _ 't' _ ';', 3, 0, 0x017b _ 0) +NAMED_CHARACTER_REFERENCE(609, /* Z e */ 'r' _ 'o' _ 'W' _ 'i' _ 'd' _ 't' _ 'h' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 13, 0, 0x200b _ 0) +NAMED_CHARACTER_REFERENCE(610, /* Z e */ 't' _ 'a' _ ';', 3, 0, 0x0396 _ 0) +NAMED_CHARACTER_REFERENCE(611, /* Z f */ 'r' _ ';', 2, 0, 0x2128 _ 0) +NAMED_CHARACTER_REFERENCE(612, /* Z o */ 'p' _ 'f' _ ';', 3, 0, 0x2124 _ 0) +NAMED_CHARACTER_REFERENCE(613, /* Z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb5) +NAMED_CHARACTER_REFERENCE(614, /* a a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e1 _ 0) +NAMED_CHARACTER_REFERENCE(615, /* a a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00e1 _ 0) +NAMED_CHARACTER_REFERENCE(616, /* a b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x0103 _ 0) +NAMED_CHARACTER_REFERENCE(617, /* a c */ ';', 1, 0, 0x223e _ 0) +NAMED_CHARACTER_REFERENCE(618, /* a c */ 'd' _ ';', 2, 0, 0x223f _ 0) +NAMED_CHARACTER_REFERENCE(619, /* a c */ 'i' _ 'r' _ 'c', 3, 0, 0x00e2 _ 0) +NAMED_CHARACTER_REFERENCE(620, /* a c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00e2 _ 0) +NAMED_CHARACTER_REFERENCE(621, /* a c */ 'u' _ 't' _ 'e', 3, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(622, /* a c */ 'u' _ 't' _ 'e' _ ';', 4, 0, 0x00b4 _ 0) +NAMED_CHARACTER_REFERENCE(623, /* a c */ 'y' _ ';', 2, 0, 0x0430 _ 0) +NAMED_CHARACTER_REFERENCE(624, /* a e */ 'l' _ 'i' _ 'g', 3, 0, 0x00e6 _ 0) +NAMED_CHARACTER_REFERENCE(625, /* a e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00e6 _ 0) +NAMED_CHARACTER_REFERENCE(626, /* a f */ ';', 1, 0, 0x2061 _ 0) +NAMED_CHARACTER_REFERENCE(627, /* a f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1e) +NAMED_CHARACTER_REFERENCE(628, /* a g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e0 _ 0) +NAMED_CHARACTER_REFERENCE(629, /* a g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00e0 _ 0) +NAMED_CHARACTER_REFERENCE(630, /* a l */ 'e' _ 'f' _ 's' _ 'y' _ 'm' _ ';', 6, 0, 0x2135 _ 0) +NAMED_CHARACTER_REFERENCE(631, /* a l */ 'e' _ 'p' _ 'h' _ ';', 4, 0, 0x2135 _ 0) +NAMED_CHARACTER_REFERENCE(632, /* a l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x03b1 _ 0) +NAMED_CHARACTER_REFERENCE(633, /* a m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0101 _ 0) +NAMED_CHARACTER_REFERENCE(634, /* a m */ 'a' _ 'l' _ 'g' _ ';', 4, 0, 0x2a3f _ 0) +NAMED_CHARACTER_REFERENCE(635, /* a m */ 'p', 1, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(636, /* a m */ 'p' _ ';', 2, 0, 0x0026 _ 0) +NAMED_CHARACTER_REFERENCE(637, /* a n */ 'd' _ ';', 2, 0, 0x2227 _ 0) +NAMED_CHARACTER_REFERENCE(638, /* a n */ 'd' _ 'a' _ 'n' _ 'd' _ ';', 5, 0, 0x2a55 _ 0) +NAMED_CHARACTER_REFERENCE(639, /* a n */ 'd' _ 'd' _ ';', 3, 0, 0x2a5c _ 0) +NAMED_CHARACTER_REFERENCE(640, /* a n */ 'd' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 7, 0, 0x2a58 _ 0) +NAMED_CHARACTER_REFERENCE(641, /* a n */ 'd' _ 'v' _ ';', 3, 0, 0x2a5a _ 0) +NAMED_CHARACTER_REFERENCE(642, /* a n */ 'g' _ ';', 2, 0, 0x2220 _ 0) +NAMED_CHARACTER_REFERENCE(643, /* a n */ 'g' _ 'e' _ ';', 3, 0, 0x29a4 _ 0) +NAMED_CHARACTER_REFERENCE(644, /* a n */ 'g' _ 'l' _ 'e' _ ';', 4, 0, 0x2220 _ 0) +NAMED_CHARACTER_REFERENCE(645, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ ';', 5, 0, 0x2221 _ 0) +NAMED_CHARACTER_REFERENCE(646, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'a' _ ';', 7, 0, 0x29a8 _ 0) +NAMED_CHARACTER_REFERENCE(647, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'b' _ ';', 7, 0, 0x29a9 _ 0) +NAMED_CHARACTER_REFERENCE(648, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'c' _ ';', 7, 0, 0x29aa _ 0) +NAMED_CHARACTER_REFERENCE(649, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'd' _ ';', 7, 0, 0x29ab _ 0) +NAMED_CHARACTER_REFERENCE(650, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'e' _ ';', 7, 0, 0x29ac _ 0) +NAMED_CHARACTER_REFERENCE(651, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'f' _ ';', 7, 0, 0x29ad _ 0) +NAMED_CHARACTER_REFERENCE(652, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'g' _ ';', 7, 0, 0x29ae _ 0) +NAMED_CHARACTER_REFERENCE(653, /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'h' _ ';', 7, 0, 0x29af _ 0) +NAMED_CHARACTER_REFERENCE(654, /* a n */ 'g' _ 'r' _ 't' _ ';', 4, 0, 0x221f _ 0) +NAMED_CHARACTER_REFERENCE(655, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 6, 0, 0x22be _ 0) +NAMED_CHARACTER_REFERENCE(656, /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 7, 0, 0x299d _ 0) +NAMED_CHARACTER_REFERENCE(657, /* a n */ 'g' _ 's' _ 'p' _ 'h' _ ';', 5, 0, 0x2222 _ 0) +NAMED_CHARACTER_REFERENCE(658, /* a n */ 'g' _ 's' _ 't' _ ';', 4, 0, 0x00c5 _ 0) +NAMED_CHARACTER_REFERENCE(659, /* a n */ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x237c _ 0) +NAMED_CHARACTER_REFERENCE(660, /* a o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0105 _ 0) +NAMED_CHARACTER_REFERENCE(661, /* a o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd52) +NAMED_CHARACTER_REFERENCE(662, /* a p */ ';', 1, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(663, /* a p */ 'E' _ ';', 2, 0, 0x2a70 _ 0) +NAMED_CHARACTER_REFERENCE(664, /* a p */ 'a' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, 0x2a6f _ 0) +NAMED_CHARACTER_REFERENCE(665, /* a p */ 'e' _ ';', 2, 0, 0x224a _ 0) +NAMED_CHARACTER_REFERENCE(666, /* a p */ 'i' _ 'd' _ ';', 3, 0, 0x224b _ 0) +NAMED_CHARACTER_REFERENCE(667, /* a p */ 'o' _ 's' _ ';', 3, 0, 0x0027 _ 0) +NAMED_CHARACTER_REFERENCE(668, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ ';', 5, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(669, /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ 'e' _ 'q' _ ';', 7, 0, 0x224a _ 0) +NAMED_CHARACTER_REFERENCE(670, /* a r */ 'i' _ 'n' _ 'g', 3, 0, 0x00e5 _ 0) +NAMED_CHARACTER_REFERENCE(671, /* a r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00e5 _ 0) +NAMED_CHARACTER_REFERENCE(672, /* a s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb6) +NAMED_CHARACTER_REFERENCE(673, /* a s */ 't' _ ';', 2, 0, 0x002a _ 0) +NAMED_CHARACTER_REFERENCE(674, /* a s */ 'y' _ 'm' _ 'p' _ ';', 4, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(675, /* a s */ 'y' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 6, 0, 0x224d _ 0) +NAMED_CHARACTER_REFERENCE(676, /* a t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00e3 _ 0) +NAMED_CHARACTER_REFERENCE(677, /* a t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00e3 _ 0) +NAMED_CHARACTER_REFERENCE(678, /* a u */ 'm' _ 'l', 2, 0, 0x00e4 _ 0) +NAMED_CHARACTER_REFERENCE(679, /* a u */ 'm' _ 'l' _ ';', 3, 0, 0x00e4 _ 0) +NAMED_CHARACTER_REFERENCE(680, /* a w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2233 _ 0) +NAMED_CHARACTER_REFERENCE(681, /* a w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2a11 _ 0) +NAMED_CHARACTER_REFERENCE(682, /* b N */ 'o' _ 't' _ ';', 3, 0, 0x2aed _ 0) +NAMED_CHARACTER_REFERENCE(683, /* b a */ 'c' _ 'k' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 7, 0, 0x224c _ 0) +NAMED_CHARACTER_REFERENCE(684, /* b a */ 'c' _ 'k' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 10, 0, 0x03f6 _ 0) +NAMED_CHARACTER_REFERENCE(685, /* b a */ 'c' _ 'k' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 8, 0, 0x2035 _ 0) +NAMED_CHARACTER_REFERENCE(686, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x223d _ 0) +NAMED_CHARACTER_REFERENCE(687, /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 8, 0, 0x22cd _ 0) +NAMED_CHARACTER_REFERENCE(688, /* b a */ 'r' _ 'v' _ 'e' _ 'e' _ ';', 5, 0, 0x22bd _ 0) +NAMED_CHARACTER_REFERENCE(689, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0, 0x2305 _ 0) +NAMED_CHARACTER_REFERENCE(690, /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0, 0x2305 _ 0) +NAMED_CHARACTER_REFERENCE(691, /* b b */ 'r' _ 'k' _ ';', 3, 0, 0x23b5 _ 0) +NAMED_CHARACTER_REFERENCE(692, /* b b */ 'r' _ 'k' _ 't' _ 'b' _ 'r' _ 'k' _ ';', 7, 0, 0x23b6 _ 0) +NAMED_CHARACTER_REFERENCE(693, /* b c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x224c _ 0) +NAMED_CHARACTER_REFERENCE(694, /* b c */ 'y' _ ';', 2, 0, 0x0431 _ 0) +NAMED_CHARACTER_REFERENCE(695, /* b d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201e _ 0) +NAMED_CHARACTER_REFERENCE(696, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ ';', 5, 0, 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(697, /* b e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0, 0x2235 _ 0) +NAMED_CHARACTER_REFERENCE(698, /* b e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, 0x29b0 _ 0) +NAMED_CHARACTER_REFERENCE(699, /* b e */ 'p' _ 's' _ 'i' _ ';', 4, 0, 0x03f6 _ 0) +NAMED_CHARACTER_REFERENCE(700, /* b e */ 'r' _ 'n' _ 'o' _ 'u' _ ';', 5, 0, 0x212c _ 0) +NAMED_CHARACTER_REFERENCE(701, /* b e */ 't' _ 'a' _ ';', 3, 0, 0x03b2 _ 0) +NAMED_CHARACTER_REFERENCE(702, /* b e */ 't' _ 'h' _ ';', 3, 0, 0x2136 _ 0) +NAMED_CHARACTER_REFERENCE(703, /* b e */ 't' _ 'w' _ 'e' _ 'e' _ 'n' _ ';', 6, 0, 0x226c _ 0) +NAMED_CHARACTER_REFERENCE(704, /* b f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1f) +NAMED_CHARACTER_REFERENCE(705, /* b i */ 'g' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(706, /* b i */ 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0, 0x25ef _ 0) +NAMED_CHARACTER_REFERENCE(707, /* b i */ 'g' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(708, /* b i */ 'g' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2a00 _ 0) +NAMED_CHARACTER_REFERENCE(709, /* b i */ 'g' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0, 0x2a01 _ 0) +NAMED_CHARACTER_REFERENCE(710, /* b i */ 'g' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0, 0x2a02 _ 0) +NAMED_CHARACTER_REFERENCE(711, /* b i */ 'g' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7, 0, 0x2a06 _ 0) +NAMED_CHARACTER_REFERENCE(712, /* b i */ 'g' _ 's' _ 't' _ 'a' _ 'r' _ ';', 6, 0, 0x2605 _ 0) +NAMED_CHARACTER_REFERENCE(713, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0, 0x25bd _ 0) +NAMED_CHARACTER_REFERENCE(714, /* b i */ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'u' _ 'p' _ ';', 12, 0, 0x25b3 _ 0) +NAMED_CHARACTER_REFERENCE(715, /* b i */ 'g' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7, 0, 0x2a04 _ 0) +NAMED_CHARACTER_REFERENCE(716, /* b i */ 'g' _ 'v' _ 'e' _ 'e' _ ';', 5, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(717, /* b i */ 'g' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(718, /* b k */ 'a' _ 'r' _ 'o' _ 'w' _ ';', 5, 0, 0x290d _ 0) +NAMED_CHARACTER_REFERENCE(719, /* b l */ 'a' _ 'c' _ 'k' _ 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 11, 0, 0x29eb _ 0) +NAMED_CHARACTER_REFERENCE(720, /* b l */ 'a' _ 'c' _ 'k' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(721, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0, 0x25b4 _ 0) +NAMED_CHARACTER_REFERENCE(722, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 16, 0, 0x25be _ 0) +NAMED_CHARACTER_REFERENCE(723, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 16, 0, 0x25c2 _ 0) +NAMED_CHARACTER_REFERENCE(724, /* b l */ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 17, 0, 0x25b8 _ 0) +NAMED_CHARACTER_REFERENCE(725, /* b l */ 'a' _ 'n' _ 'k' _ ';', 4, 0, 0x2423 _ 0) +NAMED_CHARACTER_REFERENCE(726, /* b l */ 'k' _ '1' _ '2' _ ';', 4, 0, 0x2592 _ 0) +NAMED_CHARACTER_REFERENCE(727, /* b l */ 'k' _ '1' _ '4' _ ';', 4, 0, 0x2591 _ 0) +NAMED_CHARACTER_REFERENCE(728, /* b l */ 'k' _ '3' _ '4' _ ';', 4, 0, 0x2593 _ 0) +NAMED_CHARACTER_REFERENCE(729, /* b l */ 'o' _ 'c' _ 'k' _ ';', 4, 0, 0x2588 _ 0) +NAMED_CHARACTER_REFERENCE(730, /* b n */ 'o' _ 't' _ ';', 3, 0, 0x2310 _ 0) +NAMED_CHARACTER_REFERENCE(731, /* b o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd53) +NAMED_CHARACTER_REFERENCE(732, /* b o */ 't' _ ';', 2, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(733, /* b o */ 't' _ 't' _ 'o' _ 'm' _ ';', 5, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(734, /* b o */ 'w' _ 't' _ 'i' _ 'e' _ ';', 5, 0, 0x22c8 _ 0) +NAMED_CHARACTER_REFERENCE(735, /* b o */ 'x' _ 'D' _ 'L' _ ';', 4, 0, 0x2557 _ 0) +NAMED_CHARACTER_REFERENCE(736, /* b o */ 'x' _ 'D' _ 'R' _ ';', 4, 0, 0x2554 _ 0) +NAMED_CHARACTER_REFERENCE(737, /* b o */ 'x' _ 'D' _ 'l' _ ';', 4, 0, 0x2556 _ 0) +NAMED_CHARACTER_REFERENCE(738, /* b o */ 'x' _ 'D' _ 'r' _ ';', 4, 0, 0x2553 _ 0) +NAMED_CHARACTER_REFERENCE(739, /* b o */ 'x' _ 'H' _ ';', 3, 0, 0x2550 _ 0) +NAMED_CHARACTER_REFERENCE(740, /* b o */ 'x' _ 'H' _ 'D' _ ';', 4, 0, 0x2566 _ 0) +NAMED_CHARACTER_REFERENCE(741, /* b o */ 'x' _ 'H' _ 'U' _ ';', 4, 0, 0x2569 _ 0) +NAMED_CHARACTER_REFERENCE(742, /* b o */ 'x' _ 'H' _ 'd' _ ';', 4, 0, 0x2564 _ 0) +NAMED_CHARACTER_REFERENCE(743, /* b o */ 'x' _ 'H' _ 'u' _ ';', 4, 0, 0x2567 _ 0) +NAMED_CHARACTER_REFERENCE(744, /* b o */ 'x' _ 'U' _ 'L' _ ';', 4, 0, 0x255d _ 0) +NAMED_CHARACTER_REFERENCE(745, /* b o */ 'x' _ 'U' _ 'R' _ ';', 4, 0, 0x255a _ 0) +NAMED_CHARACTER_REFERENCE(746, /* b o */ 'x' _ 'U' _ 'l' _ ';', 4, 0, 0x255c _ 0) +NAMED_CHARACTER_REFERENCE(747, /* b o */ 'x' _ 'U' _ 'r' _ ';', 4, 0, 0x2559 _ 0) +NAMED_CHARACTER_REFERENCE(748, /* b o */ 'x' _ 'V' _ ';', 3, 0, 0x2551 _ 0) +NAMED_CHARACTER_REFERENCE(749, /* b o */ 'x' _ 'V' _ 'H' _ ';', 4, 0, 0x256c _ 0) +NAMED_CHARACTER_REFERENCE(750, /* b o */ 'x' _ 'V' _ 'L' _ ';', 4, 0, 0x2563 _ 0) +NAMED_CHARACTER_REFERENCE(751, /* b o */ 'x' _ 'V' _ 'R' _ ';', 4, 0, 0x2560 _ 0) +NAMED_CHARACTER_REFERENCE(752, /* b o */ 'x' _ 'V' _ 'h' _ ';', 4, 0, 0x256b _ 0) +NAMED_CHARACTER_REFERENCE(753, /* b o */ 'x' _ 'V' _ 'l' _ ';', 4, 0, 0x2562 _ 0) +NAMED_CHARACTER_REFERENCE(754, /* b o */ 'x' _ 'V' _ 'r' _ ';', 4, 0, 0x255f _ 0) +NAMED_CHARACTER_REFERENCE(755, /* b o */ 'x' _ 'b' _ 'o' _ 'x' _ ';', 5, 0, 0x29c9 _ 0) +NAMED_CHARACTER_REFERENCE(756, /* b o */ 'x' _ 'd' _ 'L' _ ';', 4, 0, 0x2555 _ 0) +NAMED_CHARACTER_REFERENCE(757, /* b o */ 'x' _ 'd' _ 'R' _ ';', 4, 0, 0x2552 _ 0) +NAMED_CHARACTER_REFERENCE(758, /* b o */ 'x' _ 'd' _ 'l' _ ';', 4, 0, 0x2510 _ 0) +NAMED_CHARACTER_REFERENCE(759, /* b o */ 'x' _ 'd' _ 'r' _ ';', 4, 0, 0x250c _ 0) +NAMED_CHARACTER_REFERENCE(760, /* b o */ 'x' _ 'h' _ ';', 3, 0, 0x2500 _ 0) +NAMED_CHARACTER_REFERENCE(761, /* b o */ 'x' _ 'h' _ 'D' _ ';', 4, 0, 0x2565 _ 0) +NAMED_CHARACTER_REFERENCE(762, /* b o */ 'x' _ 'h' _ 'U' _ ';', 4, 0, 0x2568 _ 0) +NAMED_CHARACTER_REFERENCE(763, /* b o */ 'x' _ 'h' _ 'd' _ ';', 4, 0, 0x252c _ 0) +NAMED_CHARACTER_REFERENCE(764, /* b o */ 'x' _ 'h' _ 'u' _ ';', 4, 0, 0x2534 _ 0) +NAMED_CHARACTER_REFERENCE(765, /* b o */ 'x' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x229f _ 0) +NAMED_CHARACTER_REFERENCE(766, /* b o */ 'x' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x229e _ 0) +NAMED_CHARACTER_REFERENCE(767, /* b o */ 'x' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7, 0, 0x22a0 _ 0) +NAMED_CHARACTER_REFERENCE(768, /* b o */ 'x' _ 'u' _ 'L' _ ';', 4, 0, 0x255b _ 0) +NAMED_CHARACTER_REFERENCE(769, /* b o */ 'x' _ 'u' _ 'R' _ ';', 4, 0, 0x2558 _ 0) +NAMED_CHARACTER_REFERENCE(770, /* b o */ 'x' _ 'u' _ 'l' _ ';', 4, 0, 0x2518 _ 0) +NAMED_CHARACTER_REFERENCE(771, /* b o */ 'x' _ 'u' _ 'r' _ ';', 4, 0, 0x2514 _ 0) +NAMED_CHARACTER_REFERENCE(772, /* b o */ 'x' _ 'v' _ ';', 3, 0, 0x2502 _ 0) +NAMED_CHARACTER_REFERENCE(773, /* b o */ 'x' _ 'v' _ 'H' _ ';', 4, 0, 0x256a _ 0) +NAMED_CHARACTER_REFERENCE(774, /* b o */ 'x' _ 'v' _ 'L' _ ';', 4, 0, 0x2561 _ 0) +NAMED_CHARACTER_REFERENCE(775, /* b o */ 'x' _ 'v' _ 'R' _ ';', 4, 0, 0x255e _ 0) +NAMED_CHARACTER_REFERENCE(776, /* b o */ 'x' _ 'v' _ 'h' _ ';', 4, 0, 0x253c _ 0) +NAMED_CHARACTER_REFERENCE(777, /* b o */ 'x' _ 'v' _ 'l' _ ';', 4, 0, 0x2524 _ 0) +NAMED_CHARACTER_REFERENCE(778, /* b o */ 'x' _ 'v' _ 'r' _ ';', 4, 0, 0x251c _ 0) +NAMED_CHARACTER_REFERENCE(779, /* b p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2035 _ 0) +NAMED_CHARACTER_REFERENCE(780, /* b r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0) +NAMED_CHARACTER_REFERENCE(781, /* b r */ 'v' _ 'b' _ 'a' _ 'r', 4, 0, 0x00a6 _ 0) +NAMED_CHARACTER_REFERENCE(782, /* b r */ 'v' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x00a6 _ 0) +NAMED_CHARACTER_REFERENCE(783, /* b s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb7) +NAMED_CHARACTER_REFERENCE(784, /* b s */ 'e' _ 'm' _ 'i' _ ';', 4, 0, 0x204f _ 0) +NAMED_CHARACTER_REFERENCE(785, /* b s */ 'i' _ 'm' _ ';', 3, 0, 0x223d _ 0) +NAMED_CHARACTER_REFERENCE(786, /* b s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x22cd _ 0) +NAMED_CHARACTER_REFERENCE(787, /* b s */ 'o' _ 'l' _ ';', 3, 0, 0x005c _ 0) +NAMED_CHARACTER_REFERENCE(788, /* b s */ 'o' _ 'l' _ 'b' _ ';', 4, 0, 0x29c5 _ 0) +NAMED_CHARACTER_REFERENCE(789, /* b s */ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 7, 0, 0x27c8 _ 0) +NAMED_CHARACTER_REFERENCE(790, /* b u */ 'l' _ 'l' _ ';', 3, 0, 0x2022 _ 0) +NAMED_CHARACTER_REFERENCE(791, /* b u */ 'l' _ 'l' _ 'e' _ 't' _ ';', 5, 0, 0x2022 _ 0) +NAMED_CHARACTER_REFERENCE(792, /* b u */ 'm' _ 'p' _ ';', 3, 0, 0x224e _ 0) +NAMED_CHARACTER_REFERENCE(793, /* b u */ 'm' _ 'p' _ 'E' _ ';', 4, 0, 0x2aae _ 0) +NAMED_CHARACTER_REFERENCE(794, /* b u */ 'm' _ 'p' _ 'e' _ ';', 4, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(795, /* b u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0, 0x224f _ 0) +NAMED_CHARACTER_REFERENCE(796, /* c a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0107 _ 0) +NAMED_CHARACTER_REFERENCE(797, /* c a */ 'p' _ ';', 2, 0, 0x2229 _ 0) +NAMED_CHARACTER_REFERENCE(798, /* c a */ 'p' _ 'a' _ 'n' _ 'd' _ ';', 5, 0, 0x2a44 _ 0) +NAMED_CHARACTER_REFERENCE(799, /* c a */ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 7, 0, 0x2a49 _ 0) +NAMED_CHARACTER_REFERENCE(800, /* c a */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, 0x2a4b _ 0) +NAMED_CHARACTER_REFERENCE(801, /* c a */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x2a47 _ 0) +NAMED_CHARACTER_REFERENCE(802, /* c a */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a40 _ 0) +NAMED_CHARACTER_REFERENCE(803, /* c a */ 'r' _ 'e' _ 't' _ ';', 4, 0, 0x2041 _ 0) +NAMED_CHARACTER_REFERENCE(804, /* c a */ 'r' _ 'o' _ 'n' _ ';', 4, 0, 0x02c7 _ 0) +NAMED_CHARACTER_REFERENCE(805, /* c c */ 'a' _ 'p' _ 's' _ ';', 4, 0, 0x2a4d _ 0) +NAMED_CHARACTER_REFERENCE(806, /* c c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010d _ 0) +NAMED_CHARACTER_REFERENCE(807, /* c c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00e7 _ 0) +NAMED_CHARACTER_REFERENCE(808, /* c c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x00e7 _ 0) +NAMED_CHARACTER_REFERENCE(809, /* c c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0109 _ 0) +NAMED_CHARACTER_REFERENCE(810, /* c c */ 'u' _ 'p' _ 's' _ ';', 4, 0, 0x2a4c _ 0) +NAMED_CHARACTER_REFERENCE(811, /* c c */ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 6, 0, 0x2a50 _ 0) +NAMED_CHARACTER_REFERENCE(812, /* c d */ 'o' _ 't' _ ';', 3, 0, 0x010b _ 0) +NAMED_CHARACTER_REFERENCE(813, /* c e */ 'd' _ 'i' _ 'l', 3, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(814, /* c e */ 'd' _ 'i' _ 'l' _ ';', 4, 0, 0x00b8 _ 0) +NAMED_CHARACTER_REFERENCE(815, /* c e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, 0x29b2 _ 0) +NAMED_CHARACTER_REFERENCE(816, /* c e */ 'n' _ 't', 2, 0, 0x00a2 _ 0) +NAMED_CHARACTER_REFERENCE(817, /* c e */ 'n' _ 't' _ ';', 3, 0, 0x00a2 _ 0) +NAMED_CHARACTER_REFERENCE(818, /* c e */ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(819, /* c f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd20) +NAMED_CHARACTER_REFERENCE(820, /* c h */ 'c' _ 'y' _ ';', 3, 0, 0x0447 _ 0) +NAMED_CHARACTER_REFERENCE(821, /* c h */ 'e' _ 'c' _ 'k' _ ';', 4, 0, 0x2713 _ 0) +NAMED_CHARACTER_REFERENCE(822, /* c h */ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 8, 0, 0x2713 _ 0) +NAMED_CHARACTER_REFERENCE(823, /* c h */ 'i' _ ';', 2, 0, 0x03c7 _ 0) +NAMED_CHARACTER_REFERENCE(824, /* c i */ 'r' _ ';', 2, 0, 0x25cb _ 0) +NAMED_CHARACTER_REFERENCE(825, /* c i */ 'r' _ 'E' _ ';', 3, 0, 0x29c3 _ 0) +NAMED_CHARACTER_REFERENCE(826, /* c i */ 'r' _ 'c' _ ';', 3, 0, 0x02c6 _ 0) +NAMED_CHARACTER_REFERENCE(827, /* c i */ 'r' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, 0x2257 _ 0) +NAMED_CHARACTER_REFERENCE(828, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0, 0x21ba _ 0) +NAMED_CHARACTER_REFERENCE(829, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0, 0x21bb _ 0) +NAMED_CHARACTER_REFERENCE(830, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 7, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(831, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 7, 0, 0x24c8 _ 0) +NAMED_CHARACTER_REFERENCE(832, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 9, 0, 0x229b _ 0) +NAMED_CHARACTER_REFERENCE(833, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 10, 0, 0x229a _ 0) +NAMED_CHARACTER_REFERENCE(834, /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 10, 0, 0x229d _ 0) +NAMED_CHARACTER_REFERENCE(835, /* c i */ 'r' _ 'e' _ ';', 3, 0, 0x2257 _ 0) +NAMED_CHARACTER_REFERENCE(836, /* c i */ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a10 _ 0) +NAMED_CHARACTER_REFERENCE(837, /* c i */ 'r' _ 'm' _ 'i' _ 'd' _ ';', 5, 0, 0x2aef _ 0) +NAMED_CHARACTER_REFERENCE(838, /* c i */ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, 0x29c2 _ 0) +NAMED_CHARACTER_REFERENCE(839, /* c l */ 'u' _ 'b' _ 's' _ ';', 4, 0, 0x2663 _ 0) +NAMED_CHARACTER_REFERENCE(840, /* c l */ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 7, 0, 0x2663 _ 0) +NAMED_CHARACTER_REFERENCE(841, /* c o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x003a _ 0) +NAMED_CHARACTER_REFERENCE(842, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0, 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(843, /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 6, 0, 0x2254 _ 0) +NAMED_CHARACTER_REFERENCE(844, /* c o */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x002c _ 0) +NAMED_CHARACTER_REFERENCE(845, /* c o */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0, 0x0040 _ 0) +NAMED_CHARACTER_REFERENCE(846, /* c o */ 'm' _ 'p' _ ';', 3, 0, 0x2201 _ 0) +NAMED_CHARACTER_REFERENCE(847, /* c o */ 'm' _ 'p' _ 'f' _ 'n' _ ';', 5, 0, 0x2218 _ 0) +NAMED_CHARACTER_REFERENCE(848, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0, 0x2201 _ 0) +NAMED_CHARACTER_REFERENCE(849, /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 8, 0, 0x2102 _ 0) +NAMED_CHARACTER_REFERENCE(850, /* c o */ 'n' _ 'g' _ ';', 3, 0, 0x2245 _ 0) +NAMED_CHARACTER_REFERENCE(851, /* c o */ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2a6d _ 0) +NAMED_CHARACTER_REFERENCE(852, /* c o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(853, /* c o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd54) +NAMED_CHARACTER_REFERENCE(854, /* c o */ 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0, 0x2210 _ 0) +NAMED_CHARACTER_REFERENCE(855, /* c o */ 'p' _ 'y', 2, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(856, /* c o */ 'p' _ 'y' _ ';', 3, 0, 0x00a9 _ 0) +NAMED_CHARACTER_REFERENCE(857, /* c o */ 'p' _ 'y' _ 's' _ 'r' _ ';', 5, 0, 0x2117 _ 0) +NAMED_CHARACTER_REFERENCE(858, /* c r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21b5 _ 0) +NAMED_CHARACTER_REFERENCE(859, /* c r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2717 _ 0) +NAMED_CHARACTER_REFERENCE(860, /* c s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb8) +NAMED_CHARACTER_REFERENCE(861, /* c s */ 'u' _ 'b' _ ';', 3, 0, 0x2acf _ 0) +NAMED_CHARACTER_REFERENCE(862, /* c s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2ad1 _ 0) +NAMED_CHARACTER_REFERENCE(863, /* c s */ 'u' _ 'p' _ ';', 3, 0, 0x2ad0 _ 0) +NAMED_CHARACTER_REFERENCE(864, /* c s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2ad2 _ 0) +NAMED_CHARACTER_REFERENCE(865, /* c t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22ef _ 0) +NAMED_CHARACTER_REFERENCE(866, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 6, 0, 0x2938 _ 0) +NAMED_CHARACTER_REFERENCE(867, /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 6, 0, 0x2935 _ 0) +NAMED_CHARACTER_REFERENCE(868, /* c u */ 'e' _ 'p' _ 'r' _ ';', 4, 0, 0x22de _ 0) +NAMED_CHARACTER_REFERENCE(869, /* c u */ 'e' _ 's' _ 'c' _ ';', 4, 0, 0x22df _ 0) +NAMED_CHARACTER_REFERENCE(870, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x21b6 _ 0) +NAMED_CHARACTER_REFERENCE(871, /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 6, 0, 0x293d _ 0) +NAMED_CHARACTER_REFERENCE(872, /* c u */ 'p' _ ';', 2, 0, 0x222a _ 0) +NAMED_CHARACTER_REFERENCE(873, /* c u */ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 7, 0, 0x2a48 _ 0) +NAMED_CHARACTER_REFERENCE(874, /* c u */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0, 0x2a46 _ 0) +NAMED_CHARACTER_REFERENCE(875, /* c u */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x2a4a _ 0) +NAMED_CHARACTER_REFERENCE(876, /* c u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x228d _ 0) +NAMED_CHARACTER_REFERENCE(877, /* c u */ 'p' _ 'o' _ 'r' _ ';', 4, 0, 0x2a45 _ 0) +NAMED_CHARACTER_REFERENCE(878, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x21b7 _ 0) +NAMED_CHARACTER_REFERENCE(879, /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 6, 0, 0x293c _ 0) +NAMED_CHARACTER_REFERENCE(880, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 10, 0, 0x22de _ 0) +NAMED_CHARACTER_REFERENCE(881, /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 10, 0, 0x22df _ 0) +NAMED_CHARACTER_REFERENCE(882, /* c u */ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 7, 0, 0x22ce _ 0) +NAMED_CHARACTER_REFERENCE(883, /* c u */ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 9, 0, 0x22cf _ 0) +NAMED_CHARACTER_REFERENCE(884, /* c u */ 'r' _ 'r' _ 'e' _ 'n', 4, 0, 0x00a4 _ 0) +NAMED_CHARACTER_REFERENCE(885, /* c u */ 'r' _ 'r' _ 'e' _ 'n' _ ';', 5, 0, 0x00a4 _ 0) +NAMED_CHARACTER_REFERENCE(886, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 13, 0, 0x21b6 _ 0) +NAMED_CHARACTER_REFERENCE(887, /* c u */ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 14, 0, 0x21b7 _ 0) +NAMED_CHARACTER_REFERENCE(888, /* c u */ 'v' _ 'e' _ 'e' _ ';', 4, 0, 0x22ce _ 0) +NAMED_CHARACTER_REFERENCE(889, /* c u */ 'w' _ 'e' _ 'd' _ ';', 4, 0, 0x22cf _ 0) +NAMED_CHARACTER_REFERENCE(890, /* c w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2232 _ 0) +NAMED_CHARACTER_REFERENCE(891, /* c w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2231 _ 0) +NAMED_CHARACTER_REFERENCE(892, /* c y */ 'l' _ 'c' _ 't' _ 'y' _ ';', 5, 0, 0x232d _ 0) +NAMED_CHARACTER_REFERENCE(893, /* d A */ 'r' _ 'r' _ ';', 3, 0, 0x21d3 _ 0) +NAMED_CHARACTER_REFERENCE(894, /* d H */ 'a' _ 'r' _ ';', 3, 0, 0x2965 _ 0) +NAMED_CHARACTER_REFERENCE(895, /* d a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0, 0x2020 _ 0) +NAMED_CHARACTER_REFERENCE(896, /* d a */ 'l' _ 'e' _ 't' _ 'h' _ ';', 5, 0, 0x2138 _ 0) +NAMED_CHARACTER_REFERENCE(897, /* d a */ 'r' _ 'r' _ ';', 3, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(898, /* d a */ 's' _ 'h' _ ';', 3, 0, 0x2010 _ 0) +NAMED_CHARACTER_REFERENCE(899, /* d a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x22a3 _ 0) +NAMED_CHARACTER_REFERENCE(900, /* d b */ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x290f _ 0) +NAMED_CHARACTER_REFERENCE(901, /* d b */ 'l' _ 'a' _ 'c' _ ';', 4, 0, 0x02dd _ 0) +NAMED_CHARACTER_REFERENCE(902, /* d c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x010f _ 0) +NAMED_CHARACTER_REFERENCE(903, /* d c */ 'y' _ ';', 2, 0, 0x0434 _ 0) +NAMED_CHARACTER_REFERENCE(904, /* d d */ ';', 1, 0, 0x2146 _ 0) +NAMED_CHARACTER_REFERENCE(905, /* d d */ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 6, 0, 0x2021 _ 0) +NAMED_CHARACTER_REFERENCE(906, /* d d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ca _ 0) +NAMED_CHARACTER_REFERENCE(907, /* d d */ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 6, 0, 0x2a77 _ 0) +NAMED_CHARACTER_REFERENCE(908, /* d e */ 'g', 1, 0, 0x00b0 _ 0) +NAMED_CHARACTER_REFERENCE(909, /* d e */ 'g' _ ';', 2, 0, 0x00b0 _ 0) +NAMED_CHARACTER_REFERENCE(910, /* d e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x03b4 _ 0) +NAMED_CHARACTER_REFERENCE(911, /* d e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0, 0x29b1 _ 0) +NAMED_CHARACTER_REFERENCE(912, /* d f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297f _ 0) +NAMED_CHARACTER_REFERENCE(913, /* d f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd21) +NAMED_CHARACTER_REFERENCE(914, /* d h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(915, /* d h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(916, /* d i */ 'a' _ 'm' _ ';', 3, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(917, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0, 0x22c4 _ 0) +NAMED_CHARACTER_REFERENCE(918, /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0, 0x2666 _ 0) +NAMED_CHARACTER_REFERENCE(919, /* d i */ 'a' _ 'm' _ 's' _ ';', 4, 0, 0x2666 _ 0) +NAMED_CHARACTER_REFERENCE(920, /* d i */ 'e' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(921, /* d i */ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0, 0x03dd _ 0) +NAMED_CHARACTER_REFERENCE(922, /* d i */ 's' _ 'i' _ 'n' _ ';', 4, 0, 0x22f2 _ 0) +NAMED_CHARACTER_REFERENCE(923, /* d i */ 'v' _ ';', 2, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(924, /* d i */ 'v' _ 'i' _ 'd' _ 'e', 4, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(925, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ ';', 5, 0, 0x00f7 _ 0) +NAMED_CHARACTER_REFERENCE(926, /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 12, 0, 0x22c7 _ 0) +NAMED_CHARACTER_REFERENCE(927, /* d i */ 'v' _ 'o' _ 'n' _ 'x' _ ';', 5, 0, 0x22c7 _ 0) +NAMED_CHARACTER_REFERENCE(928, /* d j */ 'c' _ 'y' _ ';', 3, 0, 0x0452 _ 0) +NAMED_CHARACTER_REFERENCE(929, /* d l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231e _ 0) +NAMED_CHARACTER_REFERENCE(930, /* d l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230d _ 0) +NAMED_CHARACTER_REFERENCE(931, /* d o */ 'l' _ 'l' _ 'a' _ 'r' _ ';', 5, 0, 0x0024 _ 0) +NAMED_CHARACTER_REFERENCE(932, /* d o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd55) +NAMED_CHARACTER_REFERENCE(933, /* d o */ 't' _ ';', 2, 0, 0x02d9 _ 0) +NAMED_CHARACTER_REFERENCE(934, /* d o */ 't' _ 'e' _ 'q' _ ';', 4, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(935, /* d o */ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 7, 0, 0x2251 _ 0) +NAMED_CHARACTER_REFERENCE(936, /* d o */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x2238 _ 0) +NAMED_CHARACTER_REFERENCE(937, /* d o */ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2214 _ 0) +NAMED_CHARACTER_REFERENCE(938, /* d o */ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 8, 0, 0x22a1 _ 0) +NAMED_CHARACTER_REFERENCE(939, /* d o */ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 13, 0, 0x2306 _ 0) +NAMED_CHARACTER_REFERENCE(940, /* d o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0) +NAMED_CHARACTER_REFERENCE(941, /* d o */ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0, 0x21ca _ 0) +NAMED_CHARACTER_REFERENCE(942, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0, 0x21c3 _ 0) +NAMED_CHARACTER_REFERENCE(943, /* d o */ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0, 0x21c2 _ 0) +NAMED_CHARACTER_REFERENCE(944, /* d r */ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0, 0x2910 _ 0) +NAMED_CHARACTER_REFERENCE(945, /* d r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231f _ 0) +NAMED_CHARACTER_REFERENCE(946, /* d r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230c _ 0) +NAMED_CHARACTER_REFERENCE(947, /* d s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb9) +NAMED_CHARACTER_REFERENCE(948, /* d s */ 'c' _ 'y' _ ';', 3, 0, 0x0455 _ 0) +NAMED_CHARACTER_REFERENCE(949, /* d s */ 'o' _ 'l' _ ';', 3, 0, 0x29f6 _ 0) +NAMED_CHARACTER_REFERENCE(950, /* d s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0111 _ 0) +NAMED_CHARACTER_REFERENCE(951, /* d t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f1 _ 0) +NAMED_CHARACTER_REFERENCE(952, /* d t */ 'r' _ 'i' _ ';', 3, 0, 0x25bf _ 0) +NAMED_CHARACTER_REFERENCE(953, /* d t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25be _ 0) +NAMED_CHARACTER_REFERENCE(954, /* d u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21f5 _ 0) +NAMED_CHARACTER_REFERENCE(955, /* d u */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296f _ 0) +NAMED_CHARACTER_REFERENCE(956, /* d w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0, 0x29a6 _ 0) +NAMED_CHARACTER_REFERENCE(957, /* d z */ 'c' _ 'y' _ ';', 3, 0, 0x045f _ 0) +NAMED_CHARACTER_REFERENCE(958, /* d z */ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7, 0, 0x27ff _ 0) +NAMED_CHARACTER_REFERENCE(959, /* e D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2a77 _ 0) +NAMED_CHARACTER_REFERENCE(960, /* e D */ 'o' _ 't' _ ';', 3, 0, 0x2251 _ 0) +NAMED_CHARACTER_REFERENCE(961, /* e a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e9 _ 0) +NAMED_CHARACTER_REFERENCE(962, /* e a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00e9 _ 0) +NAMED_CHARACTER_REFERENCE(963, /* e a */ 's' _ 't' _ 'e' _ 'r' _ ';', 5, 0, 0x2a6e _ 0) +NAMED_CHARACTER_REFERENCE(964, /* e c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x011b _ 0) +NAMED_CHARACTER_REFERENCE(965, /* e c */ 'i' _ 'r' _ ';', 3, 0, 0x2256 _ 0) +NAMED_CHARACTER_REFERENCE(966, /* e c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ea _ 0) +NAMED_CHARACTER_REFERENCE(967, /* e c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ea _ 0) +NAMED_CHARACTER_REFERENCE(968, /* e c */ 'o' _ 'l' _ 'o' _ 'n' _ ';', 5, 0, 0x2255 _ 0) +NAMED_CHARACTER_REFERENCE(969, /* e c */ 'y' _ ';', 2, 0, 0x044d _ 0) +NAMED_CHARACTER_REFERENCE(970, /* e d */ 'o' _ 't' _ ';', 3, 0, 0x0117 _ 0) +NAMED_CHARACTER_REFERENCE(971, /* e e */ ';', 1, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(972, /* e f */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2252 _ 0) +NAMED_CHARACTER_REFERENCE(973, /* e f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd22) +NAMED_CHARACTER_REFERENCE(974, /* e g */ ';', 1, 0, 0x2a9a _ 0) +NAMED_CHARACTER_REFERENCE(975, /* e g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e8 _ 0) +NAMED_CHARACTER_REFERENCE(976, /* e g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00e8 _ 0) +NAMED_CHARACTER_REFERENCE(977, /* e g */ 's' _ ';', 2, 0, 0x2a96 _ 0) +NAMED_CHARACTER_REFERENCE(978, /* e g */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a98 _ 0) +NAMED_CHARACTER_REFERENCE(979, /* e l */ ';', 1, 0, 0x2a99 _ 0) +NAMED_CHARACTER_REFERENCE(980, /* e l */ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 7, 0, 0x23e7 _ 0) +NAMED_CHARACTER_REFERENCE(981, /* e l */ 'l' _ ';', 2, 0, 0x2113 _ 0) +NAMED_CHARACTER_REFERENCE(982, /* e l */ 's' _ ';', 2, 0, 0x2a95 _ 0) +NAMED_CHARACTER_REFERENCE(983, /* e l */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a97 _ 0) +NAMED_CHARACTER_REFERENCE(984, /* e m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0113 _ 0) +NAMED_CHARACTER_REFERENCE(985, /* e m */ 'p' _ 't' _ 'y' _ ';', 4, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(986, /* e m */ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(987, /* e m */ 'p' _ 't' _ 'y' _ 'v' _ ';', 5, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(988, /* e m */ 's' _ 'p' _ '1' _ '3' _ ';', 5, 0, 0x2004 _ 0) +NAMED_CHARACTER_REFERENCE(989, /* e m */ 's' _ 'p' _ '1' _ '4' _ ';', 5, 0, 0x2005 _ 0) +NAMED_CHARACTER_REFERENCE(990, /* e m */ 's' _ 'p' _ ';', 3, 0, 0x2003 _ 0) +NAMED_CHARACTER_REFERENCE(991, /* e n */ 'g' _ ';', 2, 0, 0x014b _ 0) +NAMED_CHARACTER_REFERENCE(992, /* e n */ 's' _ 'p' _ ';', 3, 0, 0x2002 _ 0) +NAMED_CHARACTER_REFERENCE(993, /* e o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0119 _ 0) +NAMED_CHARACTER_REFERENCE(994, /* e o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd56) +NAMED_CHARACTER_REFERENCE(995, /* e p */ 'a' _ 'r' _ ';', 3, 0, 0x22d5 _ 0) +NAMED_CHARACTER_REFERENCE(996, /* e p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0, 0x29e3 _ 0) +NAMED_CHARACTER_REFERENCE(997, /* e p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2a71 _ 0) +NAMED_CHARACTER_REFERENCE(998, /* e p */ 's' _ 'i' _ ';', 3, 0, 0x03b5 _ 0) +NAMED_CHARACTER_REFERENCE(999, /* e p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x03b5 _ 0) +NAMED_CHARACTER_REFERENCE(1000, /* e p */ 's' _ 'i' _ 'v' _ ';', 4, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(1001, /* e q */ 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0, 0x2256 _ 0) +NAMED_CHARACTER_REFERENCE(1002, /* e q */ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x2255 _ 0) +NAMED_CHARACTER_REFERENCE(1003, /* e q */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(1004, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 9, 0, 0x2a96 _ 0) +NAMED_CHARACTER_REFERENCE(1005, /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0, 0x2a95 _ 0) +NAMED_CHARACTER_REFERENCE(1006, /* e q */ 'u' _ 'a' _ 'l' _ 's' _ ';', 5, 0, 0x003d _ 0) +NAMED_CHARACTER_REFERENCE(1007, /* e q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0, 0x225f _ 0) +NAMED_CHARACTER_REFERENCE(1008, /* e q */ 'u' _ 'i' _ 'v' _ ';', 4, 0, 0x2261 _ 0) +NAMED_CHARACTER_REFERENCE(1009, /* e q */ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 6, 0, 0x2a78 _ 0) +NAMED_CHARACTER_REFERENCE(1010, /* e q */ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0, 0x29e5 _ 0) +NAMED_CHARACTER_REFERENCE(1011, /* e r */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2253 _ 0) +NAMED_CHARACTER_REFERENCE(1012, /* e r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2971 _ 0) +NAMED_CHARACTER_REFERENCE(1013, /* e s */ 'c' _ 'r' _ ';', 3, 0, 0x212f _ 0) +NAMED_CHARACTER_REFERENCE(1014, /* e s */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2250 _ 0) +NAMED_CHARACTER_REFERENCE(1015, /* e s */ 'i' _ 'm' _ ';', 3, 0, 0x2242 _ 0) +NAMED_CHARACTER_REFERENCE(1016, /* e t */ 'a' _ ';', 2, 0, 0x03b7 _ 0) +NAMED_CHARACTER_REFERENCE(1017, /* e t */ 'h', 1, 0, 0x00f0 _ 0) +NAMED_CHARACTER_REFERENCE(1018, /* e t */ 'h' _ ';', 2, 0, 0x00f0 _ 0) +NAMED_CHARACTER_REFERENCE(1019, /* e u */ 'm' _ 'l', 2, 0, 0x00eb _ 0) +NAMED_CHARACTER_REFERENCE(1020, /* e u */ 'm' _ 'l' _ ';', 3, 0, 0x00eb _ 0) +NAMED_CHARACTER_REFERENCE(1021, /* e u */ 'r' _ 'o' _ ';', 3, 0, 0x20ac _ 0) +NAMED_CHARACTER_REFERENCE(1022, /* e x */ 'c' _ 'l' _ ';', 3, 0, 0x0021 _ 0) +NAMED_CHARACTER_REFERENCE(1023, /* e x */ 'i' _ 's' _ 't' _ ';', 4, 0, 0x2203 _ 0) +NAMED_CHARACTER_REFERENCE(1024, /* e x */ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 10, 0, 0x2130 _ 0) +NAMED_CHARACTER_REFERENCE(1025, /* e x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';', 11, 0, 0x2147 _ 0) +NAMED_CHARACTER_REFERENCE(1026, /* f a */ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 12, 0, 0x2252 _ 0) +NAMED_CHARACTER_REFERENCE(1027, /* f c */ 'y' _ ';', 2, 0, 0x0444 _ 0) +NAMED_CHARACTER_REFERENCE(1028, /* f e */ 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0, 0x2640 _ 0) +NAMED_CHARACTER_REFERENCE(1029, /* f f */ 'i' _ 'l' _ 'i' _ 'g' _ ';', 5, 0, 0xfb03 _ 0) +NAMED_CHARACTER_REFERENCE(1030, /* f f */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb00 _ 0) +NAMED_CHARACTER_REFERENCE(1031, /* f f */ 'l' _ 'l' _ 'i' _ 'g' _ ';', 5, 0, 0xfb04 _ 0) +NAMED_CHARACTER_REFERENCE(1032, /* f f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd23) +NAMED_CHARACTER_REFERENCE(1033, /* f i */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb01 _ 0) +NAMED_CHARACTER_REFERENCE(1034, /* f l */ 'a' _ 't' _ ';', 3, 0, 0x266d _ 0) +NAMED_CHARACTER_REFERENCE(1035, /* f l */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb02 _ 0) +NAMED_CHARACTER_REFERENCE(1036, /* f l */ 't' _ 'n' _ 's' _ ';', 4, 0, 0x25b1 _ 0) +NAMED_CHARACTER_REFERENCE(1037, /* f n */ 'o' _ 'f' _ ';', 3, 0, 0x0192 _ 0) +NAMED_CHARACTER_REFERENCE(1038, /* f o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd57) +NAMED_CHARACTER_REFERENCE(1039, /* f o */ 'r' _ 'a' _ 'l' _ 'l' _ ';', 5, 0, 0x2200 _ 0) +NAMED_CHARACTER_REFERENCE(1040, /* f o */ 'r' _ 'k' _ ';', 3, 0, 0x22d4 _ 0) +NAMED_CHARACTER_REFERENCE(1041, /* f o */ 'r' _ 'k' _ 'v' _ ';', 4, 0, 0x2ad9 _ 0) +NAMED_CHARACTER_REFERENCE(1042, /* f p */ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a0d _ 0) +NAMED_CHARACTER_REFERENCE(1043, /* f r */ 'a' _ 'c' _ '1' _ '2', 4, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1044, /* f r */ 'a' _ 'c' _ '1' _ '2' _ ';', 5, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1045, /* f r */ 'a' _ 'c' _ '1' _ '3' _ ';', 5, 0, 0x2153 _ 0) +NAMED_CHARACTER_REFERENCE(1046, /* f r */ 'a' _ 'c' _ '1' _ '4', 4, 0, 0x00bc _ 0) +NAMED_CHARACTER_REFERENCE(1047, /* f r */ 'a' _ 'c' _ '1' _ '4' _ ';', 5, 0, 0x00bc _ 0) +NAMED_CHARACTER_REFERENCE(1048, /* f r */ 'a' _ 'c' _ '1' _ '5' _ ';', 5, 0, 0x2155 _ 0) +NAMED_CHARACTER_REFERENCE(1049, /* f r */ 'a' _ 'c' _ '1' _ '6' _ ';', 5, 0, 0x2159 _ 0) +NAMED_CHARACTER_REFERENCE(1050, /* f r */ 'a' _ 'c' _ '1' _ '8' _ ';', 5, 0, 0x215b _ 0) +NAMED_CHARACTER_REFERENCE(1051, /* f r */ 'a' _ 'c' _ '2' _ '3' _ ';', 5, 0, 0x2154 _ 0) +NAMED_CHARACTER_REFERENCE(1052, /* f r */ 'a' _ 'c' _ '2' _ '5' _ ';', 5, 0, 0x2156 _ 0) +NAMED_CHARACTER_REFERENCE(1053, /* f r */ 'a' _ 'c' _ '3' _ '4', 4, 0, 0x00be _ 0) +NAMED_CHARACTER_REFERENCE(1054, /* f r */ 'a' _ 'c' _ '3' _ '4' _ ';', 5, 0, 0x00be _ 0) +NAMED_CHARACTER_REFERENCE(1055, /* f r */ 'a' _ 'c' _ '3' _ '5' _ ';', 5, 0, 0x2157 _ 0) +NAMED_CHARACTER_REFERENCE(1056, /* f r */ 'a' _ 'c' _ '3' _ '8' _ ';', 5, 0, 0x215c _ 0) +NAMED_CHARACTER_REFERENCE(1057, /* f r */ 'a' _ 'c' _ '4' _ '5' _ ';', 5, 0, 0x2158 _ 0) +NAMED_CHARACTER_REFERENCE(1058, /* f r */ 'a' _ 'c' _ '5' _ '6' _ ';', 5, 0, 0x215a _ 0) +NAMED_CHARACTER_REFERENCE(1059, /* f r */ 'a' _ 'c' _ '5' _ '8' _ ';', 5, 0, 0x215d _ 0) +NAMED_CHARACTER_REFERENCE(1060, /* f r */ 'a' _ 'c' _ '7' _ '8' _ ';', 5, 0, 0x215e _ 0) +NAMED_CHARACTER_REFERENCE(1061, /* f r */ 'a' _ 's' _ 'l' _ ';', 4, 0, 0x2044 _ 0) +NAMED_CHARACTER_REFERENCE(1062, /* f r */ 'o' _ 'w' _ 'n' _ ';', 4, 0, 0x2322 _ 0) +NAMED_CHARACTER_REFERENCE(1063, /* f s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbb) +NAMED_CHARACTER_REFERENCE(1064, /* g E */ ';', 1, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(1065, /* g E */ 'l' _ ';', 2, 0, 0x2a8c _ 0) +NAMED_CHARACTER_REFERENCE(1066, /* g a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x01f5 _ 0) +NAMED_CHARACTER_REFERENCE(1067, /* g a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x03b3 _ 0) +NAMED_CHARACTER_REFERENCE(1068, /* g a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0, 0x03dd _ 0) +NAMED_CHARACTER_REFERENCE(1069, /* g a */ 'p' _ ';', 2, 0, 0x2a86 _ 0) +NAMED_CHARACTER_REFERENCE(1070, /* g b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x011f _ 0) +NAMED_CHARACTER_REFERENCE(1071, /* g c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011d _ 0) +NAMED_CHARACTER_REFERENCE(1072, /* g c */ 'y' _ ';', 2, 0, 0x0433 _ 0) +NAMED_CHARACTER_REFERENCE(1073, /* g d */ 'o' _ 't' _ ';', 3, 0, 0x0121 _ 0) +NAMED_CHARACTER_REFERENCE(1074, /* g e */ ';', 1, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(1075, /* g e */ 'l' _ ';', 2, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(1076, /* g e */ 'q' _ ';', 2, 0, 0x2265 _ 0) +NAMED_CHARACTER_REFERENCE(1077, /* g e */ 'q' _ 'q' _ ';', 3, 0, 0x2267 _ 0) +NAMED_CHARACTER_REFERENCE(1078, /* g e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(1079, /* g e */ 's' _ ';', 2, 0, 0x2a7e _ 0) +NAMED_CHARACTER_REFERENCE(1080, /* g e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa9 _ 0) +NAMED_CHARACTER_REFERENCE(1081, /* g e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a80 _ 0) +NAMED_CHARACTER_REFERENCE(1082, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0, 0x2a82 _ 0) +NAMED_CHARACTER_REFERENCE(1083, /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 7, 0, 0x2a84 _ 0) +NAMED_CHARACTER_REFERENCE(1084, /* g e */ 's' _ 'l' _ 'e' _ 's' _ ';', 5, 0, 0x2a94 _ 0) +NAMED_CHARACTER_REFERENCE(1085, /* g f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd24) +NAMED_CHARACTER_REFERENCE(1086, /* g g */ ';', 1, 0, 0x226b _ 0) +NAMED_CHARACTER_REFERENCE(1087, /* g g */ 'g' _ ';', 2, 0, 0x22d9 _ 0) +NAMED_CHARACTER_REFERENCE(1088, /* g i */ 'm' _ 'e' _ 'l' _ ';', 4, 0, 0x2137 _ 0) +NAMED_CHARACTER_REFERENCE(1089, /* g j */ 'c' _ 'y' _ ';', 3, 0, 0x0453 _ 0) +NAMED_CHARACTER_REFERENCE(1090, /* g l */ ';', 1, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(1091, /* g l */ 'E' _ ';', 2, 0, 0x2a92 _ 0) +NAMED_CHARACTER_REFERENCE(1092, /* g l */ 'a' _ ';', 2, 0, 0x2aa5 _ 0) +NAMED_CHARACTER_REFERENCE(1093, /* g l */ 'j' _ ';', 2, 0, 0x2aa4 _ 0) +NAMED_CHARACTER_REFERENCE(1094, /* g n */ 'E' _ ';', 2, 0, 0x2269 _ 0) +NAMED_CHARACTER_REFERENCE(1095, /* g n */ 'a' _ 'p' _ ';', 3, 0, 0x2a8a _ 0) +NAMED_CHARACTER_REFERENCE(1096, /* g n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0, 0x2a8a _ 0) +NAMED_CHARACTER_REFERENCE(1097, /* g n */ 'e' _ ';', 2, 0, 0x2a88 _ 0) +NAMED_CHARACTER_REFERENCE(1098, /* g n */ 'e' _ 'q' _ ';', 3, 0, 0x2a88 _ 0) +NAMED_CHARACTER_REFERENCE(1099, /* g n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2269 _ 0) +NAMED_CHARACTER_REFERENCE(1100, /* g n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e7 _ 0) +NAMED_CHARACTER_REFERENCE(1101, /* g o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd58) +NAMED_CHARACTER_REFERENCE(1102, /* g r */ 'a' _ 'v' _ 'e' _ ';', 4, 0, 0x0060 _ 0) +NAMED_CHARACTER_REFERENCE(1103, /* g s */ 'c' _ 'r' _ ';', 3, 0, 0x210a _ 0) +NAMED_CHARACTER_REFERENCE(1104, /* g s */ 'i' _ 'm' _ ';', 3, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(1105, /* g s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8e _ 0) +NAMED_CHARACTER_REFERENCE(1106, /* g s */ 'i' _ 'm' _ 'l' _ ';', 4, 0, 0x2a90 _ 0) +NAMED_CHARACTER_REFERENCE(1107, /* g t */ 0, 0, 1, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(1108, /* g t */ ';', 1, 0, 0x003e _ 0) +NAMED_CHARACTER_REFERENCE(1109, /* g t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa7 _ 0) +NAMED_CHARACTER_REFERENCE(1110, /* g t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a7a _ 0) +NAMED_CHARACTER_REFERENCE(1111, /* g t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d7 _ 0) +NAMED_CHARACTER_REFERENCE(1112, /* g t */ 'l' _ 'P' _ 'a' _ 'r' _ ';', 5, 0, 0x2995 _ 0) +NAMED_CHARACTER_REFERENCE(1113, /* g t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0, 0x2a7c _ 0) +NAMED_CHARACTER_REFERENCE(1114, /* g t */ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0, 0x2a86 _ 0) +NAMED_CHARACTER_REFERENCE(1115, /* g t */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x2978 _ 0) +NAMED_CHARACTER_REFERENCE(1116, /* g t */ 'r' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x22d7 _ 0) +NAMED_CHARACTER_REFERENCE(1117, /* g t */ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0, 0x22db _ 0) +NAMED_CHARACTER_REFERENCE(1118, /* g t */ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 9, 0, 0x2a8c _ 0) +NAMED_CHARACTER_REFERENCE(1119, /* g t */ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0, 0x2277 _ 0) +NAMED_CHARACTER_REFERENCE(1120, /* g t */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2273 _ 0) +NAMED_CHARACTER_REFERENCE(1121, /* h A */ 'r' _ 'r' _ ';', 3, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(1122, /* h a */ 'i' _ 'r' _ 's' _ 'p' _ ';', 5, 0, 0x200a _ 0) +NAMED_CHARACTER_REFERENCE(1123, /* h a */ 'l' _ 'f' _ ';', 3, 0, 0x00bd _ 0) +NAMED_CHARACTER_REFERENCE(1124, /* h a */ 'm' _ 'i' _ 'l' _ 't' _ ';', 5, 0, 0x210b _ 0) +NAMED_CHARACTER_REFERENCE(1125, /* h a */ 'r' _ 'd' _ 'c' _ 'y' _ ';', 5, 0, 0x044a _ 0) +NAMED_CHARACTER_REFERENCE(1126, /* h a */ 'r' _ 'r' _ ';', 3, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(1127, /* h a */ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, 0x2948 _ 0) +NAMED_CHARACTER_REFERENCE(1128, /* h a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x21ad _ 0) +NAMED_CHARACTER_REFERENCE(1129, /* h b */ 'a' _ 'r' _ ';', 3, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1130, /* h c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0125 _ 0) +NAMED_CHARACTER_REFERENCE(1131, /* h e */ 'a' _ 'r' _ 't' _ 's' _ ';', 5, 0, 0x2665 _ 0) +NAMED_CHARACTER_REFERENCE(1132, /* h e */ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2665 _ 0) +NAMED_CHARACTER_REFERENCE(1133, /* h e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0, 0x2026 _ 0) +NAMED_CHARACTER_REFERENCE(1134, /* h e */ 'r' _ 'c' _ 'o' _ 'n' _ ';', 5, 0, 0x22b9 _ 0) +NAMED_CHARACTER_REFERENCE(1135, /* h f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd25) +NAMED_CHARACTER_REFERENCE(1136, /* h k */ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0, 0x2925 _ 0) +NAMED_CHARACTER_REFERENCE(1137, /* h k */ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7, 0, 0x2926 _ 0) +NAMED_CHARACTER_REFERENCE(1138, /* h o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ff _ 0) +NAMED_CHARACTER_REFERENCE(1139, /* h o */ 'm' _ 't' _ 'h' _ 't' _ ';', 5, 0, 0x223b _ 0) +NAMED_CHARACTER_REFERENCE(1140, /* h o */ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x21a9 _ 0) +NAMED_CHARACTER_REFERENCE(1141, /* h o */ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x21aa _ 0) +NAMED_CHARACTER_REFERENCE(1142, /* h o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd59) +NAMED_CHARACTER_REFERENCE(1143, /* h o */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x2015 _ 0) +NAMED_CHARACTER_REFERENCE(1144, /* h s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbd) +NAMED_CHARACTER_REFERENCE(1145, /* h s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1146, /* h s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0127 _ 0) +NAMED_CHARACTER_REFERENCE(1147, /* h y */ 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0, 0x2043 _ 0) +NAMED_CHARACTER_REFERENCE(1148, /* h y */ 'p' _ 'h' _ 'e' _ 'n' _ ';', 5, 0, 0x2010 _ 0) +NAMED_CHARACTER_REFERENCE(1149, /* i a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00ed _ 0) +NAMED_CHARACTER_REFERENCE(1150, /* i a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00ed _ 0) +NAMED_CHARACTER_REFERENCE(1151, /* i c */ ';', 1, 0, 0x2063 _ 0) +NAMED_CHARACTER_REFERENCE(1152, /* i c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ee _ 0) +NAMED_CHARACTER_REFERENCE(1153, /* i c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ee _ 0) +NAMED_CHARACTER_REFERENCE(1154, /* i c */ 'y' _ ';', 2, 0, 0x0438 _ 0) +NAMED_CHARACTER_REFERENCE(1155, /* i e */ 'c' _ 'y' _ ';', 3, 0, 0x0435 _ 0) +NAMED_CHARACTER_REFERENCE(1156, /* i e */ 'x' _ 'c' _ 'l', 3, 0, 0x00a1 _ 0) +NAMED_CHARACTER_REFERENCE(1157, /* i e */ 'x' _ 'c' _ 'l' _ ';', 4, 0, 0x00a1 _ 0) +NAMED_CHARACTER_REFERENCE(1158, /* i f */ 'f' _ ';', 2, 0, 0x21d4 _ 0) +NAMED_CHARACTER_REFERENCE(1159, /* i f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd26) +NAMED_CHARACTER_REFERENCE(1160, /* i g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00ec _ 0) +NAMED_CHARACTER_REFERENCE(1161, /* i g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00ec _ 0) +NAMED_CHARACTER_REFERENCE(1162, /* i i */ ';', 1, 0, 0x2148 _ 0) +NAMED_CHARACTER_REFERENCE(1163, /* i i */ 'i' _ 'i' _ 'n' _ 't' _ ';', 5, 0, 0x2a0c _ 0) +NAMED_CHARACTER_REFERENCE(1164, /* i i */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x222d _ 0) +NAMED_CHARACTER_REFERENCE(1165, /* i i */ 'n' _ 'f' _ 'i' _ 'n' _ ';', 5, 0, 0x29dc _ 0) +NAMED_CHARACTER_REFERENCE(1166, /* i i */ 'o' _ 't' _ 'a' _ ';', 4, 0, 0x2129 _ 0) +NAMED_CHARACTER_REFERENCE(1167, /* i j */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0133 _ 0) +NAMED_CHARACTER_REFERENCE(1168, /* i m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012b _ 0) +NAMED_CHARACTER_REFERENCE(1169, /* i m */ 'a' _ 'g' _ 'e' _ ';', 4, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(1170, /* i m */ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0, 0x2110 _ 0) +NAMED_CHARACTER_REFERENCE(1171, /* i m */ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0, 0x2111 _ 0) +NAMED_CHARACTER_REFERENCE(1172, /* i m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0131 _ 0) +NAMED_CHARACTER_REFERENCE(1173, /* i m */ 'o' _ 'f' _ ';', 3, 0, 0x22b7 _ 0) +NAMED_CHARACTER_REFERENCE(1174, /* i m */ 'p' _ 'e' _ 'd' _ ';', 4, 0, 0x01b5 _ 0) +NAMED_CHARACTER_REFERENCE(1175, /* i n */ ';', 1, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1176, /* i n */ 'c' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, 0x2105 _ 0) +NAMED_CHARACTER_REFERENCE(1177, /* i n */ 'f' _ 'i' _ 'n' _ ';', 4, 0, 0x221e _ 0) +NAMED_CHARACTER_REFERENCE(1178, /* i n */ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 7, 0, 0x29dd _ 0) +NAMED_CHARACTER_REFERENCE(1179, /* i n */ 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x0131 _ 0) +NAMED_CHARACTER_REFERENCE(1180, /* i n */ 't' _ ';', 2, 0, 0x222b _ 0) +NAMED_CHARACTER_REFERENCE(1181, /* i n */ 't' _ 'c' _ 'a' _ 'l' _ ';', 5, 0, 0x22ba _ 0) +NAMED_CHARACTER_REFERENCE(1182, /* i n */ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 7, 0, 0x2124 _ 0) +NAMED_CHARACTER_REFERENCE(1183, /* i n */ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 7, 0, 0x22ba _ 0) +NAMED_CHARACTER_REFERENCE(1184, /* i n */ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7, 0, 0x2a17 _ 0) +NAMED_CHARACTER_REFERENCE(1185, /* i n */ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0, 0x2a3c _ 0) +NAMED_CHARACTER_REFERENCE(1186, /* i o */ 'c' _ 'y' _ ';', 3, 0, 0x0451 _ 0) +NAMED_CHARACTER_REFERENCE(1187, /* i o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012f _ 0) +NAMED_CHARACTER_REFERENCE(1188, /* i o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5a) +NAMED_CHARACTER_REFERENCE(1189, /* i o */ 't' _ 'a' _ ';', 3, 0, 0x03b9 _ 0) +NAMED_CHARACTER_REFERENCE(1190, /* i p */ 'r' _ 'o' _ 'd' _ ';', 4, 0, 0x2a3c _ 0) +NAMED_CHARACTER_REFERENCE(1191, /* i q */ 'u' _ 'e' _ 's' _ 't', 4, 0, 0x00bf _ 0) +NAMED_CHARACTER_REFERENCE(1192, /* i q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0, 0x00bf _ 0) +NAMED_CHARACTER_REFERENCE(1193, /* i s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbe) +NAMED_CHARACTER_REFERENCE(1194, /* i s */ 'i' _ 'n' _ ';', 3, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1195, /* i s */ 'i' _ 'n' _ 'E' _ ';', 4, 0, 0x22f9 _ 0) +NAMED_CHARACTER_REFERENCE(1196, /* i s */ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x22f5 _ 0) +NAMED_CHARACTER_REFERENCE(1197, /* i s */ 'i' _ 'n' _ 's' _ ';', 4, 0, 0x22f4 _ 0) +NAMED_CHARACTER_REFERENCE(1198, /* i s */ 'i' _ 'n' _ 's' _ 'v' _ ';', 5, 0, 0x22f3 _ 0) +NAMED_CHARACTER_REFERENCE(1199, /* i s */ 'i' _ 'n' _ 'v' _ ';', 4, 0, 0x2208 _ 0) +NAMED_CHARACTER_REFERENCE(1200, /* i t */ ';', 1, 0, 0x2062 _ 0) +NAMED_CHARACTER_REFERENCE(1201, /* i t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0129 _ 0) +NAMED_CHARACTER_REFERENCE(1202, /* i u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0456 _ 0) +NAMED_CHARACTER_REFERENCE(1203, /* i u */ 'm' _ 'l', 2, 0, 0x00ef _ 0) +NAMED_CHARACTER_REFERENCE(1204, /* i u */ 'm' _ 'l' _ ';', 3, 0, 0x00ef _ 0) +NAMED_CHARACTER_REFERENCE(1205, /* j c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0135 _ 0) +NAMED_CHARACTER_REFERENCE(1206, /* j c */ 'y' _ ';', 2, 0, 0x0439 _ 0) +NAMED_CHARACTER_REFERENCE(1207, /* j f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd27) +NAMED_CHARACTER_REFERENCE(1208, /* j m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0237 _ 0) +NAMED_CHARACTER_REFERENCE(1209, /* j o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5b) +NAMED_CHARACTER_REFERENCE(1210, /* j s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbf) +NAMED_CHARACTER_REFERENCE(1211, /* j s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0, 0x0458 _ 0) +NAMED_CHARACTER_REFERENCE(1212, /* j u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0454 _ 0) +NAMED_CHARACTER_REFERENCE(1213, /* k a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x03ba _ 0) +NAMED_CHARACTER_REFERENCE(1214, /* k a */ 'p' _ 'p' _ 'a' _ 'v' _ ';', 5, 0, 0x03f0 _ 0) +NAMED_CHARACTER_REFERENCE(1215, /* k c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0137 _ 0) +NAMED_CHARACTER_REFERENCE(1216, /* k c */ 'y' _ ';', 2, 0, 0x043a _ 0) +NAMED_CHARACTER_REFERENCE(1217, /* k f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd28) +NAMED_CHARACTER_REFERENCE(1218, /* k g */ 'r' _ 'e' _ 'e' _ 'n' _ ';', 5, 0, 0x0138 _ 0) +NAMED_CHARACTER_REFERENCE(1219, /* k h */ 'c' _ 'y' _ ';', 3, 0, 0x0445 _ 0) +NAMED_CHARACTER_REFERENCE(1220, /* k j */ 'c' _ 'y' _ ';', 3, 0, 0x045c _ 0) +NAMED_CHARACTER_REFERENCE(1221, /* k o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5c) +NAMED_CHARACTER_REFERENCE(1222, /* k s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc0) +NAMED_CHARACTER_REFERENCE(1223, /* l A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21da _ 0) +NAMED_CHARACTER_REFERENCE(1224, /* l A */ 'r' _ 'r' _ ';', 3, 0, 0x21d0 _ 0) +NAMED_CHARACTER_REFERENCE(1225, /* l A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x291b _ 0) +NAMED_CHARACTER_REFERENCE(1226, /* l B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290e _ 0) +NAMED_CHARACTER_REFERENCE(1227, /* l E */ ';', 1, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(1228, /* l E */ 'g' _ ';', 2, 0, 0x2a8b _ 0) +NAMED_CHARACTER_REFERENCE(1229, /* l H */ 'a' _ 'r' _ ';', 3, 0, 0x2962 _ 0) +NAMED_CHARACTER_REFERENCE(1230, /* l a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x013a _ 0) +NAMED_CHARACTER_REFERENCE(1231, /* l a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0, 0x29b4 _ 0) +NAMED_CHARACTER_REFERENCE(1232, /* l a */ 'g' _ 'r' _ 'a' _ 'n' _ ';', 5, 0, 0x2112 _ 0) +NAMED_CHARACTER_REFERENCE(1233, /* l a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0, 0x03bb _ 0) +NAMED_CHARACTER_REFERENCE(1234, /* l a */ 'n' _ 'g' _ ';', 3, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(1235, /* l a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2991 _ 0) +NAMED_CHARACTER_REFERENCE(1236, /* l a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0, 0x27e8 _ 0) +NAMED_CHARACTER_REFERENCE(1237, /* l a */ 'p' _ ';', 2, 0, 0x2a85 _ 0) +NAMED_CHARACTER_REFERENCE(1238, /* l a */ 'q' _ 'u' _ 'o', 3, 0, 0x00ab _ 0) +NAMED_CHARACTER_REFERENCE(1239, /* l a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00ab _ 0) +NAMED_CHARACTER_REFERENCE(1240, /* l a */ 'r' _ 'r' _ ';', 3, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1241, /* l a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e4 _ 0) +NAMED_CHARACTER_REFERENCE(1242, /* l a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0, 0x291f _ 0) +NAMED_CHARACTER_REFERENCE(1243, /* l a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0, 0x291d _ 0) +NAMED_CHARACTER_REFERENCE(1244, /* l a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x21a9 _ 0) +NAMED_CHARACTER_REFERENCE(1245, /* l a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0, 0x21ab _ 0) +NAMED_CHARACTER_REFERENCE(1246, /* l a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0, 0x2939 _ 0) +NAMED_CHARACTER_REFERENCE(1247, /* l a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2973 _ 0) +NAMED_CHARACTER_REFERENCE(1248, /* l a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, 0x21a2 _ 0) +NAMED_CHARACTER_REFERENCE(1249, /* l a */ 't' _ ';', 2, 0, 0x2aab _ 0) +NAMED_CHARACTER_REFERENCE(1250, /* l a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x2919 _ 0) +NAMED_CHARACTER_REFERENCE(1251, /* l a */ 't' _ 'e' _ ';', 3, 0, 0x2aad _ 0) +NAMED_CHARACTER_REFERENCE(1252, /* l b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290c _ 0) +NAMED_CHARACTER_REFERENCE(1253, /* l b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2772 _ 0) +NAMED_CHARACTER_REFERENCE(1254, /* l b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0, 0x007b _ 0) +NAMED_CHARACTER_REFERENCE(1255, /* l b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0, 0x005b _ 0) +NAMED_CHARACTER_REFERENCE(1256, /* l b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298b _ 0) +NAMED_CHARACTER_REFERENCE(1257, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0, 0x298f _ 0) +NAMED_CHARACTER_REFERENCE(1258, /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0, 0x298d _ 0) +NAMED_CHARACTER_REFERENCE(1259, /* l c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x013e _ 0) +NAMED_CHARACTER_REFERENCE(1260, /* l c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x013c _ 0) +NAMED_CHARACTER_REFERENCE(1261, /* l c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2308 _ 0) +NAMED_CHARACTER_REFERENCE(1262, /* l c */ 'u' _ 'b' _ ';', 3, 0, 0x007b _ 0) +NAMED_CHARACTER_REFERENCE(1263, /* l c */ 'y' _ ';', 2, 0, 0x043b _ 0) +NAMED_CHARACTER_REFERENCE(1264, /* l d */ 'c' _ 'a' _ ';', 3, 0, 0x2936 _ 0) +NAMED_CHARACTER_REFERENCE(1265, /* l d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201c _ 0) +NAMED_CHARACTER_REFERENCE(1266, /* l d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x201e _ 0) +NAMED_CHARACTER_REFERENCE(1267, /* l d */ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2967 _ 0) +NAMED_CHARACTER_REFERENCE(1268, /* l d */ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0, 0x294b _ 0) +NAMED_CHARACTER_REFERENCE(1269, /* l d */ 's' _ 'h' _ ';', 3, 0, 0x21b2 _ 0) +NAMED_CHARACTER_REFERENCE(1270, /* l e */ ';', 1, 0, 0x2264 _ 0) +NAMED_CHARACTER_REFERENCE(1271, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1272, /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 12, 0, 0x21a2 _ 0) +NAMED_CHARACTER_REFERENCE(1273, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 14, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(1274, /* l e */ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 12, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(1275, /* l e */ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 13, 0, 0x21c7 _ 0) +NAMED_CHARACTER_REFERENCE(1276, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x2194 _ 0) +NAMED_CHARACTER_REFERENCE(1277, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(1278, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(1279, /* l e */ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 18, 0, 0x21ad _ 0) +NAMED_CHARACTER_REFERENCE(1280, /* l e */ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 13, 0, 0x22cb _ 0) +NAMED_CHARACTER_REFERENCE(1281, /* l e */ 'g' _ ';', 2, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(1282, /* l e */ 'q' _ ';', 2, 0, 0x2264 _ 0) +NAMED_CHARACTER_REFERENCE(1283, /* l e */ 'q' _ 'q' _ ';', 3, 0, 0x2266 _ 0) +NAMED_CHARACTER_REFERENCE(1284, /* l e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(1285, /* l e */ 's' _ ';', 2, 0, 0x2a7d _ 0) +NAMED_CHARACTER_REFERENCE(1286, /* l e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa8 _ 0) +NAMED_CHARACTER_REFERENCE(1287, /* l e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a7f _ 0) +NAMED_CHARACTER_REFERENCE(1288, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0, 0x2a81 _ 0) +NAMED_CHARACTER_REFERENCE(1289, /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 7, 0, 0x2a83 _ 0) +NAMED_CHARACTER_REFERENCE(1290, /* l e */ 's' _ 'g' _ 'e' _ 's' _ ';', 5, 0, 0x2a93 _ 0) +NAMED_CHARACTER_REFERENCE(1291, /* l e */ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, 0x2a85 _ 0) +NAMED_CHARACTER_REFERENCE(1292, /* l e */ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x22d6 _ 0) +NAMED_CHARACTER_REFERENCE(1293, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 8, 0, 0x22da _ 0) +NAMED_CHARACTER_REFERENCE(1294, /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 9, 0, 0x2a8b _ 0) +NAMED_CHARACTER_REFERENCE(1295, /* l e */ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 6, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(1296, /* l e */ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(1297, /* l f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297c _ 0) +NAMED_CHARACTER_REFERENCE(1298, /* l f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0, 0x230a _ 0) +NAMED_CHARACTER_REFERENCE(1299, /* l f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd29) +NAMED_CHARACTER_REFERENCE(1300, /* l g */ ';', 1, 0, 0x2276 _ 0) +NAMED_CHARACTER_REFERENCE(1301, /* l g */ 'E' _ ';', 2, 0, 0x2a91 _ 0) +NAMED_CHARACTER_REFERENCE(1302, /* l h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21bd _ 0) +NAMED_CHARACTER_REFERENCE(1303, /* l h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21bc _ 0) +NAMED_CHARACTER_REFERENCE(1304, /* l h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0, 0x296a _ 0) +NAMED_CHARACTER_REFERENCE(1305, /* l h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2584 _ 0) +NAMED_CHARACTER_REFERENCE(1306, /* l j */ 'c' _ 'y' _ ';', 3, 0, 0x0459 _ 0) +NAMED_CHARACTER_REFERENCE(1307, /* l l */ ';', 1, 0, 0x226a _ 0) +NAMED_CHARACTER_REFERENCE(1308, /* l l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c7 _ 0) +NAMED_CHARACTER_REFERENCE(1309, /* l l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231e _ 0) +NAMED_CHARACTER_REFERENCE(1310, /* l l */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0, 0x296b _ 0) +NAMED_CHARACTER_REFERENCE(1311, /* l l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25fa _ 0) +NAMED_CHARACTER_REFERENCE(1312, /* l m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x0140 _ 0) +NAMED_CHARACTER_REFERENCE(1313, /* l m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0, 0x23b0 _ 0) +NAMED_CHARACTER_REFERENCE(1314, /* l m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0, 0x23b0 _ 0) +NAMED_CHARACTER_REFERENCE(1315, /* l n */ 'E' _ ';', 2, 0, 0x2268 _ 0) +NAMED_CHARACTER_REFERENCE(1316, /* l n */ 'a' _ 'p' _ ';', 3, 0, 0x2a89 _ 0) +NAMED_CHARACTER_REFERENCE(1317, /* l n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7, 0, 0x2a89 _ 0) +NAMED_CHARACTER_REFERENCE(1318, /* l n */ 'e' _ ';', 2, 0, 0x2a87 _ 0) +NAMED_CHARACTER_REFERENCE(1319, /* l n */ 'e' _ 'q' _ ';', 3, 0, 0x2a87 _ 0) +NAMED_CHARACTER_REFERENCE(1320, /* l n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2268 _ 0) +NAMED_CHARACTER_REFERENCE(1321, /* l n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e6 _ 0) +NAMED_CHARACTER_REFERENCE(1322, /* l o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ec _ 0) +NAMED_CHARACTER_REFERENCE(1323, /* l o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fd _ 0) +NAMED_CHARACTER_REFERENCE(1324, /* l o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e6 _ 0) +NAMED_CHARACTER_REFERENCE(1325, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(1326, /* l o */ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 17, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(1327, /* l o */ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 9, 0, 0x27fc _ 0) +NAMED_CHARACTER_REFERENCE(1328, /* l o */ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 13, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(1329, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0, 0x21ab _ 0) +NAMED_CHARACTER_REFERENCE(1330, /* l o */ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0, 0x21ac _ 0) +NAMED_CHARACTER_REFERENCE(1331, /* l o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2985 _ 0) +NAMED_CHARACTER_REFERENCE(1332, /* l o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5d) +NAMED_CHARACTER_REFERENCE(1333, /* l o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a2d _ 0) +NAMED_CHARACTER_REFERENCE(1334, /* l o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0, 0x2a34 _ 0) +NAMED_CHARACTER_REFERENCE(1335, /* l o */ 'w' _ 'a' _ 's' _ 't' _ ';', 5, 0, 0x2217 _ 0) +NAMED_CHARACTER_REFERENCE(1336, /* l o */ 'w' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x005f _ 0) +NAMED_CHARACTER_REFERENCE(1337, /* l o */ 'z' _ ';', 2, 0, 0x25ca _ 0) +NAMED_CHARACTER_REFERENCE(1338, /* l o */ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 6, 0, 0x25ca _ 0) +NAMED_CHARACTER_REFERENCE(1339, /* l o */ 'z' _ 'f' _ ';', 3, 0, 0x29eb _ 0) +NAMED_CHARACTER_REFERENCE(1340, /* l p */ 'a' _ 'r' _ ';', 3, 0, 0x0028 _ 0) +NAMED_CHARACTER_REFERENCE(1341, /* l p */ 'a' _ 'r' _ 'l' _ 't' _ ';', 5, 0, 0x2993 _ 0) +NAMED_CHARACTER_REFERENCE(1342, /* l r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c6 _ 0) +NAMED_CHARACTER_REFERENCE(1343, /* l r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231f _ 0) +NAMED_CHARACTER_REFERENCE(1344, /* l r */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cb _ 0) +NAMED_CHARACTER_REFERENCE(1345, /* l r */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0, 0x296d _ 0) +NAMED_CHARACTER_REFERENCE(1346, /* l r */ 'm' _ ';', 2, 0, 0x200e _ 0) +NAMED_CHARACTER_REFERENCE(1347, /* l r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22bf _ 0) +NAMED_CHARACTER_REFERENCE(1348, /* l s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0, 0x2039 _ 0) +NAMED_CHARACTER_REFERENCE(1349, /* l s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc1) +NAMED_CHARACTER_REFERENCE(1350, /* l s */ 'h' _ ';', 2, 0, 0x21b0 _ 0) +NAMED_CHARACTER_REFERENCE(1351, /* l s */ 'i' _ 'm' _ ';', 3, 0, 0x2272 _ 0) +NAMED_CHARACTER_REFERENCE(1352, /* l s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8d _ 0) +NAMED_CHARACTER_REFERENCE(1353, /* l s */ 'i' _ 'm' _ 'g' _ ';', 4, 0, 0x2a8f _ 0) +NAMED_CHARACTER_REFERENCE(1354, /* l s */ 'q' _ 'b' _ ';', 3, 0, 0x005b _ 0) +NAMED_CHARACTER_REFERENCE(1355, /* l s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2018 _ 0) +NAMED_CHARACTER_REFERENCE(1356, /* l s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x201a _ 0) +NAMED_CHARACTER_REFERENCE(1357, /* l s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0142 _ 0) +NAMED_CHARACTER_REFERENCE(1358, /* l t */ 0, 0, 1, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(1359, /* l t */ ';', 1, 0, 0x003c _ 0) +NAMED_CHARACTER_REFERENCE(1360, /* l t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa6 _ 0) +NAMED_CHARACTER_REFERENCE(1361, /* l t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a79 _ 0) +NAMED_CHARACTER_REFERENCE(1362, /* l t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d6 _ 0) +NAMED_CHARACTER_REFERENCE(1363, /* l t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0, 0x22cb _ 0) +NAMED_CHARACTER_REFERENCE(1364, /* l t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x22c9 _ 0) +NAMED_CHARACTER_REFERENCE(1365, /* l t */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x2976 _ 0) +NAMED_CHARACTER_REFERENCE(1366, /* l t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0, 0x2a7b _ 0) +NAMED_CHARACTER_REFERENCE(1367, /* l t */ 'r' _ 'P' _ 'a' _ 'r' _ ';', 5, 0, 0x2996 _ 0) +NAMED_CHARACTER_REFERENCE(1368, /* l t */ 'r' _ 'i' _ ';', 3, 0, 0x25c3 _ 0) +NAMED_CHARACTER_REFERENCE(1369, /* l t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(1370, /* l t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25c2 _ 0) +NAMED_CHARACTER_REFERENCE(1371, /* l u */ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7, 0, 0x294a _ 0) +NAMED_CHARACTER_REFERENCE(1372, /* l u */ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2966 _ 0) +NAMED_CHARACTER_REFERENCE(1373, /* m D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x223a _ 0) +NAMED_CHARACTER_REFERENCE(1374, /* m a */ 'c' _ 'r', 2, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1375, /* m a */ 'c' _ 'r' _ ';', 3, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1376, /* m a */ 'l' _ 'e' _ ';', 3, 0, 0x2642 _ 0) +NAMED_CHARACTER_REFERENCE(1377, /* m a */ 'l' _ 't' _ ';', 3, 0, 0x2720 _ 0) +NAMED_CHARACTER_REFERENCE(1378, /* m a */ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 6, 0, 0x2720 _ 0) +NAMED_CHARACTER_REFERENCE(1379, /* m a */ 'p' _ ';', 2, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(1380, /* m a */ 'p' _ 's' _ 't' _ 'o' _ ';', 5, 0, 0x21a6 _ 0) +NAMED_CHARACTER_REFERENCE(1381, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 9, 0, 0x21a7 _ 0) +NAMED_CHARACTER_REFERENCE(1382, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 9, 0, 0x21a4 _ 0) +NAMED_CHARACTER_REFERENCE(1383, /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 7, 0, 0x21a5 _ 0) +NAMED_CHARACTER_REFERENCE(1384, /* m a */ 'r' _ 'k' _ 'e' _ 'r' _ ';', 5, 0, 0x25ae _ 0) +NAMED_CHARACTER_REFERENCE(1385, /* m c */ 'o' _ 'm' _ 'm' _ 'a' _ ';', 5, 0, 0x2a29 _ 0) +NAMED_CHARACTER_REFERENCE(1386, /* m c */ 'y' _ ';', 2, 0, 0x043c _ 0) +NAMED_CHARACTER_REFERENCE(1387, /* m d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2014 _ 0) +NAMED_CHARACTER_REFERENCE(1388, /* m e */ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12, 0, 0x2221 _ 0) +NAMED_CHARACTER_REFERENCE(1389, /* m f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2a) +NAMED_CHARACTER_REFERENCE(1390, /* m h */ 'o' _ ';', 2, 0, 0x2127 _ 0) +NAMED_CHARACTER_REFERENCE(1391, /* m i */ 'c' _ 'r' _ 'o', 3, 0, 0x00b5 _ 0) +NAMED_CHARACTER_REFERENCE(1392, /* m i */ 'c' _ 'r' _ 'o' _ ';', 4, 0, 0x00b5 _ 0) +NAMED_CHARACTER_REFERENCE(1393, /* m i */ 'd' _ ';', 2, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1394, /* m i */ 'd' _ 'a' _ 's' _ 't' _ ';', 5, 0, 0x002a _ 0) +NAMED_CHARACTER_REFERENCE(1395, /* m i */ 'd' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, 0x2af0 _ 0) +NAMED_CHARACTER_REFERENCE(1396, /* m i */ 'd' _ 'd' _ 'o' _ 't', 4, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(1397, /* m i */ 'd' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x00b7 _ 0) +NAMED_CHARACTER_REFERENCE(1398, /* m i */ 'n' _ 'u' _ 's' _ ';', 4, 0, 0x2212 _ 0) +NAMED_CHARACTER_REFERENCE(1399, /* m i */ 'n' _ 'u' _ 's' _ 'b' _ ';', 5, 0, 0x229f _ 0) +NAMED_CHARACTER_REFERENCE(1400, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ ';', 5, 0, 0x2238 _ 0) +NAMED_CHARACTER_REFERENCE(1401, /* m i */ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 6, 0, 0x2a2a _ 0) +NAMED_CHARACTER_REFERENCE(1402, /* m l */ 'c' _ 'p' _ ';', 3, 0, 0x2adb _ 0) +NAMED_CHARACTER_REFERENCE(1403, /* m l */ 'd' _ 'r' _ ';', 3, 0, 0x2026 _ 0) +NAMED_CHARACTER_REFERENCE(1404, /* m n */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(1405, /* m o */ 'd' _ 'e' _ 'l' _ 's' _ ';', 5, 0, 0x22a7 _ 0) +NAMED_CHARACTER_REFERENCE(1406, /* m o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5e) +NAMED_CHARACTER_REFERENCE(1407, /* m p */ ';', 1, 0, 0x2213 _ 0) +NAMED_CHARACTER_REFERENCE(1408, /* m s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc2) +NAMED_CHARACTER_REFERENCE(1409, /* m s */ 't' _ 'p' _ 'o' _ 's' _ ';', 5, 0, 0x223e _ 0) +NAMED_CHARACTER_REFERENCE(1410, /* m u */ ';', 1, 0, 0x03bc _ 0) +NAMED_CHARACTER_REFERENCE(1411, /* m u */ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 7, 0, 0x22b8 _ 0) +NAMED_CHARACTER_REFERENCE(1412, /* m u */ 'm' _ 'a' _ 'p' _ ';', 4, 0, 0x22b8 _ 0) +NAMED_CHARACTER_REFERENCE(1413, /* n L */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x21cd _ 0) +NAMED_CHARACTER_REFERENCE(1414, /* n L */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21ce _ 0) +NAMED_CHARACTER_REFERENCE(1415, /* n R */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x21cf _ 0) +NAMED_CHARACTER_REFERENCE(1416, /* n V */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22af _ 0) +NAMED_CHARACTER_REFERENCE(1417, /* n V */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22ae _ 0) +NAMED_CHARACTER_REFERENCE(1418, /* n a */ 'b' _ 'l' _ 'a' _ ';', 4, 0, 0x2207 _ 0) +NAMED_CHARACTER_REFERENCE(1419, /* n a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0144 _ 0) +NAMED_CHARACTER_REFERENCE(1420, /* n a */ 'p' _ ';', 2, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(1421, /* n a */ 'p' _ 'o' _ 's' _ ';', 4, 0, 0x0149 _ 0) +NAMED_CHARACTER_REFERENCE(1422, /* n a */ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 6, 0, 0x2249 _ 0) +NAMED_CHARACTER_REFERENCE(1423, /* n a */ 't' _ 'u' _ 'r' _ ';', 4, 0, 0x266e _ 0) +NAMED_CHARACTER_REFERENCE(1424, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 6, 0, 0x266e _ 0) +NAMED_CHARACTER_REFERENCE(1425, /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 7, 0, 0x2115 _ 0) +NAMED_CHARACTER_REFERENCE(1426, /* n b */ 's' _ 'p', 2, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(1427, /* n b */ 's' _ 'p' _ ';', 3, 0, 0x00a0 _ 0) +NAMED_CHARACTER_REFERENCE(1428, /* n c */ 'a' _ 'p' _ ';', 3, 0, 0x2a43 _ 0) +NAMED_CHARACTER_REFERENCE(1429, /* n c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0148 _ 0) +NAMED_CHARACTER_REFERENCE(1430, /* n c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0146 _ 0) +NAMED_CHARACTER_REFERENCE(1431, /* n c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x2247 _ 0) +NAMED_CHARACTER_REFERENCE(1432, /* n c */ 'u' _ 'p' _ ';', 3, 0, 0x2a42 _ 0) +NAMED_CHARACTER_REFERENCE(1433, /* n c */ 'y' _ ';', 2, 0, 0x043d _ 0) +NAMED_CHARACTER_REFERENCE(1434, /* n d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2013 _ 0) +NAMED_CHARACTER_REFERENCE(1435, /* n e */ ';', 1, 0, 0x2260 _ 0) +NAMED_CHARACTER_REFERENCE(1436, /* n e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d7 _ 0) +NAMED_CHARACTER_REFERENCE(1437, /* n e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2924 _ 0) +NAMED_CHARACTER_REFERENCE(1438, /* n e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(1439, /* n e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2197 _ 0) +NAMED_CHARACTER_REFERENCE(1440, /* n e */ 'q' _ 'u' _ 'i' _ 'v' _ ';', 5, 0, 0x2262 _ 0) +NAMED_CHARACTER_REFERENCE(1441, /* n e */ 's' _ 'e' _ 'a' _ 'r' _ ';', 5, 0, 0x2928 _ 0) +NAMED_CHARACTER_REFERENCE(1442, /* n e */ 'x' _ 'i' _ 's' _ 't' _ ';', 5, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(1443, /* n e */ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 6, 0, 0x2204 _ 0) +NAMED_CHARACTER_REFERENCE(1444, /* n f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2b) +NAMED_CHARACTER_REFERENCE(1445, /* n g */ 'e' _ ';', 2, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(1446, /* n g */ 'e' _ 'q' _ ';', 3, 0, 0x2271 _ 0) +NAMED_CHARACTER_REFERENCE(1447, /* n g */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2275 _ 0) +NAMED_CHARACTER_REFERENCE(1448, /* n g */ 't' _ ';', 2, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(1449, /* n g */ 't' _ 'r' _ ';', 3, 0, 0x226f _ 0) +NAMED_CHARACTER_REFERENCE(1450, /* n h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21ce _ 0) +NAMED_CHARACTER_REFERENCE(1451, /* n h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ae _ 0) +NAMED_CHARACTER_REFERENCE(1452, /* n h */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2af2 _ 0) +NAMED_CHARACTER_REFERENCE(1453, /* n i */ ';', 1, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(1454, /* n i */ 's' _ ';', 2, 0, 0x22fc _ 0) +NAMED_CHARACTER_REFERENCE(1455, /* n i */ 's' _ 'd' _ ';', 3, 0, 0x22fa _ 0) +NAMED_CHARACTER_REFERENCE(1456, /* n i */ 'v' _ ';', 2, 0, 0x220b _ 0) +NAMED_CHARACTER_REFERENCE(1457, /* n j */ 'c' _ 'y' _ ';', 3, 0, 0x045a _ 0) +NAMED_CHARACTER_REFERENCE(1458, /* n l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cd _ 0) +NAMED_CHARACTER_REFERENCE(1459, /* n l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219a _ 0) +NAMED_CHARACTER_REFERENCE(1460, /* n l */ 'd' _ 'r' _ ';', 3, 0, 0x2025 _ 0) +NAMED_CHARACTER_REFERENCE(1461, /* n l */ 'e' _ ';', 2, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(1462, /* n l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x219a _ 0) +NAMED_CHARACTER_REFERENCE(1463, /* n l */ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x21ae _ 0) +NAMED_CHARACTER_REFERENCE(1464, /* n l */ 'e' _ 'q' _ ';', 3, 0, 0x2270 _ 0) +NAMED_CHARACTER_REFERENCE(1465, /* n l */ 'e' _ 's' _ 's' _ ';', 4, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(1466, /* n l */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2274 _ 0) +NAMED_CHARACTER_REFERENCE(1467, /* n l */ 't' _ ';', 2, 0, 0x226e _ 0) +NAMED_CHARACTER_REFERENCE(1468, /* n l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(1469, /* n l */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(1470, /* n m */ 'i' _ 'd' _ ';', 3, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1471, /* n o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5f) +NAMED_CHARACTER_REFERENCE(1472, /* n o */ 't', 1, 0, 0x00ac _ 0) +NAMED_CHARACTER_REFERENCE(1473, /* n o */ 't' _ ';', 2, 0, 0x00ac _ 0) +NAMED_CHARACTER_REFERENCE(1474, /* n o */ 't' _ 'i' _ 'n' _ ';', 4, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(1475, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 6, 0, 0x2209 _ 0) +NAMED_CHARACTER_REFERENCE(1476, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 6, 0, 0x22f7 _ 0) +NAMED_CHARACTER_REFERENCE(1477, /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 6, 0, 0x22f6 _ 0) +NAMED_CHARACTER_REFERENCE(1478, /* n o */ 't' _ 'n' _ 'i' _ ';', 4, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(1479, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 6, 0, 0x220c _ 0) +NAMED_CHARACTER_REFERENCE(1480, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 6, 0, 0x22fe _ 0) +NAMED_CHARACTER_REFERENCE(1481, /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 6, 0, 0x22fd _ 0) +NAMED_CHARACTER_REFERENCE(1482, /* n p */ 'a' _ 'r' _ ';', 3, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1483, /* n p */ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 8, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1484, /* n p */ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 6, 0, 0x2a14 _ 0) +NAMED_CHARACTER_REFERENCE(1485, /* n p */ 'r' _ ';', 2, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(1486, /* n p */ 'r' _ 'c' _ 'u' _ 'e' _ ';', 5, 0, 0x22e0 _ 0) +NAMED_CHARACTER_REFERENCE(1487, /* n p */ 'r' _ 'e' _ 'c' _ ';', 4, 0, 0x2280 _ 0) +NAMED_CHARACTER_REFERENCE(1488, /* n r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cf _ 0) +NAMED_CHARACTER_REFERENCE(1489, /* n r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219b _ 0) +NAMED_CHARACTER_REFERENCE(1490, /* n r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x219b _ 0) +NAMED_CHARACTER_REFERENCE(1491, /* n r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(1492, /* n r */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(1493, /* n s */ 'c' _ ';', 2, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(1494, /* n s */ 'c' _ 'c' _ 'u' _ 'e' _ ';', 5, 0, 0x22e1 _ 0) +NAMED_CHARACTER_REFERENCE(1495, /* n s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc3) +NAMED_CHARACTER_REFERENCE(1496, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 8, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1497, /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 13, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1498, /* n s */ 'i' _ 'm' _ ';', 3, 0, 0x2241 _ 0) +NAMED_CHARACTER_REFERENCE(1499, /* n s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(1500, /* n s */ 'i' _ 'm' _ 'e' _ 'q' _ ';', 5, 0, 0x2244 _ 0) +NAMED_CHARACTER_REFERENCE(1501, /* n s */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2224 _ 0) +NAMED_CHARACTER_REFERENCE(1502, /* n s */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2226 _ 0) +NAMED_CHARACTER_REFERENCE(1503, /* n s */ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0, 0x22e2 _ 0) +NAMED_CHARACTER_REFERENCE(1504, /* n s */ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0, 0x22e3 _ 0) +NAMED_CHARACTER_REFERENCE(1505, /* n s */ 'u' _ 'b' _ ';', 3, 0, 0x2284 _ 0) +NAMED_CHARACTER_REFERENCE(1506, /* n s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(1507, /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2288 _ 0) +NAMED_CHARACTER_REFERENCE(1508, /* n s */ 'u' _ 'c' _ 'c' _ ';', 4, 0, 0x2281 _ 0) +NAMED_CHARACTER_REFERENCE(1509, /* n s */ 'u' _ 'p' _ ';', 3, 0, 0x2285 _ 0) +NAMED_CHARACTER_REFERENCE(1510, /* n s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(1511, /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2289 _ 0) +NAMED_CHARACTER_REFERENCE(1512, /* n t */ 'g' _ 'l' _ ';', 3, 0, 0x2279 _ 0) +NAMED_CHARACTER_REFERENCE(1513, /* n t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f1 _ 0) +NAMED_CHARACTER_REFERENCE(1514, /* n t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00f1 _ 0) +NAMED_CHARACTER_REFERENCE(1515, /* n t */ 'l' _ 'g' _ ';', 3, 0, 0x2278 _ 0) +NAMED_CHARACTER_REFERENCE(1516, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0, 0x22ea _ 0) +NAMED_CHARACTER_REFERENCE(1517, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 14, 0, 0x22ec _ 0) +NAMED_CHARACTER_REFERENCE(1518, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0, 0x22eb _ 0) +NAMED_CHARACTER_REFERENCE(1519, /* n t */ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 15, 0, 0x22ed _ 0) +NAMED_CHARACTER_REFERENCE(1520, /* n u */ ';', 1, 0, 0x03bd _ 0) +NAMED_CHARACTER_REFERENCE(1521, /* n u */ 'm' _ ';', 2, 0, 0x0023 _ 0) +NAMED_CHARACTER_REFERENCE(1522, /* n u */ 'm' _ 'e' _ 'r' _ 'o' _ ';', 5, 0, 0x2116 _ 0) +NAMED_CHARACTER_REFERENCE(1523, /* n u */ 'm' _ 's' _ 'p' _ ';', 4, 0, 0x2007 _ 0) +NAMED_CHARACTER_REFERENCE(1524, /* n v */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22ad _ 0) +NAMED_CHARACTER_REFERENCE(1525, /* n v */ 'H' _ 'a' _ 'r' _ 'r' _ ';', 5, 0, 0x2904 _ 0) +NAMED_CHARACTER_REFERENCE(1526, /* n v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x22ac _ 0) +NAMED_CHARACTER_REFERENCE(1527, /* n v */ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0, 0x29de _ 0) +NAMED_CHARACTER_REFERENCE(1528, /* n v */ 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0, 0x2902 _ 0) +NAMED_CHARACTER_REFERENCE(1529, /* n v */ 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0, 0x2903 _ 0) +NAMED_CHARACTER_REFERENCE(1530, /* n w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d6 _ 0) +NAMED_CHARACTER_REFERENCE(1531, /* n w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2923 _ 0) +NAMED_CHARACTER_REFERENCE(1532, /* n w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(1533, /* n w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2196 _ 0) +NAMED_CHARACTER_REFERENCE(1534, /* n w */ 'n' _ 'e' _ 'a' _ 'r' _ ';', 5, 0, 0x2927 _ 0) +NAMED_CHARACTER_REFERENCE(1535, /* o S */ ';', 1, 0, 0x24c8 _ 0) +NAMED_CHARACTER_REFERENCE(1536, /* o a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00f3 _ 0) +NAMED_CHARACTER_REFERENCE(1537, /* o a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00f3 _ 0) +NAMED_CHARACTER_REFERENCE(1538, /* o a */ 's' _ 't' _ ';', 3, 0, 0x229b _ 0) +NAMED_CHARACTER_REFERENCE(1539, /* o c */ 'i' _ 'r' _ ';', 3, 0, 0x229a _ 0) +NAMED_CHARACTER_REFERENCE(1540, /* o c */ 'i' _ 'r' _ 'c', 3, 0, 0x00f4 _ 0) +NAMED_CHARACTER_REFERENCE(1541, /* o c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00f4 _ 0) +NAMED_CHARACTER_REFERENCE(1542, /* o c */ 'y' _ ';', 2, 0, 0x043e _ 0) +NAMED_CHARACTER_REFERENCE(1543, /* o d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x229d _ 0) +NAMED_CHARACTER_REFERENCE(1544, /* o d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0151 _ 0) +NAMED_CHARACTER_REFERENCE(1545, /* o d */ 'i' _ 'v' _ ';', 3, 0, 0x2a38 _ 0) +NAMED_CHARACTER_REFERENCE(1546, /* o d */ 'o' _ 't' _ ';', 3, 0, 0x2299 _ 0) +NAMED_CHARACTER_REFERENCE(1547, /* o d */ 's' _ 'o' _ 'l' _ 'd' _ ';', 5, 0, 0x29bc _ 0) +NAMED_CHARACTER_REFERENCE(1548, /* o e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0153 _ 0) +NAMED_CHARACTER_REFERENCE(1549, /* o f */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29bf _ 0) +NAMED_CHARACTER_REFERENCE(1550, /* o f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2c) +NAMED_CHARACTER_REFERENCE(1551, /* o g */ 'o' _ 'n' _ ';', 3, 0, 0x02db _ 0) +NAMED_CHARACTER_REFERENCE(1552, /* o g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f2 _ 0) +NAMED_CHARACTER_REFERENCE(1553, /* o g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00f2 _ 0) +NAMED_CHARACTER_REFERENCE(1554, /* o g */ 't' _ ';', 2, 0, 0x29c1 _ 0) +NAMED_CHARACTER_REFERENCE(1555, /* o h */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x29b5 _ 0) +NAMED_CHARACTER_REFERENCE(1556, /* o h */ 'm' _ ';', 2, 0, 0x03a9 _ 0) +NAMED_CHARACTER_REFERENCE(1557, /* o i */ 'n' _ 't' _ ';', 3, 0, 0x222e _ 0) +NAMED_CHARACTER_REFERENCE(1558, /* o l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ba _ 0) +NAMED_CHARACTER_REFERENCE(1559, /* o l */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29be _ 0) +NAMED_CHARACTER_REFERENCE(1560, /* o l */ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0, 0x29bb _ 0) +NAMED_CHARACTER_REFERENCE(1561, /* o l */ 'i' _ 'n' _ 'e' _ ';', 4, 0, 0x203e _ 0) +NAMED_CHARACTER_REFERENCE(1562, /* o l */ 't' _ ';', 2, 0, 0x29c0 _ 0) +NAMED_CHARACTER_REFERENCE(1563, /* o m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014d _ 0) +NAMED_CHARACTER_REFERENCE(1564, /* o m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03c9 _ 0) +NAMED_CHARACTER_REFERENCE(1565, /* o m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0, 0x03bf _ 0) +NAMED_CHARACTER_REFERENCE(1566, /* o m */ 'i' _ 'd' _ ';', 3, 0, 0x29b6 _ 0) +NAMED_CHARACTER_REFERENCE(1567, /* o m */ 'i' _ 'n' _ 'u' _ 's' _ ';', 5, 0, 0x2296 _ 0) +NAMED_CHARACTER_REFERENCE(1568, /* o o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd60) +NAMED_CHARACTER_REFERENCE(1569, /* o p */ 'a' _ 'r' _ ';', 3, 0, 0x29b7 _ 0) +NAMED_CHARACTER_REFERENCE(1570, /* o p */ 'e' _ 'r' _ 'p' _ ';', 4, 0, 0x29b9 _ 0) +NAMED_CHARACTER_REFERENCE(1571, /* o p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2295 _ 0) +NAMED_CHARACTER_REFERENCE(1572, /* o r */ ';', 1, 0, 0x2228 _ 0) +NAMED_CHARACTER_REFERENCE(1573, /* o r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21bb _ 0) +NAMED_CHARACTER_REFERENCE(1574, /* o r */ 'd' _ ';', 2, 0, 0x2a5d _ 0) +NAMED_CHARACTER_REFERENCE(1575, /* o r */ 'd' _ 'e' _ 'r' _ ';', 4, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1576, /* o r */ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 6, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1577, /* o r */ 'd' _ 'f', 2, 0, 0x00aa _ 0) +NAMED_CHARACTER_REFERENCE(1578, /* o r */ 'd' _ 'f' _ ';', 3, 0, 0x00aa _ 0) +NAMED_CHARACTER_REFERENCE(1579, /* o r */ 'd' _ 'm', 2, 0, 0x00ba _ 0) +NAMED_CHARACTER_REFERENCE(1580, /* o r */ 'd' _ 'm' _ ';', 3, 0, 0x00ba _ 0) +NAMED_CHARACTER_REFERENCE(1581, /* o r */ 'i' _ 'g' _ 'o' _ 'f' _ ';', 5, 0, 0x22b6 _ 0) +NAMED_CHARACTER_REFERENCE(1582, /* o r */ 'o' _ 'r' _ ';', 3, 0, 0x2a56 _ 0) +NAMED_CHARACTER_REFERENCE(1583, /* o r */ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 6, 0, 0x2a57 _ 0) +NAMED_CHARACTER_REFERENCE(1584, /* o r */ 'v' _ ';', 2, 0, 0x2a5b _ 0) +NAMED_CHARACTER_REFERENCE(1585, /* o s */ 'c' _ 'r' _ ';', 3, 0, 0x2134 _ 0) +NAMED_CHARACTER_REFERENCE(1586, /* o s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00f8 _ 0) +NAMED_CHARACTER_REFERENCE(1587, /* o s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0, 0x00f8 _ 0) +NAMED_CHARACTER_REFERENCE(1588, /* o s */ 'o' _ 'l' _ ';', 3, 0, 0x2298 _ 0) +NAMED_CHARACTER_REFERENCE(1589, /* o t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f5 _ 0) +NAMED_CHARACTER_REFERENCE(1590, /* o t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x00f5 _ 0) +NAMED_CHARACTER_REFERENCE(1591, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x2297 _ 0) +NAMED_CHARACTER_REFERENCE(1592, /* o t */ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 7, 0, 0x2a36 _ 0) +NAMED_CHARACTER_REFERENCE(1593, /* o u */ 'm' _ 'l', 2, 0, 0x00f6 _ 0) +NAMED_CHARACTER_REFERENCE(1594, /* o u */ 'm' _ 'l' _ ';', 3, 0, 0x00f6 _ 0) +NAMED_CHARACTER_REFERENCE(1595, /* o v */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x233d _ 0) +NAMED_CHARACTER_REFERENCE(1596, /* p a */ 'r' _ ';', 2, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1597, /* p a */ 'r' _ 'a', 2, 0, 0x00b6 _ 0) +NAMED_CHARACTER_REFERENCE(1598, /* p a */ 'r' _ 'a' _ ';', 3, 0, 0x00b6 _ 0) +NAMED_CHARACTER_REFERENCE(1599, /* p a */ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 7, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1600, /* p a */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2af3 _ 0) +NAMED_CHARACTER_REFERENCE(1601, /* p a */ 'r' _ 's' _ 'l' _ ';', 4, 0, 0x2afd _ 0) +NAMED_CHARACTER_REFERENCE(1602, /* p a */ 'r' _ 't' _ ';', 3, 0, 0x2202 _ 0) +NAMED_CHARACTER_REFERENCE(1603, /* p c */ 'y' _ ';', 2, 0, 0x043f _ 0) +NAMED_CHARACTER_REFERENCE(1604, /* p e */ 'r' _ 'c' _ 'n' _ 't' _ ';', 5, 0, 0x0025 _ 0) +NAMED_CHARACTER_REFERENCE(1605, /* p e */ 'r' _ 'i' _ 'o' _ 'd' _ ';', 5, 0, 0x002e _ 0) +NAMED_CHARACTER_REFERENCE(1606, /* p e */ 'r' _ 'm' _ 'i' _ 'l' _ ';', 5, 0, 0x2030 _ 0) +NAMED_CHARACTER_REFERENCE(1607, /* p e */ 'r' _ 'p' _ ';', 3, 0, 0x22a5 _ 0) +NAMED_CHARACTER_REFERENCE(1608, /* p e */ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 6, 0, 0x2031 _ 0) +NAMED_CHARACTER_REFERENCE(1609, /* p f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2d) +NAMED_CHARACTER_REFERENCE(1610, /* p h */ 'i' _ ';', 2, 0, 0x03c6 _ 0) +NAMED_CHARACTER_REFERENCE(1611, /* p h */ 'i' _ 'v' _ ';', 3, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(1612, /* p h */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0, 0x2133 _ 0) +NAMED_CHARACTER_REFERENCE(1613, /* p h */ 'o' _ 'n' _ 'e' _ ';', 4, 0, 0x260e _ 0) +NAMED_CHARACTER_REFERENCE(1614, /* p i */ ';', 1, 0, 0x03c0 _ 0) +NAMED_CHARACTER_REFERENCE(1615, /* p i */ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0, 0x22d4 _ 0) +NAMED_CHARACTER_REFERENCE(1616, /* p i */ 'v' _ ';', 2, 0, 0x03d6 _ 0) +NAMED_CHARACTER_REFERENCE(1617, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ ';', 5, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1618, /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 6, 0, 0x210e _ 0) +NAMED_CHARACTER_REFERENCE(1619, /* p l */ 'a' _ 'n' _ 'k' _ 'v' _ ';', 5, 0, 0x210f _ 0) +NAMED_CHARACTER_REFERENCE(1620, /* p l */ 'u' _ 's' _ ';', 3, 0, 0x002b _ 0) +NAMED_CHARACTER_REFERENCE(1621, /* p l */ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 7, 0, 0x2a23 _ 0) +NAMED_CHARACTER_REFERENCE(1622, /* p l */ 'u' _ 's' _ 'b' _ ';', 4, 0, 0x229e _ 0) +NAMED_CHARACTER_REFERENCE(1623, /* p l */ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0, 0x2a22 _ 0) +NAMED_CHARACTER_REFERENCE(1624, /* p l */ 'u' _ 's' _ 'd' _ 'o' _ ';', 5, 0, 0x2214 _ 0) +NAMED_CHARACTER_REFERENCE(1625, /* p l */ 'u' _ 's' _ 'd' _ 'u' _ ';', 5, 0, 0x2a25 _ 0) +NAMED_CHARACTER_REFERENCE(1626, /* p l */ 'u' _ 's' _ 'e' _ ';', 4, 0, 0x2a72 _ 0) +NAMED_CHARACTER_REFERENCE(1627, /* p l */ 'u' _ 's' _ 'm' _ 'n', 4, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1628, /* p l */ 'u' _ 's' _ 'm' _ 'n' _ ';', 5, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1629, /* p l */ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2a26 _ 0) +NAMED_CHARACTER_REFERENCE(1630, /* p l */ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 6, 0, 0x2a27 _ 0) +NAMED_CHARACTER_REFERENCE(1631, /* p m */ ';', 1, 0, 0x00b1 _ 0) +NAMED_CHARACTER_REFERENCE(1632, /* p o */ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a15 _ 0) +NAMED_CHARACTER_REFERENCE(1633, /* p o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd61) +NAMED_CHARACTER_REFERENCE(1634, /* p o */ 'u' _ 'n' _ 'd', 3, 0, 0x00a3 _ 0) +NAMED_CHARACTER_REFERENCE(1635, /* p o */ 'u' _ 'n' _ 'd' _ ';', 4, 0, 0x00a3 _ 0) +NAMED_CHARACTER_REFERENCE(1636, /* p r */ ';', 1, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(1637, /* p r */ 'E' _ ';', 2, 0, 0x2ab3 _ 0) +NAMED_CHARACTER_REFERENCE(1638, /* p r */ 'a' _ 'p' _ ';', 3, 0, 0x2ab7 _ 0) +NAMED_CHARACTER_REFERENCE(1639, /* p r */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(1640, /* p r */ 'e' _ ';', 2, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(1641, /* p r */ 'e' _ 'c' _ ';', 3, 0, 0x227a _ 0) +NAMED_CHARACTER_REFERENCE(1642, /* p r */ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, 0x2ab7 _ 0) +NAMED_CHARACTER_REFERENCE(1643, /* p r */ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0, 0x227c _ 0) +NAMED_CHARACTER_REFERENCE(1644, /* p r */ 'e' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, 0x2aaf _ 0) +NAMED_CHARACTER_REFERENCE(1645, /* p r */ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, 0x2ab9 _ 0) +NAMED_CHARACTER_REFERENCE(1646, /* p r */ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0, 0x2ab5 _ 0) +NAMED_CHARACTER_REFERENCE(1647, /* p r */ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0, 0x22e8 _ 0) +NAMED_CHARACTER_REFERENCE(1648, /* p r */ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(1649, /* p r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2032 _ 0) +NAMED_CHARACTER_REFERENCE(1650, /* p r */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x2119 _ 0) +NAMED_CHARACTER_REFERENCE(1651, /* p r */ 'n' _ 'E' _ ';', 3, 0, 0x2ab5 _ 0) +NAMED_CHARACTER_REFERENCE(1652, /* p r */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2ab9 _ 0) +NAMED_CHARACTER_REFERENCE(1653, /* p r */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x22e8 _ 0) +NAMED_CHARACTER_REFERENCE(1654, /* p r */ 'o' _ 'd' _ ';', 3, 0, 0x220f _ 0) +NAMED_CHARACTER_REFERENCE(1655, /* p r */ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 7, 0, 0x232e _ 0) +NAMED_CHARACTER_REFERENCE(1656, /* p r */ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7, 0, 0x2312 _ 0) +NAMED_CHARACTER_REFERENCE(1657, /* p r */ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 7, 0, 0x2313 _ 0) +NAMED_CHARACTER_REFERENCE(1658, /* p r */ 'o' _ 'p' _ ';', 3, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(1659, /* p r */ 'o' _ 'p' _ 't' _ 'o' _ ';', 5, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(1660, /* p r */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227e _ 0) +NAMED_CHARACTER_REFERENCE(1661, /* p r */ 'u' _ 'r' _ 'e' _ 'l' _ ';', 5, 0, 0x22b0 _ 0) +NAMED_CHARACTER_REFERENCE(1662, /* p s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc5) +NAMED_CHARACTER_REFERENCE(1663, /* p s */ 'i' _ ';', 2, 0, 0x03c8 _ 0) +NAMED_CHARACTER_REFERENCE(1664, /* p u */ 'n' _ 'c' _ 's' _ 'p' _ ';', 5, 0, 0x2008 _ 0) +NAMED_CHARACTER_REFERENCE(1665, /* q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2e) +NAMED_CHARACTER_REFERENCE(1666, /* q i */ 'n' _ 't' _ ';', 3, 0, 0x2a0c _ 0) +NAMED_CHARACTER_REFERENCE(1667, /* q o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd62) +NAMED_CHARACTER_REFERENCE(1668, /* q p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2057 _ 0) +NAMED_CHARACTER_REFERENCE(1669, /* q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc6) +NAMED_CHARACTER_REFERENCE(1670, /* q u */ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 10, 0, 0x210d _ 0) +NAMED_CHARACTER_REFERENCE(1671, /* q u */ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 6, 0, 0x2a16 _ 0) +NAMED_CHARACTER_REFERENCE(1672, /* q u */ 'e' _ 's' _ 't' _ ';', 4, 0, 0x003f _ 0) +NAMED_CHARACTER_REFERENCE(1673, /* q u */ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 6, 0, 0x225f _ 0) +NAMED_CHARACTER_REFERENCE(1674, /* q u */ 'o' _ 't', 2, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(1675, /* q u */ 'o' _ 't' _ ';', 3, 0, 0x0022 _ 0) +NAMED_CHARACTER_REFERENCE(1676, /* r A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21db _ 0) +NAMED_CHARACTER_REFERENCE(1677, /* r A */ 'r' _ 'r' _ ';', 3, 0, 0x21d2 _ 0) +NAMED_CHARACTER_REFERENCE(1678, /* r A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x291c _ 0) +NAMED_CHARACTER_REFERENCE(1679, /* r B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290f _ 0) +NAMED_CHARACTER_REFERENCE(1680, /* r H */ 'a' _ 'r' _ ';', 3, 0, 0x2964 _ 0) +NAMED_CHARACTER_REFERENCE(1681, /* r a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x0155 _ 0) +NAMED_CHARACTER_REFERENCE(1682, /* r a */ 'd' _ 'i' _ 'c' _ ';', 4, 0, 0x221a _ 0) +NAMED_CHARACTER_REFERENCE(1683, /* r a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7, 0, 0x29b3 _ 0) +NAMED_CHARACTER_REFERENCE(1684, /* r a */ 'n' _ 'g' _ ';', 3, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(1685, /* r a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2992 _ 0) +NAMED_CHARACTER_REFERENCE(1686, /* r a */ 'n' _ 'g' _ 'e' _ ';', 4, 0, 0x29a5 _ 0) +NAMED_CHARACTER_REFERENCE(1687, /* r a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0, 0x27e9 _ 0) +NAMED_CHARACTER_REFERENCE(1688, /* r a */ 'q' _ 'u' _ 'o', 3, 0, 0x00bb _ 0) +NAMED_CHARACTER_REFERENCE(1689, /* r a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00bb _ 0) +NAMED_CHARACTER_REFERENCE(1690, /* r a */ 'r' _ 'r' _ ';', 3, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1691, /* r a */ 'r' _ 'r' _ 'a' _ 'p' _ ';', 5, 0, 0x2975 _ 0) +NAMED_CHARACTER_REFERENCE(1692, /* r a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e5 _ 0) +NAMED_CHARACTER_REFERENCE(1693, /* r a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0, 0x2920 _ 0) +NAMED_CHARACTER_REFERENCE(1694, /* r a */ 'r' _ 'r' _ 'c' _ ';', 4, 0, 0x2933 _ 0) +NAMED_CHARACTER_REFERENCE(1695, /* r a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0, 0x291e _ 0) +NAMED_CHARACTER_REFERENCE(1696, /* r a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x21aa _ 0) +NAMED_CHARACTER_REFERENCE(1697, /* r a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0, 0x21ac _ 0) +NAMED_CHARACTER_REFERENCE(1698, /* r a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0, 0x2945 _ 0) +NAMED_CHARACTER_REFERENCE(1699, /* r a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x2974 _ 0) +NAMED_CHARACTER_REFERENCE(1700, /* r a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0, 0x21a3 _ 0) +NAMED_CHARACTER_REFERENCE(1701, /* r a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x219d _ 0) +NAMED_CHARACTER_REFERENCE(1702, /* r a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0, 0x291a _ 0) +NAMED_CHARACTER_REFERENCE(1703, /* r a */ 't' _ 'i' _ 'o' _ ';', 4, 0, 0x2236 _ 0) +NAMED_CHARACTER_REFERENCE(1704, /* r a */ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ 's' _ ';', 8, 0, 0x211a _ 0) +NAMED_CHARACTER_REFERENCE(1705, /* r b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290d _ 0) +NAMED_CHARACTER_REFERENCE(1706, /* r b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2773 _ 0) +NAMED_CHARACTER_REFERENCE(1707, /* r b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0, 0x007d _ 0) +NAMED_CHARACTER_REFERENCE(1708, /* r b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0, 0x005d _ 0) +NAMED_CHARACTER_REFERENCE(1709, /* r b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298c _ 0) +NAMED_CHARACTER_REFERENCE(1710, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0, 0x298e _ 0) +NAMED_CHARACTER_REFERENCE(1711, /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0, 0x2990 _ 0) +NAMED_CHARACTER_REFERENCE(1712, /* r c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0159 _ 0) +NAMED_CHARACTER_REFERENCE(1713, /* r c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0157 _ 0) +NAMED_CHARACTER_REFERENCE(1714, /* r c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2309 _ 0) +NAMED_CHARACTER_REFERENCE(1715, /* r c */ 'u' _ 'b' _ ';', 3, 0, 0x007d _ 0) +NAMED_CHARACTER_REFERENCE(1716, /* r c */ 'y' _ ';', 2, 0, 0x0440 _ 0) +NAMED_CHARACTER_REFERENCE(1717, /* r d */ 'c' _ 'a' _ ';', 3, 0, 0x2937 _ 0) +NAMED_CHARACTER_REFERENCE(1718, /* r d */ 'l' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2969 _ 0) +NAMED_CHARACTER_REFERENCE(1719, /* r d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(1720, /* r d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x201d _ 0) +NAMED_CHARACTER_REFERENCE(1721, /* r d */ 's' _ 'h' _ ';', 3, 0, 0x21b3 _ 0) +NAMED_CHARACTER_REFERENCE(1722, /* r e */ 'a' _ 'l' _ ';', 3, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(1723, /* r e */ 'a' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0, 0x211b _ 0) +NAMED_CHARACTER_REFERENCE(1724, /* r e */ 'a' _ 'l' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7, 0, 0x211c _ 0) +NAMED_CHARACTER_REFERENCE(1725, /* r e */ 'a' _ 'l' _ 's' _ ';', 4, 0, 0x211d _ 0) +NAMED_CHARACTER_REFERENCE(1726, /* r e */ 'c' _ 't' _ ';', 3, 0, 0x25ad _ 0) +NAMED_CHARACTER_REFERENCE(1727, /* r e */ 'g', 1, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(1728, /* r e */ 'g' _ ';', 2, 0, 0x00ae _ 0) +NAMED_CHARACTER_REFERENCE(1729, /* r f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297d _ 0) +NAMED_CHARACTER_REFERENCE(1730, /* r f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0, 0x230b _ 0) +NAMED_CHARACTER_REFERENCE(1731, /* r f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2f) +NAMED_CHARACTER_REFERENCE(1732, /* r h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(1733, /* r h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(1734, /* r h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0, 0x296c _ 0) +NAMED_CHARACTER_REFERENCE(1735, /* r h */ 'o' _ ';', 2, 0, 0x03c1 _ 0) +NAMED_CHARACTER_REFERENCE(1736, /* r h */ 'o' _ 'v' _ ';', 3, 0, 0x03f1 _ 0) +NAMED_CHARACTER_REFERENCE(1737, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1738, /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 13, 0, 0x21a3 _ 0) +NAMED_CHARACTER_REFERENCE(1739, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 15, 0, 0x21c1 _ 0) +NAMED_CHARACTER_REFERENCE(1740, /* r i */ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 13, 0, 0x21c0 _ 0) +NAMED_CHARACTER_REFERENCE(1741, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 14, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(1742, /* r i */ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';', 16, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(1743, /* r i */ 'g' _ 'h' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 15, 0, 0x21c9 _ 0) +NAMED_CHARACTER_REFERENCE(1744, /* r i */ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 14, 0, 0x219d _ 0) +NAMED_CHARACTER_REFERENCE(1745, /* r i */ 'g' _ 'h' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 14, 0, 0x22cc _ 0) +NAMED_CHARACTER_REFERENCE(1746, /* r i */ 'n' _ 'g' _ ';', 3, 0, 0x02da _ 0) +NAMED_CHARACTER_REFERENCE(1747, /* r i */ 's' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 11, 0, 0x2253 _ 0) +NAMED_CHARACTER_REFERENCE(1748, /* r l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c4 _ 0) +NAMED_CHARACTER_REFERENCE(1749, /* r l */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cc _ 0) +NAMED_CHARACTER_REFERENCE(1750, /* r l */ 'm' _ ';', 2, 0, 0x200f _ 0) +NAMED_CHARACTER_REFERENCE(1751, /* r m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0, 0x23b1 _ 0) +NAMED_CHARACTER_REFERENCE(1752, /* r m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0, 0x23b1 _ 0) +NAMED_CHARACTER_REFERENCE(1753, /* r n */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2aee _ 0) +NAMED_CHARACTER_REFERENCE(1754, /* r o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ed _ 0) +NAMED_CHARACTER_REFERENCE(1755, /* r o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fe _ 0) +NAMED_CHARACTER_REFERENCE(1756, /* r o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e7 _ 0) +NAMED_CHARACTER_REFERENCE(1757, /* r o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2986 _ 0) +NAMED_CHARACTER_REFERENCE(1758, /* r o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd63) +NAMED_CHARACTER_REFERENCE(1759, /* r o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a2e _ 0) +NAMED_CHARACTER_REFERENCE(1760, /* r o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0, 0x2a35 _ 0) +NAMED_CHARACTER_REFERENCE(1761, /* r p */ 'a' _ 'r' _ ';', 3, 0, 0x0029 _ 0) +NAMED_CHARACTER_REFERENCE(1762, /* r p */ 'a' _ 'r' _ 'g' _ 't' _ ';', 5, 0, 0x2994 _ 0) +NAMED_CHARACTER_REFERENCE(1763, /* r p */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a12 _ 0) +NAMED_CHARACTER_REFERENCE(1764, /* r r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c9 _ 0) +NAMED_CHARACTER_REFERENCE(1765, /* r s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0, 0x203a _ 0) +NAMED_CHARACTER_REFERENCE(1766, /* r s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc7) +NAMED_CHARACTER_REFERENCE(1767, /* r s */ 'h' _ ';', 2, 0, 0x21b1 _ 0) +NAMED_CHARACTER_REFERENCE(1768, /* r s */ 'q' _ 'b' _ ';', 3, 0, 0x005d _ 0) +NAMED_CHARACTER_REFERENCE(1769, /* r s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(1770, /* r s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0, 0x2019 _ 0) +NAMED_CHARACTER_REFERENCE(1771, /* r t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0, 0x22cc _ 0) +NAMED_CHARACTER_REFERENCE(1772, /* r t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0, 0x22ca _ 0) +NAMED_CHARACTER_REFERENCE(1773, /* r t */ 'r' _ 'i' _ ';', 3, 0, 0x25b9 _ 0) +NAMED_CHARACTER_REFERENCE(1774, /* r t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(1775, /* r t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b8 _ 0) +NAMED_CHARACTER_REFERENCE(1776, /* r t */ 'r' _ 'i' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 7, 0, 0x29ce _ 0) +NAMED_CHARACTER_REFERENCE(1777, /* r u */ 'l' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0, 0x2968 _ 0) +NAMED_CHARACTER_REFERENCE(1778, /* r x */ ';', 1, 0, 0x211e _ 0) +NAMED_CHARACTER_REFERENCE(1779, /* s a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x015b _ 0) +NAMED_CHARACTER_REFERENCE(1780, /* s b */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201a _ 0) +NAMED_CHARACTER_REFERENCE(1781, /* s c */ ';', 1, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(1782, /* s c */ 'E' _ ';', 2, 0, 0x2ab4 _ 0) +NAMED_CHARACTER_REFERENCE(1783, /* s c */ 'a' _ 'p' _ ';', 3, 0, 0x2ab8 _ 0) +NAMED_CHARACTER_REFERENCE(1784, /* s c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0161 _ 0) +NAMED_CHARACTER_REFERENCE(1785, /* s c */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(1786, /* s c */ 'e' _ ';', 2, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(1787, /* s c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x015f _ 0) +NAMED_CHARACTER_REFERENCE(1788, /* s c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015d _ 0) +NAMED_CHARACTER_REFERENCE(1789, /* s c */ 'n' _ 'E' _ ';', 3, 0, 0x2ab6 _ 0) +NAMED_CHARACTER_REFERENCE(1790, /* s c */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2aba _ 0) +NAMED_CHARACTER_REFERENCE(1791, /* s c */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x22e9 _ 0) +NAMED_CHARACTER_REFERENCE(1792, /* s c */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7, 0, 0x2a13 _ 0) +NAMED_CHARACTER_REFERENCE(1793, /* s c */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(1794, /* s c */ 'y' _ ';', 2, 0, 0x0441 _ 0) +NAMED_CHARACTER_REFERENCE(1795, /* s d */ 'o' _ 't' _ ';', 3, 0, 0x22c5 _ 0) +NAMED_CHARACTER_REFERENCE(1796, /* s d */ 'o' _ 't' _ 'b' _ ';', 4, 0, 0x22a1 _ 0) +NAMED_CHARACTER_REFERENCE(1797, /* s d */ 'o' _ 't' _ 'e' _ ';', 4, 0, 0x2a66 _ 0) +NAMED_CHARACTER_REFERENCE(1798, /* s e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d8 _ 0) +NAMED_CHARACTER_REFERENCE(1799, /* s e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2925 _ 0) +NAMED_CHARACTER_REFERENCE(1800, /* s e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(1801, /* s e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2198 _ 0) +NAMED_CHARACTER_REFERENCE(1802, /* s e */ 'c' _ 't', 2, 0, 0x00a7 _ 0) +NAMED_CHARACTER_REFERENCE(1803, /* s e */ 'c' _ 't' _ ';', 3, 0, 0x00a7 _ 0) +NAMED_CHARACTER_REFERENCE(1804, /* s e */ 'm' _ 'i' _ ';', 3, 0, 0x003b _ 0) +NAMED_CHARACTER_REFERENCE(1805, /* s e */ 's' _ 'w' _ 'a' _ 'r' _ ';', 5, 0, 0x2929 _ 0) +NAMED_CHARACTER_REFERENCE(1806, /* s e */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1807, /* s e */ 't' _ 'm' _ 'n' _ ';', 4, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1808, /* s e */ 'x' _ 't' _ ';', 3, 0, 0x2736 _ 0) +NAMED_CHARACTER_REFERENCE(1809, /* s f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd30) +NAMED_CHARACTER_REFERENCE(1810, /* s f */ 'r' _ 'o' _ 'w' _ 'n' _ ';', 5, 0, 0x2322 _ 0) +NAMED_CHARACTER_REFERENCE(1811, /* s h */ 'a' _ 'r' _ 'p' _ ';', 4, 0, 0x266f _ 0) +NAMED_CHARACTER_REFERENCE(1812, /* s h */ 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0, 0x0449 _ 0) +NAMED_CHARACTER_REFERENCE(1813, /* s h */ 'c' _ 'y' _ ';', 3, 0, 0x0448 _ 0) +NAMED_CHARACTER_REFERENCE(1814, /* s h */ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 7, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1815, /* s h */ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 12, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1816, /* s h */ 'y', 1, 0, 0x00ad _ 0) +NAMED_CHARACTER_REFERENCE(1817, /* s h */ 'y' _ ';', 2, 0, 0x00ad _ 0) +NAMED_CHARACTER_REFERENCE(1818, /* s i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03c3 _ 0) +NAMED_CHARACTER_REFERENCE(1819, /* s i */ 'g' _ 'm' _ 'a' _ 'f' _ ';', 5, 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(1820, /* s i */ 'g' _ 'm' _ 'a' _ 'v' _ ';', 5, 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(1821, /* s i */ 'm' _ ';', 2, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1822, /* s i */ 'm' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2a6a _ 0) +NAMED_CHARACTER_REFERENCE(1823, /* s i */ 'm' _ 'e' _ ';', 3, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(1824, /* s i */ 'm' _ 'e' _ 'q' _ ';', 4, 0, 0x2243 _ 0) +NAMED_CHARACTER_REFERENCE(1825, /* s i */ 'm' _ 'g' _ ';', 3, 0, 0x2a9e _ 0) +NAMED_CHARACTER_REFERENCE(1826, /* s i */ 'm' _ 'g' _ 'E' _ ';', 4, 0, 0x2aa0 _ 0) +NAMED_CHARACTER_REFERENCE(1827, /* s i */ 'm' _ 'l' _ ';', 3, 0, 0x2a9d _ 0) +NAMED_CHARACTER_REFERENCE(1828, /* s i */ 'm' _ 'l' _ 'E' _ ';', 4, 0, 0x2a9f _ 0) +NAMED_CHARACTER_REFERENCE(1829, /* s i */ 'm' _ 'n' _ 'e' _ ';', 4, 0, 0x2246 _ 0) +NAMED_CHARACTER_REFERENCE(1830, /* s i */ 'm' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2a24 _ 0) +NAMED_CHARACTER_REFERENCE(1831, /* s i */ 'm' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x2972 _ 0) +NAMED_CHARACTER_REFERENCE(1832, /* s l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2190 _ 0) +NAMED_CHARACTER_REFERENCE(1833, /* s m */ 'a' _ 'l' _ 'l' _ 's' _ 'e' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 12, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1834, /* s m */ 'a' _ 's' _ 'h' _ 'p' _ ';', 5, 0, 0x2a33 _ 0) +NAMED_CHARACTER_REFERENCE(1835, /* s m */ 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7, 0, 0x29e4 _ 0) +NAMED_CHARACTER_REFERENCE(1836, /* s m */ 'i' _ 'd' _ ';', 3, 0, 0x2223 _ 0) +NAMED_CHARACTER_REFERENCE(1837, /* s m */ 'i' _ 'l' _ 'e' _ ';', 4, 0, 0x2323 _ 0) +NAMED_CHARACTER_REFERENCE(1838, /* s m */ 't' _ ';', 2, 0, 0x2aaa _ 0) +NAMED_CHARACTER_REFERENCE(1839, /* s m */ 't' _ 'e' _ ';', 3, 0, 0x2aac _ 0) +NAMED_CHARACTER_REFERENCE(1840, /* s o */ 'f' _ 't' _ 'c' _ 'y' _ ';', 5, 0, 0x044c _ 0) +NAMED_CHARACTER_REFERENCE(1841, /* s o */ 'l' _ ';', 2, 0, 0x002f _ 0) +NAMED_CHARACTER_REFERENCE(1842, /* s o */ 'l' _ 'b' _ ';', 3, 0, 0x29c4 _ 0) +NAMED_CHARACTER_REFERENCE(1843, /* s o */ 'l' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x233f _ 0) +NAMED_CHARACTER_REFERENCE(1844, /* s o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd64) +NAMED_CHARACTER_REFERENCE(1845, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ ';', 5, 0, 0x2660 _ 0) +NAMED_CHARACTER_REFERENCE(1846, /* s p */ 'a' _ 'd' _ 'e' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2660 _ 0) +NAMED_CHARACTER_REFERENCE(1847, /* s p */ 'a' _ 'r' _ ';', 3, 0, 0x2225 _ 0) +NAMED_CHARACTER_REFERENCE(1848, /* s q */ 'c' _ 'a' _ 'p' _ ';', 4, 0, 0x2293 _ 0) +NAMED_CHARACTER_REFERENCE(1849, /* s q */ 'c' _ 'u' _ 'p' _ ';', 4, 0, 0x2294 _ 0) +NAMED_CHARACTER_REFERENCE(1850, /* s q */ 's' _ 'u' _ 'b' _ ';', 4, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(1851, /* s q */ 's' _ 'u' _ 'b' _ 'e' _ ';', 5, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(1852, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x228f _ 0) +NAMED_CHARACTER_REFERENCE(1853, /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0, 0x2291 _ 0) +NAMED_CHARACTER_REFERENCE(1854, /* s q */ 's' _ 'u' _ 'p' _ ';', 4, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(1855, /* s q */ 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(1856, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7, 0, 0x2290 _ 0) +NAMED_CHARACTER_REFERENCE(1857, /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0, 0x2292 _ 0) +NAMED_CHARACTER_REFERENCE(1858, /* s q */ 'u' _ ';', 2, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(1859, /* s q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0, 0x25a1 _ 0) +NAMED_CHARACTER_REFERENCE(1860, /* s q */ 'u' _ 'a' _ 'r' _ 'f' _ ';', 5, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(1861, /* s q */ 'u' _ 'f' _ ';', 3, 0, 0x25aa _ 0) +NAMED_CHARACTER_REFERENCE(1862, /* s r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2192 _ 0) +NAMED_CHARACTER_REFERENCE(1863, /* s s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc8) +NAMED_CHARACTER_REFERENCE(1864, /* s s */ 'e' _ 't' _ 'm' _ 'n' _ ';', 5, 0, 0x2216 _ 0) +NAMED_CHARACTER_REFERENCE(1865, /* s s */ 'm' _ 'i' _ 'l' _ 'e' _ ';', 5, 0, 0x2323 _ 0) +NAMED_CHARACTER_REFERENCE(1866, /* s s */ 't' _ 'a' _ 'r' _ 'f' _ ';', 5, 0, 0x22c6 _ 0) +NAMED_CHARACTER_REFERENCE(1867, /* s t */ 'a' _ 'r' _ ';', 3, 0, 0x2606 _ 0) +NAMED_CHARACTER_REFERENCE(1868, /* s t */ 'a' _ 'r' _ 'f' _ ';', 4, 0, 0x2605 _ 0) +NAMED_CHARACTER_REFERENCE(1869, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 14, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(1870, /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'p' _ 'h' _ 'i' _ ';', 10, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(1871, /* s t */ 'r' _ 'n' _ 's' _ ';', 4, 0, 0x00af _ 0) +NAMED_CHARACTER_REFERENCE(1872, /* s u */ 'b' _ ';', 2, 0, 0x2282 _ 0) +NAMED_CHARACTER_REFERENCE(1873, /* s u */ 'b' _ 'E' _ ';', 3, 0, 0x2ac5 _ 0) +NAMED_CHARACTER_REFERENCE(1874, /* s u */ 'b' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2abd _ 0) +NAMED_CHARACTER_REFERENCE(1875, /* s u */ 'b' _ 'e' _ ';', 3, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(1876, /* s u */ 'b' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2ac3 _ 0) +NAMED_CHARACTER_REFERENCE(1877, /* s u */ 'b' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0, 0x2ac1 _ 0) +NAMED_CHARACTER_REFERENCE(1878, /* s u */ 'b' _ 'n' _ 'E' _ ';', 4, 0, 0x2acb _ 0) +NAMED_CHARACTER_REFERENCE(1879, /* s u */ 'b' _ 'n' _ 'e' _ ';', 4, 0, 0x228a _ 0) +NAMED_CHARACTER_REFERENCE(1880, /* s u */ 'b' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2abf _ 0) +NAMED_CHARACTER_REFERENCE(1881, /* s u */ 'b' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x2979 _ 0) +NAMED_CHARACTER_REFERENCE(1882, /* s u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x2282 _ 0) +NAMED_CHARACTER_REFERENCE(1883, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0, 0x2286 _ 0) +NAMED_CHARACTER_REFERENCE(1884, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac5 _ 0) +NAMED_CHARACTER_REFERENCE(1885, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228a _ 0) +NAMED_CHARACTER_REFERENCE(1886, /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, 0x2acb _ 0) +NAMED_CHARACTER_REFERENCE(1887, /* s u */ 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2ac7 _ 0) +NAMED_CHARACTER_REFERENCE(1888, /* s u */ 'b' _ 's' _ 'u' _ 'b' _ ';', 5, 0, 0x2ad5 _ 0) +NAMED_CHARACTER_REFERENCE(1889, /* s u */ 'b' _ 's' _ 'u' _ 'p' _ ';', 5, 0, 0x2ad3 _ 0) +NAMED_CHARACTER_REFERENCE(1890, /* s u */ 'c' _ 'c' _ ';', 3, 0, 0x227b _ 0) +NAMED_CHARACTER_REFERENCE(1891, /* s u */ 'c' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0, 0x2ab8 _ 0) +NAMED_CHARACTER_REFERENCE(1892, /* s u */ 'c' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0, 0x227d _ 0) +NAMED_CHARACTER_REFERENCE(1893, /* s u */ 'c' _ 'c' _ 'e' _ 'q' _ ';', 5, 0, 0x2ab0 _ 0) +NAMED_CHARACTER_REFERENCE(1894, /* s u */ 'c' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, 0x2aba _ 0) +NAMED_CHARACTER_REFERENCE(1895, /* s u */ 'c' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7, 0, 0x2ab6 _ 0) +NAMED_CHARACTER_REFERENCE(1896, /* s u */ 'c' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7, 0, 0x22e9 _ 0) +NAMED_CHARACTER_REFERENCE(1897, /* s u */ 'c' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0, 0x227f _ 0) +NAMED_CHARACTER_REFERENCE(1898, /* s u */ 'm' _ ';', 2, 0, 0x2211 _ 0) +NAMED_CHARACTER_REFERENCE(1899, /* s u */ 'n' _ 'g' _ ';', 3, 0, 0x266a _ 0) +NAMED_CHARACTER_REFERENCE(1900, /* s u */ 'p' _ '1', 2, 0, 0x00b9 _ 0) +NAMED_CHARACTER_REFERENCE(1901, /* s u */ 'p' _ '1' _ ';', 3, 0, 0x00b9 _ 0) +NAMED_CHARACTER_REFERENCE(1902, /* s u */ 'p' _ '2', 2, 0, 0x00b2 _ 0) +NAMED_CHARACTER_REFERENCE(1903, /* s u */ 'p' _ '2' _ ';', 3, 0, 0x00b2 _ 0) +NAMED_CHARACTER_REFERENCE(1904, /* s u */ 'p' _ '3', 2, 0, 0x00b3 _ 0) +NAMED_CHARACTER_REFERENCE(1905, /* s u */ 'p' _ '3' _ ';', 3, 0, 0x00b3 _ 0) +NAMED_CHARACTER_REFERENCE(1906, /* s u */ 'p' _ ';', 2, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(1907, /* s u */ 'p' _ 'E' _ ';', 3, 0, 0x2ac6 _ 0) +NAMED_CHARACTER_REFERENCE(1908, /* s u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x2abe _ 0) +NAMED_CHARACTER_REFERENCE(1909, /* s u */ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 6, 0, 0x2ad8 _ 0) +NAMED_CHARACTER_REFERENCE(1910, /* s u */ 'p' _ 'e' _ ';', 3, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(1911, /* s u */ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0, 0x2ac4 _ 0) +NAMED_CHARACTER_REFERENCE(1912, /* s u */ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 6, 0, 0x27c9 _ 0) +NAMED_CHARACTER_REFERENCE(1913, /* s u */ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 6, 0, 0x2ad7 _ 0) +NAMED_CHARACTER_REFERENCE(1914, /* s u */ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x297b _ 0) +NAMED_CHARACTER_REFERENCE(1915, /* s u */ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0, 0x2ac2 _ 0) +NAMED_CHARACTER_REFERENCE(1916, /* s u */ 'p' _ 'n' _ 'E' _ ';', 4, 0, 0x2acc _ 0) +NAMED_CHARACTER_REFERENCE(1917, /* s u */ 'p' _ 'n' _ 'e' _ ';', 4, 0, 0x228b _ 0) +NAMED_CHARACTER_REFERENCE(1918, /* s u */ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2ac0 _ 0) +NAMED_CHARACTER_REFERENCE(1919, /* s u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0, 0x2283 _ 0) +NAMED_CHARACTER_REFERENCE(1920, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7, 0, 0x2287 _ 0) +NAMED_CHARACTER_REFERENCE(1921, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac6 _ 0) +NAMED_CHARACTER_REFERENCE(1922, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228b _ 0) +NAMED_CHARACTER_REFERENCE(1923, /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0, 0x2acc _ 0) +NAMED_CHARACTER_REFERENCE(1924, /* s u */ 'p' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x2ac8 _ 0) +NAMED_CHARACTER_REFERENCE(1925, /* s u */ 'p' _ 's' _ 'u' _ 'b' _ ';', 5, 0, 0x2ad4 _ 0) +NAMED_CHARACTER_REFERENCE(1926, /* s u */ 'p' _ 's' _ 'u' _ 'p' _ ';', 5, 0, 0x2ad6 _ 0) +NAMED_CHARACTER_REFERENCE(1927, /* s w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d9 _ 0) +NAMED_CHARACTER_REFERENCE(1928, /* s w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0, 0x2926 _ 0) +NAMED_CHARACTER_REFERENCE(1929, /* s w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(1930, /* s w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2199 _ 0) +NAMED_CHARACTER_REFERENCE(1931, /* s w */ 'n' _ 'w' _ 'a' _ 'r' _ ';', 5, 0, 0x292a _ 0) +NAMED_CHARACTER_REFERENCE(1932, /* s z */ 'l' _ 'i' _ 'g', 3, 0, 0x00df _ 0) +NAMED_CHARACTER_REFERENCE(1933, /* s z */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00df _ 0) +NAMED_CHARACTER_REFERENCE(1934, /* t a */ 'r' _ 'g' _ 'e' _ 't' _ ';', 5, 0, 0x2316 _ 0) +NAMED_CHARACTER_REFERENCE(1935, /* t a */ 'u' _ ';', 2, 0, 0x03c4 _ 0) +NAMED_CHARACTER_REFERENCE(1936, /* t b */ 'r' _ 'k' _ ';', 3, 0, 0x23b4 _ 0) +NAMED_CHARACTER_REFERENCE(1937, /* t c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x0165 _ 0) +NAMED_CHARACTER_REFERENCE(1938, /* t c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0, 0x0163 _ 0) +NAMED_CHARACTER_REFERENCE(1939, /* t c */ 'y' _ ';', 2, 0, 0x0442 _ 0) +NAMED_CHARACTER_REFERENCE(1940, /* t d */ 'o' _ 't' _ ';', 3, 0, 0x20db _ 0) +NAMED_CHARACTER_REFERENCE(1941, /* t e */ 'l' _ 'r' _ 'e' _ 'c' _ ';', 5, 0, 0x2315 _ 0) +NAMED_CHARACTER_REFERENCE(1942, /* t f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd31) +NAMED_CHARACTER_REFERENCE(1943, /* t h */ 'e' _ 'r' _ 'e' _ '4' _ ';', 5, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(1944, /* t h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0) +NAMED_CHARACTER_REFERENCE(1945, /* t h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x03b8 _ 0) +NAMED_CHARACTER_REFERENCE(1946, /* t h */ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 7, 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(1947, /* t h */ 'e' _ 't' _ 'a' _ 'v' _ ';', 5, 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(1948, /* t h */ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(1949, /* t h */ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1950, /* t h */ 'i' _ 'n' _ 's' _ 'p' _ ';', 5, 0, 0x2009 _ 0) +NAMED_CHARACTER_REFERENCE(1951, /* t h */ 'k' _ 'a' _ 'p' _ ';', 4, 0, 0x2248 _ 0) +NAMED_CHARACTER_REFERENCE(1952, /* t h */ 'k' _ 's' _ 'i' _ 'm' _ ';', 5, 0, 0x223c _ 0) +NAMED_CHARACTER_REFERENCE(1953, /* t h */ 'o' _ 'r' _ 'n', 3, 0, 0x00fe _ 0) +NAMED_CHARACTER_REFERENCE(1954, /* t h */ 'o' _ 'r' _ 'n' _ ';', 4, 0, 0x00fe _ 0) +NAMED_CHARACTER_REFERENCE(1955, /* t i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x02dc _ 0) +NAMED_CHARACTER_REFERENCE(1956, /* t i */ 'm' _ 'e' _ 's', 3, 0, 0x00d7 _ 0) +NAMED_CHARACTER_REFERENCE(1957, /* t i */ 'm' _ 'e' _ 's' _ ';', 4, 0, 0x00d7 _ 0) +NAMED_CHARACTER_REFERENCE(1958, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ ';', 5, 0, 0x22a0 _ 0) +NAMED_CHARACTER_REFERENCE(1959, /* t i */ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 7, 0, 0x2a31 _ 0) +NAMED_CHARACTER_REFERENCE(1960, /* t i */ 'm' _ 'e' _ 's' _ 'd' _ ';', 5, 0, 0x2a30 _ 0) +NAMED_CHARACTER_REFERENCE(1961, /* t i */ 'n' _ 't' _ ';', 3, 0, 0x222d _ 0) +NAMED_CHARACTER_REFERENCE(1962, /* t o */ 'e' _ 'a' _ ';', 3, 0, 0x2928 _ 0) +NAMED_CHARACTER_REFERENCE(1963, /* t o */ 'p' _ ';', 2, 0, 0x22a4 _ 0) +NAMED_CHARACTER_REFERENCE(1964, /* t o */ 'p' _ 'b' _ 'o' _ 't' _ ';', 5, 0, 0x2336 _ 0) +NAMED_CHARACTER_REFERENCE(1965, /* t o */ 'p' _ 'c' _ 'i' _ 'r' _ ';', 5, 0, 0x2af1 _ 0) +NAMED_CHARACTER_REFERENCE(1966, /* t o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd65) +NAMED_CHARACTER_REFERENCE(1967, /* t o */ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 6, 0, 0x2ada _ 0) +NAMED_CHARACTER_REFERENCE(1968, /* t o */ 's' _ 'a' _ ';', 3, 0, 0x2929 _ 0) +NAMED_CHARACTER_REFERENCE(1969, /* t p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2034 _ 0) +NAMED_CHARACTER_REFERENCE(1970, /* t r */ 'a' _ 'd' _ 'e' _ ';', 4, 0, 0x2122 _ 0) +NAMED_CHARACTER_REFERENCE(1971, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7, 0, 0x25b5 _ 0) +NAMED_CHARACTER_REFERENCE(1972, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 11, 0, 0x25bf _ 0) +NAMED_CHARACTER_REFERENCE(1973, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 11, 0, 0x25c3 _ 0) +NAMED_CHARACTER_REFERENCE(1974, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';', 13, 0, 0x22b4 _ 0) +NAMED_CHARACTER_REFERENCE(1975, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 8, 0, 0x225c _ 0) +NAMED_CHARACTER_REFERENCE(1976, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 12, 0, 0x25b9 _ 0) +NAMED_CHARACTER_REFERENCE(1977, /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';', 14, 0, 0x22b5 _ 0) +NAMED_CHARACTER_REFERENCE(1978, /* t r */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0, 0x25ec _ 0) +NAMED_CHARACTER_REFERENCE(1979, /* t r */ 'i' _ 'e' _ ';', 3, 0, 0x225c _ 0) +NAMED_CHARACTER_REFERENCE(1980, /* t r */ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7, 0, 0x2a3a _ 0) +NAMED_CHARACTER_REFERENCE(1981, /* t r */ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0, 0x2a39 _ 0) +NAMED_CHARACTER_REFERENCE(1982, /* t r */ 'i' _ 's' _ 'b' _ ';', 4, 0, 0x29cd _ 0) +NAMED_CHARACTER_REFERENCE(1983, /* t r */ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 6, 0, 0x2a3b _ 0) +NAMED_CHARACTER_REFERENCE(1984, /* t r */ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 7, 0, 0x23e2 _ 0) +NAMED_CHARACTER_REFERENCE(1985, /* t s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc9) +NAMED_CHARACTER_REFERENCE(1986, /* t s */ 'c' _ 'y' _ ';', 3, 0, 0x0446 _ 0) +NAMED_CHARACTER_REFERENCE(1987, /* t s */ 'h' _ 'c' _ 'y' _ ';', 4, 0, 0x045b _ 0) +NAMED_CHARACTER_REFERENCE(1988, /* t s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0, 0x0167 _ 0) +NAMED_CHARACTER_REFERENCE(1989, /* t w */ 'i' _ 'x' _ 't' _ ';', 4, 0, 0x226c _ 0) +NAMED_CHARACTER_REFERENCE(1990, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 15, 0, 0x219e _ 0) +NAMED_CHARACTER_REFERENCE(1991, /* t w */ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 16, 0, 0x21a0 _ 0) +NAMED_CHARACTER_REFERENCE(1992, /* u A */ 'r' _ 'r' _ ';', 3, 0, 0x21d1 _ 0) +NAMED_CHARACTER_REFERENCE(1993, /* u H */ 'a' _ 'r' _ ';', 3, 0, 0x2963 _ 0) +NAMED_CHARACTER_REFERENCE(1994, /* u a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fa _ 0) +NAMED_CHARACTER_REFERENCE(1995, /* u a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00fa _ 0) +NAMED_CHARACTER_REFERENCE(1996, /* u a */ 'r' _ 'r' _ ';', 3, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(1997, /* u b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x045e _ 0) +NAMED_CHARACTER_REFERENCE(1998, /* u b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0, 0x016d _ 0) +NAMED_CHARACTER_REFERENCE(1999, /* u c */ 'i' _ 'r' _ 'c', 3, 0, 0x00fb _ 0) +NAMED_CHARACTER_REFERENCE(2000, /* u c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00fb _ 0) +NAMED_CHARACTER_REFERENCE(2001, /* u c */ 'y' _ ';', 2, 0, 0x0443 _ 0) +NAMED_CHARACTER_REFERENCE(2002, /* u d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c5 _ 0) +NAMED_CHARACTER_REFERENCE(2003, /* u d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0, 0x0171 _ 0) +NAMED_CHARACTER_REFERENCE(2004, /* u d */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296e _ 0) +NAMED_CHARACTER_REFERENCE(2005, /* u f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0, 0x297e _ 0) +NAMED_CHARACTER_REFERENCE(2006, /* u f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd32) +NAMED_CHARACTER_REFERENCE(2007, /* u g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f9 _ 0) +NAMED_CHARACTER_REFERENCE(2008, /* u g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0, 0x00f9 _ 0) +NAMED_CHARACTER_REFERENCE(2009, /* u h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(2010, /* u h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(2011, /* u h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2580 _ 0) +NAMED_CHARACTER_REFERENCE(2012, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231c _ 0) +NAMED_CHARACTER_REFERENCE(2013, /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231c _ 0) +NAMED_CHARACTER_REFERENCE(2014, /* u l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230f _ 0) +NAMED_CHARACTER_REFERENCE(2015, /* u l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f8 _ 0) +NAMED_CHARACTER_REFERENCE(2016, /* u m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016b _ 0) +NAMED_CHARACTER_REFERENCE(2017, /* u m */ 'l', 1, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(2018, /* u m */ 'l' _ ';', 2, 0, 0x00a8 _ 0) +NAMED_CHARACTER_REFERENCE(2019, /* u o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0173 _ 0) +NAMED_CHARACTER_REFERENCE(2020, /* u o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd66) +NAMED_CHARACTER_REFERENCE(2021, /* u p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0, 0x2191 _ 0) +NAMED_CHARACTER_REFERENCE(2022, /* u p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(2023, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12, 0, 0x21bf _ 0) +NAMED_CHARACTER_REFERENCE(2024, /* u p */ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 13, 0, 0x21be _ 0) +NAMED_CHARACTER_REFERENCE(2025, /* u p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x228e _ 0) +NAMED_CHARACTER_REFERENCE(2026, /* u p */ 's' _ 'i' _ ';', 3, 0, 0x03c5 _ 0) +NAMED_CHARACTER_REFERENCE(2027, /* u p */ 's' _ 'i' _ 'h' _ ';', 4, 0, 0x03d2 _ 0) +NAMED_CHARACTER_REFERENCE(2028, /* u p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0, 0x03c5 _ 0) +NAMED_CHARACTER_REFERENCE(2029, /* u p */ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 9, 0, 0x21c8 _ 0) +NAMED_CHARACTER_REFERENCE(2030, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0, 0x231d _ 0) +NAMED_CHARACTER_REFERENCE(2031, /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7, 0, 0x231d _ 0) +NAMED_CHARACTER_REFERENCE(2032, /* u r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0, 0x230e _ 0) +NAMED_CHARACTER_REFERENCE(2033, /* u r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016f _ 0) +NAMED_CHARACTER_REFERENCE(2034, /* u r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f9 _ 0) +NAMED_CHARACTER_REFERENCE(2035, /* u s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcca) +NAMED_CHARACTER_REFERENCE(2036, /* u t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f0 _ 0) +NAMED_CHARACTER_REFERENCE(2037, /* u t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0, 0x0169 _ 0) +NAMED_CHARACTER_REFERENCE(2038, /* u t */ 'r' _ 'i' _ ';', 3, 0, 0x25b5 _ 0) +NAMED_CHARACTER_REFERENCE(2039, /* u t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b4 _ 0) +NAMED_CHARACTER_REFERENCE(2040, /* u u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c8 _ 0) +NAMED_CHARACTER_REFERENCE(2041, /* u u */ 'm' _ 'l', 2, 0, 0x00fc _ 0) +NAMED_CHARACTER_REFERENCE(2042, /* u u */ 'm' _ 'l' _ ';', 3, 0, 0x00fc _ 0) +NAMED_CHARACTER_REFERENCE(2043, /* u w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0, 0x29a7 _ 0) +NAMED_CHARACTER_REFERENCE(2044, /* v A */ 'r' _ 'r' _ ';', 3, 0, 0x21d5 _ 0) +NAMED_CHARACTER_REFERENCE(2045, /* v B */ 'a' _ 'r' _ ';', 3, 0, 0x2ae8 _ 0) +NAMED_CHARACTER_REFERENCE(2046, /* v B */ 'a' _ 'r' _ 'v' _ ';', 4, 0, 0x2ae9 _ 0) +NAMED_CHARACTER_REFERENCE(2047, /* v D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a8 _ 0) +NAMED_CHARACTER_REFERENCE(2048, /* v a */ 'n' _ 'g' _ 'r' _ 't' _ ';', 5, 0, 0x299c _ 0) +NAMED_CHARACTER_REFERENCE(2049, /* v a */ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 9, 0, 0x03f5 _ 0) +NAMED_CHARACTER_REFERENCE(2050, /* v a */ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 7, 0, 0x03f0 _ 0) +NAMED_CHARACTER_REFERENCE(2051, /* v a */ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 9, 0, 0x2205 _ 0) +NAMED_CHARACTER_REFERENCE(2052, /* v a */ 'r' _ 'p' _ 'h' _ 'i' _ ';', 5, 0, 0x03d5 _ 0) +NAMED_CHARACTER_REFERENCE(2053, /* v a */ 'r' _ 'p' _ 'i' _ ';', 4, 0, 0x03d6 _ 0) +NAMED_CHARACTER_REFERENCE(2054, /* v a */ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 8, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(2055, /* v a */ 'r' _ 'r' _ ';', 3, 0, 0x2195 _ 0) +NAMED_CHARACTER_REFERENCE(2056, /* v a */ 'r' _ 'r' _ 'h' _ 'o' _ ';', 5, 0, 0x03f1 _ 0) +NAMED_CHARACTER_REFERENCE(2057, /* v a */ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 7, 0, 0x03c2 _ 0) +NAMED_CHARACTER_REFERENCE(2058, /* v a */ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 7, 0, 0x03d1 _ 0) +NAMED_CHARACTER_REFERENCE(2059, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 14, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(2060, /* v a */ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 15, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(2061, /* v c */ 'y' _ ';', 2, 0, 0x0432 _ 0) +NAMED_CHARACTER_REFERENCE(2062, /* v d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a2 _ 0) +NAMED_CHARACTER_REFERENCE(2063, /* v e */ 'e' _ ';', 2, 0, 0x2228 _ 0) +NAMED_CHARACTER_REFERENCE(2064, /* v e */ 'e' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x22bb _ 0) +NAMED_CHARACTER_REFERENCE(2065, /* v e */ 'e' _ 'e' _ 'q' _ ';', 4, 0, 0x225a _ 0) +NAMED_CHARACTER_REFERENCE(2066, /* v e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0, 0x22ee _ 0) +NAMED_CHARACTER_REFERENCE(2067, /* v e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(2068, /* v e */ 'r' _ 't' _ ';', 3, 0, 0x007c _ 0) +NAMED_CHARACTER_REFERENCE(2069, /* v f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd33) +NAMED_CHARACTER_REFERENCE(2070, /* v l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b2 _ 0) +NAMED_CHARACTER_REFERENCE(2071, /* v o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd67) +NAMED_CHARACTER_REFERENCE(2072, /* v p */ 'r' _ 'o' _ 'p' _ ';', 4, 0, 0x221d _ 0) +NAMED_CHARACTER_REFERENCE(2073, /* v r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b3 _ 0) +NAMED_CHARACTER_REFERENCE(2074, /* v s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccb) +NAMED_CHARACTER_REFERENCE(2075, /* v z */ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 6, 0, 0x299a _ 0) +NAMED_CHARACTER_REFERENCE(2076, /* w c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0175 _ 0) +NAMED_CHARACTER_REFERENCE(2077, /* w e */ 'd' _ 'b' _ 'a' _ 'r' _ ';', 5, 0, 0x2a5f _ 0) +NAMED_CHARACTER_REFERENCE(2078, /* w e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x2227 _ 0) +NAMED_CHARACTER_REFERENCE(2079, /* w e */ 'd' _ 'g' _ 'e' _ 'q' _ ';', 5, 0, 0x2259 _ 0) +NAMED_CHARACTER_REFERENCE(2080, /* w e */ 'i' _ 'e' _ 'r' _ 'p' _ ';', 5, 0, 0x2118 _ 0) +NAMED_CHARACTER_REFERENCE(2081, /* w f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd34) +NAMED_CHARACTER_REFERENCE(2082, /* w o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd68) +NAMED_CHARACTER_REFERENCE(2083, /* w p */ ';', 1, 0, 0x2118 _ 0) +NAMED_CHARACTER_REFERENCE(2084, /* w r */ ';', 1, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(2085, /* w r */ 'e' _ 'a' _ 't' _ 'h' _ ';', 5, 0, 0x2240 _ 0) +NAMED_CHARACTER_REFERENCE(2086, /* w s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccc) +NAMED_CHARACTER_REFERENCE(2087, /* x c */ 'a' _ 'p' _ ';', 3, 0, 0x22c2 _ 0) +NAMED_CHARACTER_REFERENCE(2088, /* x c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x25ef _ 0) +NAMED_CHARACTER_REFERENCE(2089, /* x c */ 'u' _ 'p' _ ';', 3, 0, 0x22c3 _ 0) +NAMED_CHARACTER_REFERENCE(2090, /* x d */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25bd _ 0) +NAMED_CHARACTER_REFERENCE(2091, /* x f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd35) +NAMED_CHARACTER_REFERENCE(2092, /* x h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27fa _ 0) +NAMED_CHARACTER_REFERENCE(2093, /* x h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f7 _ 0) +NAMED_CHARACTER_REFERENCE(2094, /* x i */ ';', 1, 0, 0x03be _ 0) +NAMED_CHARACTER_REFERENCE(2095, /* x l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f8 _ 0) +NAMED_CHARACTER_REFERENCE(2096, /* x l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f5 _ 0) +NAMED_CHARACTER_REFERENCE(2097, /* x m */ 'a' _ 'p' _ ';', 3, 0, 0x27fc _ 0) +NAMED_CHARACTER_REFERENCE(2098, /* x n */ 'i' _ 's' _ ';', 3, 0, 0x22fb _ 0) +NAMED_CHARACTER_REFERENCE(2099, /* x o */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2a00 _ 0) +NAMED_CHARACTER_REFERENCE(2100, /* x o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd69) +NAMED_CHARACTER_REFERENCE(2101, /* x o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a01 _ 0) +NAMED_CHARACTER_REFERENCE(2102, /* x o */ 't' _ 'i' _ 'm' _ 'e' _ ';', 5, 0, 0x2a02 _ 0) +NAMED_CHARACTER_REFERENCE(2103, /* x r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f9 _ 0) +NAMED_CHARACTER_REFERENCE(2104, /* x r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f6 _ 0) +NAMED_CHARACTER_REFERENCE(2105, /* x s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccd) +NAMED_CHARACTER_REFERENCE(2106, /* x s */ 'q' _ 'c' _ 'u' _ 'p' _ ';', 5, 0, 0x2a06 _ 0) +NAMED_CHARACTER_REFERENCE(2107, /* x u */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0, 0x2a04 _ 0) +NAMED_CHARACTER_REFERENCE(2108, /* x u */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25b3 _ 0) +NAMED_CHARACTER_REFERENCE(2109, /* x v */ 'e' _ 'e' _ ';', 3, 0, 0x22c1 _ 0) +NAMED_CHARACTER_REFERENCE(2110, /* x w */ 'e' _ 'd' _ 'g' _ 'e' _ ';', 5, 0, 0x22c0 _ 0) +NAMED_CHARACTER_REFERENCE(2111, /* y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fd _ 0) +NAMED_CHARACTER_REFERENCE(2112, /* y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x00fd _ 0) +NAMED_CHARACTER_REFERENCE(2113, /* y a */ 'c' _ 'y' _ ';', 3, 0, 0x044f _ 0) +NAMED_CHARACTER_REFERENCE(2114, /* y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0177 _ 0) +NAMED_CHARACTER_REFERENCE(2115, /* y c */ 'y' _ ';', 2, 0, 0x044b _ 0) +NAMED_CHARACTER_REFERENCE(2116, /* y e */ 'n', 1, 0, 0x00a5 _ 0) +NAMED_CHARACTER_REFERENCE(2117, /* y e */ 'n' _ ';', 2, 0, 0x00a5 _ 0) +NAMED_CHARACTER_REFERENCE(2118, /* y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd36) +NAMED_CHARACTER_REFERENCE(2119, /* y i */ 'c' _ 'y' _ ';', 3, 0, 0x0457 _ 0) +NAMED_CHARACTER_REFERENCE(2120, /* y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6a) +NAMED_CHARACTER_REFERENCE(2121, /* y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcce) +NAMED_CHARACTER_REFERENCE(2122, /* y u */ 'c' _ 'y' _ ';', 3, 0, 0x044e _ 0) +NAMED_CHARACTER_REFERENCE(2123, /* y u */ 'm' _ 'l', 2, 0, 0x00ff _ 0) +NAMED_CHARACTER_REFERENCE(2124, /* y u */ 'm' _ 'l' _ ';', 3, 0, 0x00ff _ 0) +NAMED_CHARACTER_REFERENCE(2125, /* z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0, 0x017a _ 0) +NAMED_CHARACTER_REFERENCE(2126, /* z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0, 0x017e _ 0) +NAMED_CHARACTER_REFERENCE(2127, /* z c */ 'y' _ ';', 2, 0, 0x0437 _ 0) +NAMED_CHARACTER_REFERENCE(2128, /* z d */ 'o' _ 't' _ ';', 3, 0, 0x017c _ 0) +NAMED_CHARACTER_REFERENCE(2129, /* z e */ 'e' _ 't' _ 'r' _ 'f' _ ';', 5, 0, 0x2128 _ 0) +NAMED_CHARACTER_REFERENCE(2130, /* z e */ 't' _ 'a' _ ';', 3, 0, 0x03b6 _ 0) +NAMED_CHARACTER_REFERENCE(2131, /* z f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd37) +NAMED_CHARACTER_REFERENCE(2132, /* z h */ 'c' _ 'y' _ ';', 3, 0, 0x0436 _ 0) +NAMED_CHARACTER_REFERENCE(2133, /* z i */ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0, 0x21dd _ 0) +NAMED_CHARACTER_REFERENCE(2134, /* z o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6b) +NAMED_CHARACTER_REFERENCE(2135, /* z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccf) +NAMED_CHARACTER_REFERENCE(2136, /* z w */ 'j' _ ';', 2, 0, 0x200d _ 0) +NAMED_CHARACTER_REFERENCE(2137, /* z w */ 'n' _ 'j' _ ';', 3, 0, 0x200c _ 0) #undef _ From db76afec5f40b1265d46bd2a3e5cf5d4396f5e5c Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Thu, 1 Apr 2010 13:28:25 +0200 Subject: [PATCH 14/69] Bug 555519 - disable test_doSetAndLoadFaviconForPage_failures.js since it randomly succeeds --- .../tests/unit/test_doSetAndLoadFaviconForPage_failures.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js index 0d3d5bacf60e..9f2866c81879 100644 --- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js +++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js @@ -178,6 +178,12 @@ let historyObserver = { let currentTest = null; function run_test() { + // Disabled till LAZY_ADD is killed, this test should be fixed, since the + // below timeout is clearly wrong due to 3s lazy timer. But fixing it right + // now would mean making it take about 12s to run. This is not acceptable. + // See bug 555519. + return; + do_test_pending(); // check that the favicon loaded correctly From e09dc8f272ebc7f307119597205a09ff53e31c7b Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Thu, 1 Apr 2010 13:29:09 +0200 Subject: [PATCH 15/69] Bug 527735 - nsITaskbarPreviewButton.visible always returns the wrong value. r=robarnold --- widget/src/windows/TaskbarPreviewButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/src/windows/TaskbarPreviewButton.cpp b/widget/src/windows/TaskbarPreviewButton.cpp index d50a55b5146d..645d1348a735 100644 --- a/widget/src/windows/TaskbarPreviewButton.cpp +++ b/widget/src/windows/TaskbarPreviewButton.cpp @@ -150,7 +150,7 @@ TaskbarPreviewButton::SetImage(imgIContainer *img) { NS_IMETHODIMP TaskbarPreviewButton::GetVisible(PRBool *visible) { - *visible = (Button().dwFlags & THBF_HIDDEN) == THBF_HIDDEN; + *visible = (Button().dwFlags & THBF_HIDDEN) != THBF_HIDDEN; return NS_OK; } From 75db30109edd9c696fd8477aeb9235f47dad4b65 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Thu, 1 Apr 2010 13:29:13 +0200 Subject: [PATCH 16/69] Bug 556231 - Tests are trying to QI to nsIDirectoryProvider, that does not exist. r=ted --- docshell/test/unit/head_docshell.js | 2 +- modules/plugin/test/unit/test_bug471245.js | 2 +- testing/xpcshell/head.js | 2 +- toolkit/components/downloads/test/unit/head_download_manager.js | 2 +- .../tests/unit/test_privatebrowsing_downloadLastDir_c.js | 2 +- .../tests/unit/test_privatebrowsing_downloadLastDir.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docshell/test/unit/head_docshell.js b/docshell/test/unit/head_docshell.js index f893629eb946..cd3c0dc59862 100644 --- a/docshell/test/unit/head_docshell.js +++ b/docshell/test/unit/head_docshell.js @@ -67,7 +67,7 @@ var provider = { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/modules/plugin/test/unit/test_bug471245.js b/modules/plugin/test/unit/test_bug471245.js index d25099a742a7..9f22f658665a 100644 --- a/modules/plugin/test/unit/test_bug471245.js +++ b/modules/plugin/test/unit/test_bug471245.js @@ -60,7 +60,7 @@ function do_get_profile_startup() { throw Components.results.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIDirectoryProvider) || + if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) || iid.equals(Components.interfaces.nsISupports)) { return this; } diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index 4dcfbb855cac..e9a474616145 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -452,7 +452,7 @@ function do_get_profile() { throw Components.results.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIDirectoryProvider) || + if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) || iid.equals(Components.interfaces.nsISupports)) { return this; } diff --git a/toolkit/components/downloads/test/unit/head_download_manager.js b/toolkit/components/downloads/test/unit/head_download_manager.js index 4d7d421e1ad3..8f9b7eea5c28 100644 --- a/toolkit/components/downloads/test/unit/head_download_manager.js +++ b/toolkit/components/downloads/test/unit/head_download_manager.js @@ -63,7 +63,7 @@ var provider = { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js b/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js index 715036b34c58..339b7e57471a 100644 --- a/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js +++ b/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js @@ -69,7 +69,7 @@ if (!profileDir) { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } diff --git a/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js b/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js index cef9ebb0fecb..8285808f058d 100644 --- a/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js +++ b/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js @@ -70,7 +70,7 @@ if (!profileDir) { throw Cr.NS_ERROR_FAILURE; }, QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryProvider) || + if (iid.equals(Ci.nsIDirectoryServiceProvider) || iid.equals(Ci.nsISupports)) { return this; } From d0fffdb53f64dc2f29ab33c6bca3caebe9ee94fb Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 1 Apr 2010 09:58:42 -0400 Subject: [PATCH 17/69] Bug 541015 - Support rotating between portrait and landscape on N900 [r=karlt] --- toolkit/xre/nsNativeAppSupportUnix.cpp | 176 +++++++++++++++++++++++-- widget/src/gtk2/nsWindow.cpp | 8 ++ 2 files changed, 174 insertions(+), 10 deletions(-) diff --git a/toolkit/xre/nsNativeAppSupportUnix.cpp b/toolkit/xre/nsNativeAppSupportUnix.cpp index 8aa75451133f..56b68d4f717d 100644 --- a/toolkit/xre/nsNativeAppSupportUnix.cpp +++ b/toolkit/xre/nsNativeAppSupportUnix.cpp @@ -53,18 +53,36 @@ #include "nsICommandLineRunner.h" #include "nsIWindowMediator.h" #include "nsIDOMWindowInternal.h" +#include "nsPIDOMWindow.h" +#include "nsIDocShell.h" +#include "nsIBaseWindow.h" +#include "nsIWidget.h" +#include "nsIWritablePropertyBag2.h" #include #include #include #include +#ifdef MOZ_X11 +#include +#include +#endif + #ifdef MOZ_PLATFORM_MAEMO struct DBusMessage; /* libosso.h references internals of dbus */ #include #include #include + +// These come from (maemo sdk 5+) +#define MCE_SERVICE "com.nokia.mce" +#define MCE_REQUEST_IF "com.nokia.mce.request" +#define MCE_REQUEST_PATH "/com/nokia/mce/request" +#define MCE_SIGNAL_IF "com.nokia.mce.signal" +#define MCE_DEVICE_ORIENTATION_SIG "sig_device_orientation_ind" +#define MCE_MATCH_RULE "type='signal',interface='" MCE_SIGNAL_IF "',member='" MCE_DEVICE_ORIENTATION_SIG "'" #endif #define MIN_GTK_MAJOR_VERSION 2 @@ -155,6 +173,7 @@ class nsNativeAppSupportUnix : public nsNativeAppSupportBase public: NS_IMETHOD Start(PRBool* aRetVal); NS_IMETHOD Stop(PRBool *aResult); + NS_IMETHOD Enable(); private: #ifdef MOZ_PLATFORM_MAEMO @@ -169,17 +188,118 @@ private: }; #ifdef MOZ_PLATFORM_MAEMO +static nsresult +GetMostRecentWindow(const PRUnichar* aType, nsIDOMWindowInternal** aWindow) +{ + nsCOMPtr wm = do_GetService("@mozilla.org/appshell/window-mediator;1"); + if (wm) + return wm->GetMostRecentWindow(aType, aWindow); + return NS_ERROR_FAILURE; +} + +static GtkWidget* +WidgetForDOMWindow(nsISupports *aWindow) +{ + nsCOMPtr domWindow(do_QueryInterface(aWindow)); + if (!domWindow) + return NULL; + + nsCOMPtr baseWindow = do_QueryInterface(domWindow->GetDocShell()); + if (!baseWindow) + return NULL; + + nsCOMPtr widget; + baseWindow->GetMainWidget(getter_AddRefs(widget)); + if (!widget) + return NULL; + + return (GtkWidget*)(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); +} + +static void +OssoSetWindowOrientation(PRBool aPortrait) +{ + // Tell Hildon desktop to force our window to be either portrait or landscape, + // depending on the current rotation + // NOTE: We only update the most recent top-level window so this is only + // suitable for apps with only one window. + nsCOMPtr window; + GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window)); + GtkWidget* widget = WidgetForDOMWindow(window); + if (widget && widget->window) { + GdkWindow *gdk = widget->window; + GdkAtom request = gdk_atom_intern("_HILDON_PORTRAIT_MODE_REQUEST", FALSE); + + if (aPortrait) { + gulong portrait_set = 1; + gdk_property_change(gdk, request, gdk_x11_xatom_to_atom(XA_CARDINAL), + 32, GDK_PROP_MODE_REPLACE, (const guchar *) &portrait_set, 1); + } + else { + gdk_property_delete(gdk, request); + } + } + + // Update the system info property + nsCOMPtr info = do_GetService("@mozilla.org/system-info;1"); + if (info) { + info->SetPropertyAsAString(NS_LITERAL_STRING("screen-orientation"), + aPortrait ? NS_LITERAL_STRING("portrait") : NS_LITERAL_STRING("landscape")); + } +} + +static PRBool OssoIsScreenOn(osso_context_t* ctx) +{ + osso_return_t rv; + osso_rpc_t ret; + PRBool result = PR_FALSE; + + rv = osso_rpc_run_system(ctx, MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF, + "get_display_status", &ret, DBUS_TYPE_INVALID); + if (rv == OSSO_OK) { + if (strcmp(ret.value.s, "on") == 0) + result = PR_TRUE; + + osso_rpc_free_val(&ret); + } + return result; +} + +static void OssoRequestAccelerometer(osso_context_t *ctx, PRBool aEnabled) +{ + osso_return_t rv; + osso_rpc_t ret; + + rv = osso_rpc_run_system(ctx, + MCE_SERVICE, + MCE_REQUEST_PATH, MCE_REQUEST_IF, + aEnabled ? "req_accelerometer_enable" : "req_accelerometer_disable", + aEnabled ? &ret : NULL, + DBUS_TYPE_INVALID); + + // Orientation might changed while the accelerometer was off, so let's update + // the window's orientation + if (rv == OSSO_OK && aEnabled) { + OssoSetWindowOrientation(strcmp(ret.value.s, "portrait") == 0); + osso_rpc_free_val(&ret); + } +} static void OssoDisplayCallback(osso_display_state_t state, gpointer data) { nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1"); if (!os) return; - - if (state == OSSO_DISPLAY_ON) + + osso_context_t* context = (osso_context_t*) data; + + if (state == OSSO_DISPLAY_ON) { os->NotifyObservers(nsnull, "system-display-on", nsnull); - else + OssoRequestAccelerometer(context, PR_TRUE); + } else { os->NotifyObservers(nsnull, "system-display-dimmed-or-off", nsnull); + OssoRequestAccelerometer(context, PR_FALSE); + } } static void OssoHardwareCallback(osso_hw_state_t *state, gpointer data) @@ -226,13 +346,11 @@ OssoDbusCallback(const gchar *interface, const gchar *method, // The "top_application" method just wants us to focus the top-most window. if (!strcmp("top_application", method)) { - nsCOMPtr wm = do_GetService("@mozilla.org/appshell/window-mediator;1"); - nsCOMPtr window; - wm->GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window)); - if (window) { + GetMostRecentWindow(NS_LITERAL_STRING("").get(), getter_AddRefs(window)); + if (window) window->Focus(); - } + return OSSO_OK; } @@ -285,6 +403,21 @@ OssoDbusCallback(const gchar *interface, const gchar *method, return OSSO_OK; } +static DBusHandlerResult +OssoModeControlCallback(DBusConnection *con, DBusMessage *msg, gpointer data) +{ + if (dbus_message_is_signal(msg, MCE_SIGNAL_IF, MCE_DEVICE_ORIENTATION_SIG)) { + DBusMessageIter iter; + if (dbus_message_iter_init(msg, &iter)) { + const gchar *mode = NULL; + dbus_message_iter_get_basic(&iter, &mode); + + OssoSetWindowOrientation(strcmp(mode, "portrait") == 0); + } + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + #endif NS_IMETHODIMP @@ -323,7 +456,7 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal) system will happily kill your process. */ nsCAutoString applicationName; - if(gAppData->vendor) { + if (gAppData->vendor) { applicationName.Append(gAppData->vendor); applicationName.Append("."); } @@ -341,8 +474,13 @@ nsNativeAppSupportUnix::Start(PRBool *aRetVal) } osso_hw_set_event_cb(m_osso_context, nsnull, OssoHardwareCallback, &m_hw_state); - osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, nsnull); + osso_hw_set_display_event_cb(m_osso_context, OssoDisplayCallback, m_osso_context); osso_rpc_set_default_cb_f(m_osso_context, OssoDbusCallback, nsnull); + + // Setup an MCE callback to monitor orientation + DBusConnection *connnection = (DBusConnection*)osso_get_sys_dbus_connection(m_osso_context); + dbus_bus_add_match(connnection, MCE_MATCH_RULE, nsnull); + dbus_connection_add_filter(connnection, OssoModeControlCallback, nsnull, nsnull); #endif *aRetVal = PR_TRUE; @@ -455,6 +593,13 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult) #ifdef MOZ_PLATFORM_MAEMO if (m_osso_context) { + // Disable the accelerometer when closing + OssoRequestAccelerometer(m_osso_context, PR_FALSE); + + // Remove the MCE callback filter + DBusConnection *connnection = (DBusConnection*)osso_get_sys_dbus_connection(m_osso_context); + dbus_connection_remove_filter(connnection, OssoModeControlCallback, nsnull); + osso_hw_unset_event_cb(m_osso_context, nsnull); osso_rpc_unset_default_cb_f(m_osso_context, OssoDbusCallback, nsnull); osso_deinitialize(m_osso_context); @@ -464,6 +609,17 @@ nsNativeAppSupportUnix::Stop(PRBool *aResult) return NS_OK; } +NS_IMETHODIMP +nsNativeAppSupportUnix::Enable() +{ +#ifdef MOZ_PLATFORM_MAEMO + // Enable the accelerometer for orientation support + if (OssoIsScreenOn(m_osso_context)) + OssoRequestAccelerometer(m_osso_context, PR_TRUE); +#endif + return NS_OK; +} + nsresult NS_CreateNativeAppSupport(nsINativeAppSupport **aResult) { diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index aa3efded7197..37c8c6fd1a7a 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -91,6 +91,7 @@ #include "nsIObserverService.h" #include "nsIdleService.h" +#include "nsIPropertyBag2.h" #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" @@ -4265,6 +4266,13 @@ nsWindow::Create(nsIWidget *aParent, if (mWindowType == eWindowType_toplevel) { GdkWindow *gdkwin = mShell->window; + // Tell the Hildon desktop that we support being rotated + gulong portrait_set = 1; + GdkAtom support = gdk_atom_intern("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE); + gdk_property_change(gdkwin, support, gdk_x11_xatom_to_atom(XA_CARDINAL), + 32, GDK_PROP_MODE_REPLACE, + (const guchar *) &portrait_set, 1); + // Tell maemo-status-volume daemon to ungrab keys gulong volume_set = 1; GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE); From 2aec598f2712f1a3f89647d5c36a9b8a73f8703e Mon Sep 17 00:00:00 2001 From: "timeless@mozdev.org" Date: Thu, 1 Apr 2010 08:07:22 -0700 Subject: [PATCH 18/69] Bug 552246 remove unused variable availWidth from nsTableRowFrame::CalcHeight r=bernd --- layout/tables/nsTableRowFrame.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 1eee1602142c..c3e4595c6cb6 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -552,7 +552,6 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState) kidFrame = kidFrame->GetNextSibling()) { nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame); if (cellFrame) { - nscoord availWidth = cellFrame->GetPriorAvailWidth(); nsSize desSize = cellFrame->GetDesiredSize(); if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !GetPrevInFlow()) { CalculateCellActualHeight(cellFrame, desSize.height); From 5732abd0d78cfe5d6d9fc6d2cefa7f34c4ead7cc Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 08:07:22 -0700 Subject: [PATCH 19/69] Bug 556005: Remove unused variable 'rv' from nsXULDocument.cpp. r=bz --- content/xul/document/src/nsXULDocument.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 914001b3826f..ad208e62a434 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -4164,8 +4164,6 @@ nsXULDocument::BroadcasterHookup::~BroadcasterHookup() #ifdef PR_LOGGING if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING) && !mResolved) { // Tell the world we failed - nsresult rv; - nsIAtom *tag = mObservesElement->Tag(); nsAutoString broadcasterID; From 9d9224d62d94bc61b346e14be971732fcf2d1370 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 08:07:23 -0700 Subject: [PATCH 20/69] Bug 551298, patch A: Move THEBES_INLINE_DECL_REFCOUNTING to xpcom (with s/THEBES/NS/). r=bsmedberg --- gfx/thebes/public/gfxTypes.h | 22 +--------------------- xpcom/glue/nsISupportsImpl.h | 29 +++++++++++++++++++++++++++++ xpcom/glue/nsISupportsUtils.h | 6 ++++-- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index cb4dccebffa0..b68c48f1e790 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -98,27 +98,7 @@ enum gfxBreakPriority { #include "nsAutoPtr.h" #define THEBES_INLINE_DECL_REFCOUNTING(_class) \ -public: \ - nsrefcnt AddRef(void) { \ - NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ - ++mRefCnt; \ - NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ - return mRefCnt; \ - } \ - nsrefcnt Release(void) { \ - NS_PRECONDITION(0 != mRefCnt, "dup release"); \ - --mRefCnt; \ - NS_LOG_RELEASE(this, mRefCnt, #_class); \ - if (mRefCnt == 0) { \ - mRefCnt = 1; /* stabilize */ \ - NS_DELETEXPCOM(this); \ - return 0; \ - } \ - return mRefCnt; \ - } \ -protected: \ - nsAutoRefCnt mRefCnt; \ -public: + NS_INLINE_DECL_REFCOUNTING(_class) #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index fe0c719e62e9..f510c8e4ef3f 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -303,6 +303,35 @@ public: */ #define NS_INIT_ISUPPORTS() ((void)0) +/** + * Use this macro to declare and implement the AddRef & Release methods for a + * given non-XPCOM _class. + * + * The implementations here should match NS_IMPL_ADDREF/NS_IMPL_RELEASE, minus + * the nsrefcnt return-value and the NS_ASSERT_OWNINGTHREAD() call. + * + * @param _class The name of the class implementing the method + */ +#define NS_INLINE_DECL_REFCOUNTING(_class) \ +public: \ + void AddRef(void) { \ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + ++mRefCnt; \ + NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ + } \ + void Release(void) { \ + NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + --mRefCnt; \ + NS_LOG_RELEASE(this, mRefCnt, #_class); \ + if (mRefCnt == 0) { \ + mRefCnt = 1; /* stabilize */ \ + NS_DELETEXPCOM(this); \ + } \ + } \ +protected: \ + nsAutoRefCnt mRefCnt; \ +public: + /** * Use this macro to implement the AddRef method for a given _class * @param _class The name of the class implementing the method diff --git a/xpcom/glue/nsISupportsUtils.h b/xpcom/glue/nsISupportsUtils.h index e20aa5e3ece8..7bfb89494650 100644 --- a/xpcom/glue/nsISupportsUtils.h +++ b/xpcom/glue/nsISupportsUtils.h @@ -108,10 +108,12 @@ extern "C++" { // yet still denies you the ability to |AddRef()| an |nsCOMPtr|. template inline -nsrefcnt +void ns_if_addref( T expr ) { - return expr ? expr->AddRef() : 0; + if (expr) { + expr->AddRef(); + } } } /* extern "C++" */ From ca50c7092d553aa5ae26ea4379611ec977797d94 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 08:08:51 -0700 Subject: [PATCH 21/69] Bug 551298, patch D: Use NS_INLINE_DECL_REFCOUNTING in /content/ directory. r=sicking --- content/smil/nsSMILInstanceTime.h | 34 +------------- content/xbl/src/nsXBLBinding.h | 21 +-------- content/xbl/src/nsXBLInsertionPoint.cpp | 13 ------ content/xbl/src/nsXBLInsertionPoint.h | 11 +---- content/xbl/src/nsXBLPrototypeBinding.cpp | 17 +------ .../src/xslt/txMozillaStylesheetCompiler.cpp | 44 ++----------------- .../xslt/txStandaloneStylesheetCompiler.cpp | 21 +-------- content/xslt/src/xslt/txStylesheet.h | 20 ++------- .../xslt/src/xslt/txStylesheetCompiler.cpp | 21 --------- content/xslt/src/xslt/txStylesheetCompiler.h | 19 +++----- content/xul/templates/src/nsRDFBinding.h | 21 ++------- 11 files changed, 22 insertions(+), 220 deletions(-) diff --git a/content/smil/nsSMILInstanceTime.h b/content/smil/nsSMILInstanceTime.h index 6b05ace864d6..b76e87641720 100644 --- a/content/smil/nsSMILInstanceTime.h +++ b/content/smil/nsSMILInstanceTime.h @@ -124,36 +124,7 @@ public: PRUint32 Serial() const { return mSerial; } void SetSerial(PRUint32 aIndex) { mSerial = aIndex; } - nsrefcnt AddRef() - { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); - return mRefCnt; - } - NS_ASSERT_OWNINGTHREAD(_class); - NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), - "nsSMILInstanceTime addref isn't thread-safe!"); - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsSMILInstanceTime", sizeof(*this)); - return mRefCnt; - } - - nsrefcnt Release() - { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); - return mRefCnt; - } - NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), - "nsSMILInstanceTime release isn't thread-safe!"); - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsSMILInstanceTime"); - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsSMILInstanceTime) protected: void SetBaseInterval(nsSMILInterval* aBaseInterval); @@ -162,9 +133,6 @@ protected: nsSMILTimeValue mTime; - nsAutoRefCnt mRefCnt; - NS_DECL_OWNINGTHREAD - // Internal flags used for represent behaviour of different instance times` enum { // Indicates if this instance time should be removed when the owning timed diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index 492c9757ee5d..d88633a70899 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -46,6 +46,7 @@ #include "nsClassHashtable.h" #include "nsTArray.h" #include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" class nsXBLPrototypeBinding; class nsIContent; @@ -77,24 +78,7 @@ public: * which are queued to fire their constructors. */ - nsrefcnt AddRef() - { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLBinding", sizeof(nsXBLBinding)); - return mRefCnt; - } - - nsrefcnt Release() - { - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLBinding"); - if (mRefCnt == 0) { - mRefCnt = 1; - delete this; - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsXBLBinding) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding) @@ -172,7 +156,6 @@ public: // MEMBER VARIABLES protected: - nsAutoRefCnt mRefCnt; nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. nsRefPtr mNextBinding; // Strong. The derived binding owns the base class bindings. diff --git a/content/xbl/src/nsXBLInsertionPoint.cpp b/content/xbl/src/nsXBLInsertionPoint.cpp index 62e703195086..d3d0dc582fa8 100644 --- a/content/xbl/src/nsXBLInsertionPoint.cpp +++ b/content/xbl/src/nsXBLInsertionPoint.cpp @@ -57,19 +57,6 @@ nsXBLInsertionPoint::~nsXBLInsertionPoint() } } -nsrefcnt -nsXBLInsertionPoint::Release() -{ - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPoint"); - if (mRefCnt == 0) { - mRefCnt = 1; - delete this; - return 0; - } - return mRefCnt; -} - NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) diff --git a/content/xbl/src/nsXBLInsertionPoint.h b/content/xbl/src/nsXBLInsertionPoint.h index c1f05045a4df..5ec9239bd3f3 100644 --- a/content/xbl/src/nsXBLInsertionPoint.h +++ b/content/xbl/src/nsXBLInsertionPoint.h @@ -50,15 +50,7 @@ public: nsXBLInsertionPoint(nsIContent* aParentElement, PRUint32 aIndex, nsIContent* aDefContent); ~nsXBLInsertionPoint(); - nsrefcnt AddRef() - { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPoint", - sizeof(nsXBLInsertionPoint)); - return mRefCnt; - } - - nsrefcnt Release(); + NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPoint) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint) @@ -90,7 +82,6 @@ public: void UnbindDefaultContent(); protected: - nsAutoRefCnt mRefCnt; nsIContent* mParentElement; // This ref is weak. The parent of the element. PRInt32 mIndex; // The index of this insertion point. -1 is a pseudo-point. nsCOMArray mElements; // An array of elements present at the insertion point. diff --git a/content/xbl/src/nsXBLPrototypeBinding.cpp b/content/xbl/src/nsXBLPrototypeBinding.cpp index 8b6e97d2b036..4f417c8e1c60 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -207,27 +207,12 @@ public: nsXBLInsertionPointEntry::ReleasePool(); } - nsrefcnt AddRef() { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPointEntry", sizeof(nsXBLInsertionPointEntry)); - return mRefCnt; - } - - nsrefcnt Release() { - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPointEntry"); - if (mRefCnt == 0) { - Destroy(this); - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPointEntry) protected: nsCOMPtr mInsertionParent; nsCOMPtr mDefaultContent; PRUint32 mInsertionIndex; - nsAutoRefCnt mRefCnt; nsXBLInsertionPointEntry(nsIContent* aParent) : mInsertionParent(aParent), diff --git a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp index daf934456161..2ab7c3f11795 100644 --- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp @@ -404,14 +404,12 @@ public: txCompileObserver(txMozillaXSLTProcessor* aProcessor, nsILoadGroup* aLoadGroup); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txCompileObserver) nsresult startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsIPrincipal* aSourcePrincipal); -protected: - nsAutoRefCnt mRefCnt; - private: nsRefPtr mProcessor; nsCOMPtr mLoadGroup; @@ -429,23 +427,6 @@ txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor, { } -nsrefcnt -txCompileObserver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txCompileObserver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - nsresult txCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -658,11 +639,11 @@ class txSyncCompileObserver : public txACompileObserver public: txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver) protected: nsRefPtr mProcessor; - nsAutoRefCnt mRefCnt; }; txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) @@ -670,23 +651,6 @@ txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) { } -nsrefcnt -txSyncCompileObserver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txSyncCompileObserver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - nsresult txSyncCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, diff --git a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp index 11347fbbfd06..f68ad544ccad 100644 --- a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp @@ -64,7 +64,8 @@ class txDriver : public txACompileObserver const XML_Char *aSystemId, const XML_Char *aPublicId); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txDriver) nsRefPtr mCompiler; protected: @@ -73,7 +74,6 @@ class txDriver : public txACompileObserver // keep track of the nsresult returned by the handlers, expat forgets them nsresult mRV; XML_Parser mExpatParser; - nsAutoRefCnt mRefCnt; }; nsresult @@ -338,23 +338,6 @@ txDriver::createErrorString() * txACompileObserver implementation */ -nsrefcnt -txDriver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txDriver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - void txDriver::onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, const PRUnichar *aErrorText, const PRUnichar *aParam) diff --git a/content/xslt/src/xslt/txStylesheet.h b/content/xslt/src/xslt/txStylesheet.h index 5f6228f1fbe9..cd159e8f7306 100644 --- a/content/xslt/src/xslt/txStylesheet.h +++ b/content/xslt/src/xslt/txStylesheet.h @@ -44,6 +44,7 @@ #include "txList.h" #include "txXSLTPatterns.h" #include "nsTPtrArray.h" +#include "nsISupportsImpl.h" class txInstruction; class txToplevelItem; @@ -67,20 +68,8 @@ public: txStylesheet(); ~txStylesheet(); nsresult init(); - - nsrefcnt AddRef() - { - return ++mRefCnt; - } - nsrefcnt Release() - { - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; - } + + NS_INLINE_DECL_REFCOUNTING(txStylesheet) txInstruction* findTemplate(const txXPathNode& aNode, const txExpandedName& aMode, @@ -159,9 +148,6 @@ private: nsTPtrArray& aFrameStripSpaceTests); nsresult addAttributeSet(txAttributeSetItem* aAttributeSetItem); - // Refcount - nsAutoRefCnt mRefCnt; - // List of ImportFrames txList mImportFrames; diff --git a/content/xslt/src/xslt/txStylesheetCompiler.cpp b/content/xslt/src/xslt/txStylesheetCompiler.cpp index 759c5cb4306d..d0050683fd0b 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStylesheetCompiler.cpp @@ -69,27 +69,6 @@ txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI, mStatus = init(aStylesheetURI, aStylesheet, aInsertPosition); } -nsrefcnt -txStylesheetCompiler::AddRef() -{ - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "txStylesheetCompiler", sizeof(*this)); - return mRefCnt; -} - -nsrefcnt -txStylesheetCompiler::Release() -{ - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "txStylesheetCompiler"); - if (mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - void txStylesheetCompiler::setBaseURI(const nsString& aBaseURI) { diff --git a/content/xslt/src/xslt/txStylesheetCompiler.h b/content/xslt/src/xslt/txStylesheetCompiler.h index fc23fb4d3d89..4d71484af266 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.h +++ b/content/xslt/src/xslt/txStylesheetCompiler.h @@ -77,8 +77,8 @@ public: class txACompileObserver { public: - virtual nsrefcnt AddRef() = 0; - virtual nsrefcnt Release() = 0; + virtual void AddRef() = 0; + virtual void Release() = 0; virtual nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -90,13 +90,11 @@ public: }; #define TX_DECL_ACOMPILEOBSERVER \ - nsrefcnt AddRef(); \ - nsrefcnt Release(); \ nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, \ txStylesheetCompiler* aCompiler); \ void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, \ const PRUnichar *aErrorText = nsnull, \ - const PRUnichar *aParam = nsnull) + const PRUnichar *aParam = nsnull); class txStylesheetCompilerState : public txIParseContext { @@ -215,8 +213,6 @@ public: txStylesheet* aStylesheet, txListIterator* aInsertPosition, txACompileObserver* aObserver); - virtual nsrefcnt AddRef(); - virtual nsrefcnt Release(); void setBaseURI(const nsString& aBaseURI); @@ -235,12 +231,8 @@ public: txStylesheet* getStylesheet(); - // txACompileObserver - nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, - txStylesheetCompiler* aCompiler); - void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, - const PRUnichar *aErrorText = nsnull, - const PRUnichar *aParam = nsnull); + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txStylesheetCompiler) private: nsresult startElementInternal(PRInt32 aNamespaceID, nsIAtom* aLocalName, @@ -253,7 +245,6 @@ private: nsresult ensureNewElementContext(); nsresult maybeDoneCompiling(); - nsAutoRefCnt mRefCnt; nsString mCharacters; nsresult mStatus; }; diff --git a/content/xul/templates/src/nsRDFBinding.h b/content/xul/templates/src/nsRDFBinding.h index 2a8ab79973fc..82ad20068ddf 100644 --- a/content/xul/templates/src/nsRDFBinding.h +++ b/content/xul/templates/src/nsRDFBinding.h @@ -40,6 +40,7 @@ #include "nsAutoPtr.h" #include "nsIAtom.h" #include "nsIRDFResource.h" +#include "nsISupportsImpl.h" class nsXULTemplateResultRDF; class nsBindingValues; @@ -95,9 +96,6 @@ class RDFBindingSet { protected: - // results hold a reference to a binding set in their nsBindingValues fields - PRInt32 mRefCnt; - // the number of bindings PRInt32 mCount; @@ -107,8 +105,7 @@ protected: public: RDFBindingSet() - : mRefCnt(0), - mCount(0), + : mCount(0), mFirst(nsnull) { MOZ_COUNT_CTOR(RDFBindingSet); @@ -116,19 +113,7 @@ public: ~RDFBindingSet(); - PRInt32 AddRef() { - mRefCnt++; - NS_LOG_ADDREF(this, mRefCnt, "RDFBindingSet", sizeof(*this)); - return mRefCnt; - } - - PRInt32 Release() - { - PRInt32 refcnt = --mRefCnt; - NS_LOG_RELEASE(this, refcnt, "RDFBindingSet"); - if (refcnt == 0) delete this; - return refcnt; - } + NS_INLINE_DECL_REFCOUNTING(RDFBindingSet) PRInt32 Count() const { return mCount; } From b5ac7959ce15e285f9c9b365ee8bb116d4845b53 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 08:08:51 -0700 Subject: [PATCH 22/69] Bug 551298, patch C: Use NS_INLINE_DECL_REFCOUNTING in /layout/ directory. r=roc --- layout/style/nsCSSValue.cpp | 6 ++-- layout/style/nsCSSValue.h | 65 ++++------------------------------ layout/style/nsStyleStruct.cpp | 21 ----------- layout/style/nsStyleStruct.h | 42 +++------------------- 4 files changed, 14 insertions(+), 120 deletions(-) diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index 548a969c429c..f2a940779659 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -506,8 +506,7 @@ nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer, : mURI(aURI), mString(aString), mReferrer(aReferrer), - mOriginPrincipal(aOriginPrincipal), - mRefCnt(0) + mOriginPrincipal(aOriginPrincipal) { NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal"); mString->AddRef(); @@ -593,7 +592,6 @@ nsCSSValueGradient::nsCSSValueGradient(PRBool aIsRadial, mBgPosY(eCSSUnit_None), mAngle(eCSSUnit_None), mRadialShape(eCSSUnit_None), - mRadialSize(eCSSUnit_None), - mRefCnt(0) + mRadialSize(eCSSUnit_None) { } diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 35db8b4d3003..4404beef5087 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -51,6 +51,7 @@ #include "nsCRTGlue.h" #include "nsStringBuffer.h" #include "nsTArray.h" +#include "nsISupportsImpl.h" class imgIRequest; class nsIDocument; @@ -379,26 +380,9 @@ public: nsCOMPtr mReferrer; nsCOMPtr mOriginPrincipal; - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::URL", sizeof(*this)); - } - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::URL"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(URL) + protected: - nsrefcnt mRefCnt; // not to be implemented URL(const URL& aOther); @@ -420,25 +404,7 @@ public: // Override AddRef and Release to not only log ourselves correctly, but // also so that we delete correctly without a virtual destructor - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Image", sizeof(*this)); - } - - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Image"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(Image) }; private: @@ -529,28 +495,9 @@ struct nsCSSValueGradient { return !(*this == aOther); } - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Gradient", sizeof(*this)); - } - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Gradient"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient) private: - nsrefcnt mRefCnt; - // not to be implemented nsCSSValueGradient(const nsCSSValueGradient& aOther); nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther); @@ -588,6 +535,8 @@ struct nsCSSValue::Array { return PR_TRUE; } + // XXXdholbert This uses a 16-bit ref count to save space. Should we use + // a variant of NS_INLINE_DECL_REFCOUNTING that takes a type as an argument? void AddRef() { if (mRefCnt == PR_UINT16_MAX) { NS_WARNING("refcount overflow, leaking nsCSSValue::Array"); diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 1368487368d5..4eeb50f86ae2 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1317,7 +1317,6 @@ nsStyleGradient::nsStyleGradient(void) : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR) , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) , mRepeating(PR_FALSE) - , mRefCnt(0) { } @@ -2318,26 +2317,6 @@ nsChangeHint nsStyleTextReset::MaxDifference() } #endif -// -------------------- -// nsCSSShadowArray -// nsCSSShadowItem -// - -nsrefcnt -nsCSSShadowArray::Release() -{ - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - mRefCnt--; - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; -} - // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though. // XXXbz can this not return a more specific hint? If that's ever diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 46be0ae3db1b..77f8e7e0910e 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -163,38 +163,14 @@ public: // stops are in the order specified in the stylesheet nsTArray mStops; - nsrefcnt AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsStyleGradient"); - return mRefCnt; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsStyleGradient", sizeof(*this)); - return mRefCnt; - } - - nsrefcnt Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsStyleGradient"); - return mRefCnt; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsStyleGradient"); - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } - PRBool operator==(const nsStyleGradient& aOther) const; PRBool operator!=(const nsStyleGradient& aOther) const { return !(*this == aOther); }; -private: - nsrefcnt mRefCnt; + NS_INLINE_DECL_REFCOUNTING(nsStyleGradient) +private: ~nsStyleGradient() {} // Not to be implemented @@ -671,7 +647,7 @@ class nsCSSShadowArray { } nsCSSShadowArray(PRUint32 aArrayLen) : - mLength(aArrayLen), mRefCnt(0) + mLength(aArrayLen) { MOZ_COUNT_CTOR(nsCSSShadowArray); for (PRUint32 i = 1; i < mLength; ++i) { @@ -687,15 +663,6 @@ class nsCSSShadowArray { } } - nsrefcnt AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - return ++mRefCnt; - } - nsrefcnt Release(); - PRUint32 Length() const { return mLength; } nsCSSShadowItem* ShadowAt(PRUint32 i) { NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!"); @@ -706,9 +673,10 @@ class nsCSSShadowArray { return &mArray[i]; } + NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray) + private: PRUint32 mLength; - PRUint32 mRefCnt; nsCSSShadowItem mArray[1]; // This MUST be the last item }; From f670acaa95ecf36ff3ddb62b2ae1571c4c14855a Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 08:08:51 -0700 Subject: [PATCH 23/69] Bug 551298, patch B: Replace uses of THEBES_INLINE_DECL_REFCOUNTING with NS_INLINE_DECL_REFCOUNTING. r=roc --- content/svg/content/src/nsSVGMatrix.cpp | 1 + content/svg/content/src/nsSVGMatrix.h | 1 + gfx/layers/Layers.h | 6 ++++-- gfx/thebes/public/gfxASurface.h | 1 + gfx/thebes/public/gfxContext.h | 3 ++- gfx/thebes/public/gfxFont.h | 7 ++++--- gfx/thebes/public/gfxGdkNativeRenderer.h | 1 + gfx/thebes/public/gfxPath.h | 3 ++- gfx/thebes/public/gfxPattern.h | 4 +++- gfx/thebes/public/gfxRect.h | 1 + gfx/thebes/public/gfxTypes.h | 10 ---------- gfx/thebes/public/gfxUserFontSet.h | 3 ++- gfx/thebes/src/gfxFontconfigUtils.h | 3 ++- gfx/thebes/src/gfxPangoFonts.cpp | 2 +- layout/printing/nsPrintData.h | 1 + 15 files changed, 26 insertions(+), 21 deletions(-) diff --git a/content/svg/content/src/nsSVGMatrix.cpp b/content/svg/content/src/nsSVGMatrix.cpp index ee155e5aa7ac..c7e7d75612d1 100644 --- a/content/svg/content/src/nsSVGMatrix.cpp +++ b/content/svg/content/src/nsSVGMatrix.cpp @@ -41,6 +41,7 @@ #include "nsSVGValue.h" #include #include "nsContentUtils.h" +#include "nsISupportsImpl.h" const double radPerDegree = 2.0*3.1415926535 / 360.0; diff --git a/content/svg/content/src/nsSVGMatrix.h b/content/svg/content/src/nsSVGMatrix.h index 6d1f5d2f2612..c95002031716 100644 --- a/content/svg/content/src/nsSVGMatrix.h +++ b/content/svg/content/src/nsSVGMatrix.h @@ -71,6 +71,7 @@ #include "nsIDOMSVGMatrix.h" #include "gfxMatrix.h" +#include "nsAutoPtr.h" nsresult NS_NewSVGMatrix(nsIDOMSVGMatrix** result, diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index a3759ceeebde..b5d674be34b4 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -42,6 +42,8 @@ #include "nsRegion.h" #include "nsPoint.h" #include "nsRect.h" +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" #include "gfx3DMatrix.h" class gfxContext; @@ -106,7 +108,7 @@ class ImageContainer; * root layer, and each container layer holds a reference to its children. */ class THEBES_API LayerManager { - THEBES_INLINE_DECL_REFCOUNTING(LayerManager) + NS_INLINE_DECL_REFCOUNTING(LayerManager) public: enum LayersBackend { @@ -181,7 +183,7 @@ public: * surface. */ class THEBES_API Layer { - THEBES_INLINE_DECL_REFCOUNTING(Layer) + NS_INLINE_DECL_REFCOUNTING(Layer) public: virtual ~Layer() {} diff --git a/gfx/thebes/public/gfxASurface.h b/gfx/thebes/public/gfxASurface.h index 4c2143d646aa..c84f4ea14a60 100644 --- a/gfx/thebes/public/gfxASurface.h +++ b/gfx/thebes/public/gfxASurface.h @@ -40,6 +40,7 @@ #include "gfxTypes.h" #include "gfxRect.h" +#include "nsAutoPtr.h" typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_user_data_key cairo_user_data_key_t; diff --git a/gfx/thebes/public/gfxContext.h b/gfx/thebes/public/gfxContext.h index 23f2f068db8c..f9e95d2dfeb8 100644 --- a/gfx/thebes/public/gfxContext.h +++ b/gfx/thebes/public/gfxContext.h @@ -48,6 +48,7 @@ #include "gfxMatrix.h" #include "gfxPattern.h" #include "gfxPath.h" +#include "nsISupportsImpl.h" typedef struct _cairo cairo_t; @@ -66,7 +67,7 @@ typedef struct _cairo cairo_t; * as opposed to app units. */ class THEBES_API gfxContext { - THEBES_INLINE_DECL_REFCOUNTING(gfxContext) + NS_INLINE_DECL_REFCOUNTING(gfxContext) public: /** diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index 370654c53e02..f808c32ce9f6 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -55,6 +55,7 @@ #include "gfxFontConstants.h" #include "gfxPlatform.h" #include "nsIAtom.h" +#include "nsISupportsImpl.h" #ifdef DEBUG #include @@ -160,7 +161,7 @@ struct THEBES_API gfxFontStyle { class gfxFontEntry { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry) + NS_INLINE_DECL_REFCOUNTING(gfxFontEntry) gfxFontEntry(const nsAString& aName, gfxFontFamily *aFamily = nsnull, PRBool aIsStandardFace = PR_FALSE) : @@ -289,7 +290,7 @@ struct FontSearch { class gfxFontFamily { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontFamily) + NS_INLINE_DECL_REFCOUNTING(gfxFontFamily) gfxFontFamily(const nsAString& aName) : mName(aName), @@ -955,7 +956,7 @@ protected: }; class THEBES_API gfxTextRunFactory { - THEBES_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) + NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) public: // Flags in the mask 0xFFFF0000 are reserved for textrun clients diff --git a/gfx/thebes/public/gfxGdkNativeRenderer.h b/gfx/thebes/public/gfxGdkNativeRenderer.h index 68cf01570061..ca5bef4337aa 100644 --- a/gfx/thebes/public/gfxGdkNativeRenderer.h +++ b/gfx/thebes/public/gfxGdkNativeRenderer.h @@ -39,6 +39,7 @@ #define GFXGDKNATIVERENDER_H_ #include "gfxColor.h" +#include "nsAutoPtr.h" #include class gfxASurface; diff --git a/gfx/thebes/public/gfxPath.h b/gfx/thebes/public/gfxPath.h index 1a5cc2e9f729..127b81ea4d24 100644 --- a/gfx/thebes/public/gfxPath.h +++ b/gfx/thebes/public/gfxPath.h @@ -38,6 +38,7 @@ #define GFX_PATH_H #include "gfxTypes.h" +#include "nsISupportsImpl.h" class gfxContext; struct gfxPoint; @@ -48,7 +49,7 @@ typedef struct cairo_path cairo_path_t; * of a gfxContext. */ class THEBES_API gfxPath { - THEBES_INLINE_DECL_REFCOUNTING(gfxPath) + NS_INLINE_DECL_REFCOUNTING(gfxPath) friend class gfxContext; diff --git a/gfx/thebes/public/gfxPattern.h b/gfx/thebes/public/gfxPattern.h index 26f67b35f1d2..b378b815c02a 100644 --- a/gfx/thebes/public/gfxPattern.h +++ b/gfx/thebes/public/gfxPattern.h @@ -42,6 +42,8 @@ #include "gfxColor.h" #include "gfxMatrix.h" +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" class gfxContext; class gfxASurface; @@ -49,7 +51,7 @@ typedef struct _cairo_pattern cairo_pattern_t; class THEBES_API gfxPattern { - THEBES_INLINE_DECL_REFCOUNTING(gfxPattern) + NS_INLINE_DECL_REFCOUNTING(gfxPattern) public: gfxPattern(cairo_pattern_t *aPattern); diff --git a/gfx/thebes/public/gfxRect.h b/gfx/thebes/public/gfxRect.h index c024211aa5bd..7da3e1f2678a 100644 --- a/gfx/thebes/public/gfxRect.h +++ b/gfx/thebes/public/gfxRect.h @@ -40,6 +40,7 @@ #include "gfxTypes.h" #include "gfxPoint.h" +#include "nsDebug.h" struct THEBES_API gfxCorner { typedef int Corner; diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index b68c48f1e790..1e1f0862cb3d 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -90,16 +90,6 @@ enum gfxBreakPriority { eNormalBreak }; -/** - * Define refcounting for Thebes. For now use the stuff from nsISupportsImpl - * even though it forces the functions to be virtual... - */ -#include "nsISupportsImpl.h" -#include "nsAutoPtr.h" - -#define THEBES_INLINE_DECL_REFCOUNTING(_class) \ - NS_INLINE_DECL_REFCOUNTING(_class) - #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ nsrefcnt AddRef(void) { \ diff --git a/gfx/thebes/public/gfxUserFontSet.h b/gfx/thebes/public/gfxUserFontSet.h index 654350c89d8a..aece55f5789b 100644 --- a/gfx/thebes/public/gfxUserFontSet.h +++ b/gfx/thebes/public/gfxUserFontSet.h @@ -46,6 +46,7 @@ #include "nsCOMPtr.h" #include "nsIURI.h" #include "nsIFile.h" +#include "nsISupportsImpl.h" class nsIURI; class gfxMixedFontFamily; @@ -138,7 +139,7 @@ class THEBES_API gfxUserFontSet { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxUserFontSet) + NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet) gfxUserFontSet(); virtual ~gfxUserFontSet(); diff --git a/gfx/thebes/src/gfxFontconfigUtils.h b/gfx/thebes/src/gfxFontconfigUtils.h index 7dcb6a38758b..4943f77b8cda 100644 --- a/gfx/thebes/src/gfxFontconfigUtils.h +++ b/gfx/thebes/src/gfxFontconfigUtils.h @@ -44,6 +44,7 @@ #include "nsAutoRef.h" #include "nsTArray.h" #include "nsTHashtable.h" +#include "nsISupportsImpl.h" #include @@ -87,7 +88,7 @@ class gfxIgnoreCaseCStringComparator class gfxFontNameList : public nsTArray { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontNameList) + NS_INLINE_DECL_REFCOUNTING(gfxFontNameList) PRBool Exists(nsAString& aName); }; diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index 3069a396e015..06b1da984218 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -935,7 +935,7 @@ GetFontGroup(PangoContext *aContext) class gfxFcPangoFontSet { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) + NS_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) explicit gfxFcPangoFontSet(FcPattern *aPattern, gfxUserFontSet *aUserFontSet) diff --git a/layout/printing/nsPrintData.h b/layout/printing/nsPrintData.h index bd6dbf322e38..97dfb4f468d8 100644 --- a/layout/printing/nsPrintData.h +++ b/layout/printing/nsPrintData.h @@ -44,6 +44,7 @@ #include "nsIPrintOptions.h" #include "nsTArray.h" #include "nsCOMArray.h" +#include "nsAutoPtr.h" // Classes class nsPrintObject; From 73d9d71072e93739c0cf7c41f6438118480209c6 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 08:08:51 -0700 Subject: [PATCH 24/69] Bug 551298, patch A followup i: Add thread safety assertions to AddRef/Release implementations. r=bsmedberg --- xpcom/glue/nsISupportsImpl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index f510c8e4ef3f..69c5ed10b983 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -316,11 +316,13 @@ public: public: \ void AddRef(void) { \ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ ++mRefCnt; \ NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ } \ void Release(void) { \ NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ --mRefCnt; \ NS_LOG_RELEASE(this, mRefCnt, #_class); \ if (mRefCnt == 0) { \ @@ -330,6 +332,7 @@ public: \ } \ protected: \ nsAutoRefCnt mRefCnt; \ + NS_DECL_OWNINGTHREAD \ public: /** From 9a588376e3cad1d91bb6224b6f72279de2bc4bb1 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 09:37:26 -0700 Subject: [PATCH 25/69] Backed out changeset 13819d2e9bd8 (Bug 551298) due to Linux debug mochitest-5 orange --- content/smil/nsSMILInstanceTime.h | 34 +++++++++++++- content/xbl/src/nsXBLBinding.h | 21 ++++++++- content/xbl/src/nsXBLInsertionPoint.cpp | 13 ++++++ content/xbl/src/nsXBLInsertionPoint.h | 11 ++++- content/xbl/src/nsXBLPrototypeBinding.cpp | 17 ++++++- .../src/xslt/txMozillaStylesheetCompiler.cpp | 44 +++++++++++++++++-- .../xslt/txStandaloneStylesheetCompiler.cpp | 21 ++++++++- content/xslt/src/xslt/txStylesheet.h | 20 +++++++-- .../xslt/src/xslt/txStylesheetCompiler.cpp | 21 +++++++++ content/xslt/src/xslt/txStylesheetCompiler.h | 19 +++++--- content/xul/templates/src/nsRDFBinding.h | 21 +++++++-- 11 files changed, 220 insertions(+), 22 deletions(-) diff --git a/content/smil/nsSMILInstanceTime.h b/content/smil/nsSMILInstanceTime.h index b76e87641720..6b05ace864d6 100644 --- a/content/smil/nsSMILInstanceTime.h +++ b/content/smil/nsSMILInstanceTime.h @@ -124,7 +124,36 @@ public: PRUint32 Serial() const { return mSerial; } void SetSerial(PRUint32 aIndex) { mSerial = aIndex; } - NS_INLINE_DECL_REFCOUNTING(nsSMILInstanceTime) + nsrefcnt AddRef() + { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); + return mRefCnt; + } + NS_ASSERT_OWNINGTHREAD(_class); + NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), + "nsSMILInstanceTime addref isn't thread-safe!"); + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsSMILInstanceTime", sizeof(*this)); + return mRefCnt; + } + + nsrefcnt Release() + { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); + return mRefCnt; + } + NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), + "nsSMILInstanceTime release isn't thread-safe!"); + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsSMILInstanceTime"); + if (mRefCnt == 0) { + delete this; + return 0; + } + return mRefCnt; + } protected: void SetBaseInterval(nsSMILInterval* aBaseInterval); @@ -133,6 +162,9 @@ protected: nsSMILTimeValue mTime; + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD + // Internal flags used for represent behaviour of different instance times` enum { // Indicates if this instance time should be removed when the owning timed diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index d88633a70899..492c9757ee5d 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -46,7 +46,6 @@ #include "nsClassHashtable.h" #include "nsTArray.h" #include "nsCycleCollectionParticipant.h" -#include "nsISupportsImpl.h" class nsXBLPrototypeBinding; class nsIContent; @@ -78,7 +77,24 @@ public: * which are queued to fire their constructors. */ - NS_INLINE_DECL_REFCOUNTING(nsXBLBinding) + nsrefcnt AddRef() + { + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsXBLBinding", sizeof(nsXBLBinding)); + return mRefCnt; + } + + nsrefcnt Release() + { + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsXBLBinding"); + if (mRefCnt == 0) { + mRefCnt = 1; + delete this; + return 0; + } + return mRefCnt; + } NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding) @@ -156,6 +172,7 @@ public: // MEMBER VARIABLES protected: + nsAutoRefCnt mRefCnt; nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. nsRefPtr mNextBinding; // Strong. The derived binding owns the base class bindings. diff --git a/content/xbl/src/nsXBLInsertionPoint.cpp b/content/xbl/src/nsXBLInsertionPoint.cpp index d3d0dc582fa8..62e703195086 100644 --- a/content/xbl/src/nsXBLInsertionPoint.cpp +++ b/content/xbl/src/nsXBLInsertionPoint.cpp @@ -57,6 +57,19 @@ nsXBLInsertionPoint::~nsXBLInsertionPoint() } } +nsrefcnt +nsXBLInsertionPoint::Release() +{ + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPoint"); + if (mRefCnt == 0) { + mRefCnt = 1; + delete this; + return 0; + } + return mRefCnt; +} + NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) diff --git a/content/xbl/src/nsXBLInsertionPoint.h b/content/xbl/src/nsXBLInsertionPoint.h index 5ec9239bd3f3..c1f05045a4df 100644 --- a/content/xbl/src/nsXBLInsertionPoint.h +++ b/content/xbl/src/nsXBLInsertionPoint.h @@ -50,7 +50,15 @@ public: nsXBLInsertionPoint(nsIContent* aParentElement, PRUint32 aIndex, nsIContent* aDefContent); ~nsXBLInsertionPoint(); - NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPoint) + nsrefcnt AddRef() + { + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPoint", + sizeof(nsXBLInsertionPoint)); + return mRefCnt; + } + + nsrefcnt Release(); NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint) @@ -82,6 +90,7 @@ public: void UnbindDefaultContent(); protected: + nsAutoRefCnt mRefCnt; nsIContent* mParentElement; // This ref is weak. The parent of the element. PRInt32 mIndex; // The index of this insertion point. -1 is a pseudo-point. nsCOMArray mElements; // An array of elements present at the insertion point. diff --git a/content/xbl/src/nsXBLPrototypeBinding.cpp b/content/xbl/src/nsXBLPrototypeBinding.cpp index 4f417c8e1c60..8b6e97d2b036 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -207,12 +207,27 @@ public: nsXBLInsertionPointEntry::ReleasePool(); } - NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPointEntry) + nsrefcnt AddRef() { + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPointEntry", sizeof(nsXBLInsertionPointEntry)); + return mRefCnt; + } + + nsrefcnt Release() { + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPointEntry"); + if (mRefCnt == 0) { + Destroy(this); + return 0; + } + return mRefCnt; + } protected: nsCOMPtr mInsertionParent; nsCOMPtr mDefaultContent; PRUint32 mInsertionIndex; + nsAutoRefCnt mRefCnt; nsXBLInsertionPointEntry(nsIContent* aParent) : mInsertionParent(aParent), diff --git a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp index 2ab7c3f11795..daf934456161 100644 --- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp @@ -404,12 +404,14 @@ public: txCompileObserver(txMozillaXSLTProcessor* aProcessor, nsILoadGroup* aLoadGroup); - TX_DECL_ACOMPILEOBSERVER - NS_INLINE_DECL_REFCOUNTING(txCompileObserver) + TX_DECL_ACOMPILEOBSERVER; nsresult startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsIPrincipal* aSourcePrincipal); +protected: + nsAutoRefCnt mRefCnt; + private: nsRefPtr mProcessor; nsCOMPtr mLoadGroup; @@ -427,6 +429,23 @@ txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor, { } +nsrefcnt +txCompileObserver::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txCompileObserver::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + nsresult txCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -639,11 +658,11 @@ class txSyncCompileObserver : public txACompileObserver public: txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor); - TX_DECL_ACOMPILEOBSERVER - NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver) + TX_DECL_ACOMPILEOBSERVER; protected: nsRefPtr mProcessor; + nsAutoRefCnt mRefCnt; }; txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) @@ -651,6 +670,23 @@ txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) { } +nsrefcnt +txSyncCompileObserver::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txSyncCompileObserver::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + nsresult txSyncCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, diff --git a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp index f68ad544ccad..11347fbbfd06 100644 --- a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp @@ -64,8 +64,7 @@ class txDriver : public txACompileObserver const XML_Char *aSystemId, const XML_Char *aPublicId); - TX_DECL_ACOMPILEOBSERVER - NS_INLINE_DECL_REFCOUNTING(txDriver) + TX_DECL_ACOMPILEOBSERVER; nsRefPtr mCompiler; protected: @@ -74,6 +73,7 @@ class txDriver : public txACompileObserver // keep track of the nsresult returned by the handlers, expat forgets them nsresult mRV; XML_Parser mExpatParser; + nsAutoRefCnt mRefCnt; }; nsresult @@ -338,6 +338,23 @@ txDriver::createErrorString() * txACompileObserver implementation */ +nsrefcnt +txDriver::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +txDriver::Release() +{ + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + void txDriver::onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, const PRUnichar *aErrorText, const PRUnichar *aParam) diff --git a/content/xslt/src/xslt/txStylesheet.h b/content/xslt/src/xslt/txStylesheet.h index cd159e8f7306..5f6228f1fbe9 100644 --- a/content/xslt/src/xslt/txStylesheet.h +++ b/content/xslt/src/xslt/txStylesheet.h @@ -44,7 +44,6 @@ #include "txList.h" #include "txXSLTPatterns.h" #include "nsTPtrArray.h" -#include "nsISupportsImpl.h" class txInstruction; class txToplevelItem; @@ -68,8 +67,20 @@ public: txStylesheet(); ~txStylesheet(); nsresult init(); - - NS_INLINE_DECL_REFCOUNTING(txStylesheet) + + nsrefcnt AddRef() + { + return ++mRefCnt; + } + nsrefcnt Release() + { + if (--mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; + } txInstruction* findTemplate(const txXPathNode& aNode, const txExpandedName& aMode, @@ -148,6 +159,9 @@ private: nsTPtrArray& aFrameStripSpaceTests); nsresult addAttributeSet(txAttributeSetItem* aAttributeSetItem); + // Refcount + nsAutoRefCnt mRefCnt; + // List of ImportFrames txList mImportFrames; diff --git a/content/xslt/src/xslt/txStylesheetCompiler.cpp b/content/xslt/src/xslt/txStylesheetCompiler.cpp index d0050683fd0b..759c5cb4306d 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStylesheetCompiler.cpp @@ -69,6 +69,27 @@ txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI, mStatus = init(aStylesheetURI, aStylesheet, aInsertPosition); } +nsrefcnt +txStylesheetCompiler::AddRef() +{ + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "txStylesheetCompiler", sizeof(*this)); + return mRefCnt; +} + +nsrefcnt +txStylesheetCompiler::Release() +{ + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "txStylesheetCompiler"); + if (mRefCnt == 0) { + mRefCnt = 1; //stabilize + delete this; + return 0; + } + return mRefCnt; +} + void txStylesheetCompiler::setBaseURI(const nsString& aBaseURI) { diff --git a/content/xslt/src/xslt/txStylesheetCompiler.h b/content/xslt/src/xslt/txStylesheetCompiler.h index 4d71484af266..fc23fb4d3d89 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.h +++ b/content/xslt/src/xslt/txStylesheetCompiler.h @@ -77,8 +77,8 @@ public: class txACompileObserver { public: - virtual void AddRef() = 0; - virtual void Release() = 0; + virtual nsrefcnt AddRef() = 0; + virtual nsrefcnt Release() = 0; virtual nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -90,11 +90,13 @@ public: }; #define TX_DECL_ACOMPILEOBSERVER \ + nsrefcnt AddRef(); \ + nsrefcnt Release(); \ nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, \ txStylesheetCompiler* aCompiler); \ void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, \ const PRUnichar *aErrorText = nsnull, \ - const PRUnichar *aParam = nsnull); + const PRUnichar *aParam = nsnull) class txStylesheetCompilerState : public txIParseContext { @@ -213,6 +215,8 @@ public: txStylesheet* aStylesheet, txListIterator* aInsertPosition, txACompileObserver* aObserver); + virtual nsrefcnt AddRef(); + virtual nsrefcnt Release(); void setBaseURI(const nsString& aBaseURI); @@ -231,8 +235,12 @@ public: txStylesheet* getStylesheet(); - TX_DECL_ACOMPILEOBSERVER - NS_INLINE_DECL_REFCOUNTING(txStylesheetCompiler) + // txACompileObserver + nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, + txStylesheetCompiler* aCompiler); + void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, + const PRUnichar *aErrorText = nsnull, + const PRUnichar *aParam = nsnull); private: nsresult startElementInternal(PRInt32 aNamespaceID, nsIAtom* aLocalName, @@ -245,6 +253,7 @@ private: nsresult ensureNewElementContext(); nsresult maybeDoneCompiling(); + nsAutoRefCnt mRefCnt; nsString mCharacters; nsresult mStatus; }; diff --git a/content/xul/templates/src/nsRDFBinding.h b/content/xul/templates/src/nsRDFBinding.h index 82ad20068ddf..2a8ab79973fc 100644 --- a/content/xul/templates/src/nsRDFBinding.h +++ b/content/xul/templates/src/nsRDFBinding.h @@ -40,7 +40,6 @@ #include "nsAutoPtr.h" #include "nsIAtom.h" #include "nsIRDFResource.h" -#include "nsISupportsImpl.h" class nsXULTemplateResultRDF; class nsBindingValues; @@ -96,6 +95,9 @@ class RDFBindingSet { protected: + // results hold a reference to a binding set in their nsBindingValues fields + PRInt32 mRefCnt; + // the number of bindings PRInt32 mCount; @@ -105,7 +107,8 @@ protected: public: RDFBindingSet() - : mCount(0), + : mRefCnt(0), + mCount(0), mFirst(nsnull) { MOZ_COUNT_CTOR(RDFBindingSet); @@ -113,7 +116,19 @@ public: ~RDFBindingSet(); - NS_INLINE_DECL_REFCOUNTING(RDFBindingSet) + PRInt32 AddRef() { + mRefCnt++; + NS_LOG_ADDREF(this, mRefCnt, "RDFBindingSet", sizeof(*this)); + return mRefCnt; + } + + PRInt32 Release() + { + PRInt32 refcnt = --mRefCnt; + NS_LOG_RELEASE(this, refcnt, "RDFBindingSet"); + if (refcnt == 0) delete this; + return refcnt; + } PRInt32 Count() const { return mCount; } From d7be484ef19a15b72390da6f3644545b2ac5b866 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 09:37:59 -0700 Subject: [PATCH 26/69] Backed out changeset afcaf3670c21 (Bug 551298) due to Linux debug mochitest-5 orange --- layout/style/nsCSSValue.cpp | 6 ++-- layout/style/nsCSSValue.h | 65 ++++++++++++++++++++++++++++++---- layout/style/nsStyleStruct.cpp | 21 +++++++++++ layout/style/nsStyleStruct.h | 42 +++++++++++++++++++--- 4 files changed, 120 insertions(+), 14 deletions(-) diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index f2a940779659..548a969c429c 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -506,7 +506,8 @@ nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer, : mURI(aURI), mString(aString), mReferrer(aReferrer), - mOriginPrincipal(aOriginPrincipal) + mOriginPrincipal(aOriginPrincipal), + mRefCnt(0) { NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal"); mString->AddRef(); @@ -592,6 +593,7 @@ nsCSSValueGradient::nsCSSValueGradient(PRBool aIsRadial, mBgPosY(eCSSUnit_None), mAngle(eCSSUnit_None), mRadialShape(eCSSUnit_None), - mRadialSize(eCSSUnit_None) + mRadialSize(eCSSUnit_None), + mRefCnt(0) { } diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 4404beef5087..35db8b4d3003 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -51,7 +51,6 @@ #include "nsCRTGlue.h" #include "nsStringBuffer.h" #include "nsTArray.h" -#include "nsISupportsImpl.h" class imgIRequest; class nsIDocument; @@ -380,9 +379,26 @@ public: nsCOMPtr mReferrer; nsCOMPtr mOriginPrincipal; - NS_INLINE_DECL_REFCOUNTING(URL) - + void AddRef() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); + return; + } + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::URL", sizeof(*this)); + } + void Release() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); + return; + } + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::URL"); + if (mRefCnt == 0) + delete this; + } protected: + nsrefcnt mRefCnt; // not to be implemented URL(const URL& aOther); @@ -404,7 +420,25 @@ public: // Override AddRef and Release to not only log ourselves correctly, but // also so that we delete correctly without a virtual destructor - NS_INLINE_DECL_REFCOUNTING(Image) + void AddRef() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); + return; + } + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Image", sizeof(*this)); + } + + void Release() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); + return; + } + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Image"); + if (mRefCnt == 0) + delete this; + } }; private: @@ -495,9 +529,28 @@ struct nsCSSValueGradient { return !(*this == aOther); } - NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient) + void AddRef() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); + return; + } + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Gradient", sizeof(*this)); + } + void Release() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); + return; + } + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Gradient"); + if (mRefCnt == 0) + delete this; + } private: + nsrefcnt mRefCnt; + // not to be implemented nsCSSValueGradient(const nsCSSValueGradient& aOther); nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther); @@ -535,8 +588,6 @@ struct nsCSSValue::Array { return PR_TRUE; } - // XXXdholbert This uses a 16-bit ref count to save space. Should we use - // a variant of NS_INLINE_DECL_REFCOUNTING that takes a type as an argument? void AddRef() { if (mRefCnt == PR_UINT16_MAX) { NS_WARNING("refcount overflow, leaking nsCSSValue::Array"); diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 4eeb50f86ae2..1368487368d5 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1317,6 +1317,7 @@ nsStyleGradient::nsStyleGradient(void) : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR) , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) , mRepeating(PR_FALSE) + , mRefCnt(0) { } @@ -2317,6 +2318,26 @@ nsChangeHint nsStyleTextReset::MaxDifference() } #endif +// -------------------- +// nsCSSShadowArray +// nsCSSShadowItem +// + +nsrefcnt +nsCSSShadowArray::Release() +{ + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking object"); + return mRefCnt; + } + mRefCnt--; + if (mRefCnt == 0) { + delete this; + return 0; + } + return mRefCnt; +} + // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though. // XXXbz can this not return a more specific hint? If that's ever diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 77f8e7e0910e..46be0ae3db1b 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -163,14 +163,38 @@ public: // stops are in the order specified in the stylesheet nsTArray mStops; + nsrefcnt AddRef() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsStyleGradient"); + return mRefCnt; + } + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsStyleGradient", sizeof(*this)); + return mRefCnt; + } + + nsrefcnt Release() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking nsStyleGradient"); + return mRefCnt; + } + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsStyleGradient"); + if (mRefCnt == 0) { + delete this; + return 0; + } + return mRefCnt; + } + PRBool operator==(const nsStyleGradient& aOther) const; PRBool operator!=(const nsStyleGradient& aOther) const { return !(*this == aOther); }; - NS_INLINE_DECL_REFCOUNTING(nsStyleGradient) - private: + nsrefcnt mRefCnt; + ~nsStyleGradient() {} // Not to be implemented @@ -647,7 +671,7 @@ class nsCSSShadowArray { } nsCSSShadowArray(PRUint32 aArrayLen) : - mLength(aArrayLen) + mLength(aArrayLen), mRefCnt(0) { MOZ_COUNT_CTOR(nsCSSShadowArray); for (PRUint32 i = 1; i < mLength; ++i) { @@ -663,6 +687,15 @@ class nsCSSShadowArray { } } + nsrefcnt AddRef() { + if (mRefCnt == PR_UINT32_MAX) { + NS_WARNING("refcount overflow, leaking object"); + return mRefCnt; + } + return ++mRefCnt; + } + nsrefcnt Release(); + PRUint32 Length() const { return mLength; } nsCSSShadowItem* ShadowAt(PRUint32 i) { NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!"); @@ -673,10 +706,9 @@ class nsCSSShadowArray { return &mArray[i]; } - NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray) - private: PRUint32 mLength; + PRUint32 mRefCnt; nsCSSShadowItem mArray[1]; // This MUST be the last item }; From 605900c19fefba0517a533826fd2d34c4ce19525 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 09:38:53 -0700 Subject: [PATCH 27/69] Backed out changeset 29bc09de2f77 (Bug 551298) due to Linux debug mochitest-5 orange --- content/svg/content/src/nsSVGMatrix.cpp | 1 - content/svg/content/src/nsSVGMatrix.h | 1 - gfx/layers/Layers.h | 6 ++---- gfx/thebes/public/gfxASurface.h | 1 - gfx/thebes/public/gfxContext.h | 3 +-- gfx/thebes/public/gfxFont.h | 7 +++---- gfx/thebes/public/gfxGdkNativeRenderer.h | 1 - gfx/thebes/public/gfxPath.h | 3 +-- gfx/thebes/public/gfxPattern.h | 4 +--- gfx/thebes/public/gfxRect.h | 1 - gfx/thebes/public/gfxTypes.h | 10 ++++++++++ gfx/thebes/public/gfxUserFontSet.h | 3 +-- gfx/thebes/src/gfxFontconfigUtils.h | 3 +-- gfx/thebes/src/gfxPangoFonts.cpp | 2 +- layout/printing/nsPrintData.h | 1 - 15 files changed, 21 insertions(+), 26 deletions(-) diff --git a/content/svg/content/src/nsSVGMatrix.cpp b/content/svg/content/src/nsSVGMatrix.cpp index c7e7d75612d1..ee155e5aa7ac 100644 --- a/content/svg/content/src/nsSVGMatrix.cpp +++ b/content/svg/content/src/nsSVGMatrix.cpp @@ -41,7 +41,6 @@ #include "nsSVGValue.h" #include #include "nsContentUtils.h" -#include "nsISupportsImpl.h" const double radPerDegree = 2.0*3.1415926535 / 360.0; diff --git a/content/svg/content/src/nsSVGMatrix.h b/content/svg/content/src/nsSVGMatrix.h index c95002031716..6d1f5d2f2612 100644 --- a/content/svg/content/src/nsSVGMatrix.h +++ b/content/svg/content/src/nsSVGMatrix.h @@ -71,7 +71,6 @@ #include "nsIDOMSVGMatrix.h" #include "gfxMatrix.h" -#include "nsAutoPtr.h" nsresult NS_NewSVGMatrix(nsIDOMSVGMatrix** result, diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index b5d674be34b4..a3759ceeebde 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -42,8 +42,6 @@ #include "nsRegion.h" #include "nsPoint.h" #include "nsRect.h" -#include "nsISupportsImpl.h" -#include "nsAutoPtr.h" #include "gfx3DMatrix.h" class gfxContext; @@ -108,7 +106,7 @@ class ImageContainer; * root layer, and each container layer holds a reference to its children. */ class THEBES_API LayerManager { - NS_INLINE_DECL_REFCOUNTING(LayerManager) + THEBES_INLINE_DECL_REFCOUNTING(LayerManager) public: enum LayersBackend { @@ -183,7 +181,7 @@ public: * surface. */ class THEBES_API Layer { - NS_INLINE_DECL_REFCOUNTING(Layer) + THEBES_INLINE_DECL_REFCOUNTING(Layer) public: virtual ~Layer() {} diff --git a/gfx/thebes/public/gfxASurface.h b/gfx/thebes/public/gfxASurface.h index c84f4ea14a60..4c2143d646aa 100644 --- a/gfx/thebes/public/gfxASurface.h +++ b/gfx/thebes/public/gfxASurface.h @@ -40,7 +40,6 @@ #include "gfxTypes.h" #include "gfxRect.h" -#include "nsAutoPtr.h" typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_user_data_key cairo_user_data_key_t; diff --git a/gfx/thebes/public/gfxContext.h b/gfx/thebes/public/gfxContext.h index f9e95d2dfeb8..23f2f068db8c 100644 --- a/gfx/thebes/public/gfxContext.h +++ b/gfx/thebes/public/gfxContext.h @@ -48,7 +48,6 @@ #include "gfxMatrix.h" #include "gfxPattern.h" #include "gfxPath.h" -#include "nsISupportsImpl.h" typedef struct _cairo cairo_t; @@ -67,7 +66,7 @@ typedef struct _cairo cairo_t; * as opposed to app units. */ class THEBES_API gfxContext { - NS_INLINE_DECL_REFCOUNTING(gfxContext) + THEBES_INLINE_DECL_REFCOUNTING(gfxContext) public: /** diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index f808c32ce9f6..370654c53e02 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -55,7 +55,6 @@ #include "gfxFontConstants.h" #include "gfxPlatform.h" #include "nsIAtom.h" -#include "nsISupportsImpl.h" #ifdef DEBUG #include @@ -161,7 +160,7 @@ struct THEBES_API gfxFontStyle { class gfxFontEntry { public: - NS_INLINE_DECL_REFCOUNTING(gfxFontEntry) + THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry) gfxFontEntry(const nsAString& aName, gfxFontFamily *aFamily = nsnull, PRBool aIsStandardFace = PR_FALSE) : @@ -290,7 +289,7 @@ struct FontSearch { class gfxFontFamily { public: - NS_INLINE_DECL_REFCOUNTING(gfxFontFamily) + THEBES_INLINE_DECL_REFCOUNTING(gfxFontFamily) gfxFontFamily(const nsAString& aName) : mName(aName), @@ -956,7 +955,7 @@ protected: }; class THEBES_API gfxTextRunFactory { - NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) + THEBES_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) public: // Flags in the mask 0xFFFF0000 are reserved for textrun clients diff --git a/gfx/thebes/public/gfxGdkNativeRenderer.h b/gfx/thebes/public/gfxGdkNativeRenderer.h index ca5bef4337aa..68cf01570061 100644 --- a/gfx/thebes/public/gfxGdkNativeRenderer.h +++ b/gfx/thebes/public/gfxGdkNativeRenderer.h @@ -39,7 +39,6 @@ #define GFXGDKNATIVERENDER_H_ #include "gfxColor.h" -#include "nsAutoPtr.h" #include class gfxASurface; diff --git a/gfx/thebes/public/gfxPath.h b/gfx/thebes/public/gfxPath.h index 127b81ea4d24..1a5cc2e9f729 100644 --- a/gfx/thebes/public/gfxPath.h +++ b/gfx/thebes/public/gfxPath.h @@ -38,7 +38,6 @@ #define GFX_PATH_H #include "gfxTypes.h" -#include "nsISupportsImpl.h" class gfxContext; struct gfxPoint; @@ -49,7 +48,7 @@ typedef struct cairo_path cairo_path_t; * of a gfxContext. */ class THEBES_API gfxPath { - NS_INLINE_DECL_REFCOUNTING(gfxPath) + THEBES_INLINE_DECL_REFCOUNTING(gfxPath) friend class gfxContext; diff --git a/gfx/thebes/public/gfxPattern.h b/gfx/thebes/public/gfxPattern.h index b378b815c02a..26f67b35f1d2 100644 --- a/gfx/thebes/public/gfxPattern.h +++ b/gfx/thebes/public/gfxPattern.h @@ -42,8 +42,6 @@ #include "gfxColor.h" #include "gfxMatrix.h" -#include "nsISupportsImpl.h" -#include "nsAutoPtr.h" class gfxContext; class gfxASurface; @@ -51,7 +49,7 @@ typedef struct _cairo_pattern cairo_pattern_t; class THEBES_API gfxPattern { - NS_INLINE_DECL_REFCOUNTING(gfxPattern) + THEBES_INLINE_DECL_REFCOUNTING(gfxPattern) public: gfxPattern(cairo_pattern_t *aPattern); diff --git a/gfx/thebes/public/gfxRect.h b/gfx/thebes/public/gfxRect.h index 7da3e1f2678a..c024211aa5bd 100644 --- a/gfx/thebes/public/gfxRect.h +++ b/gfx/thebes/public/gfxRect.h @@ -40,7 +40,6 @@ #include "gfxTypes.h" #include "gfxPoint.h" -#include "nsDebug.h" struct THEBES_API gfxCorner { typedef int Corner; diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index 1e1f0862cb3d..b68c48f1e790 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -90,6 +90,16 @@ enum gfxBreakPriority { eNormalBreak }; +/** + * Define refcounting for Thebes. For now use the stuff from nsISupportsImpl + * even though it forces the functions to be virtual... + */ +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" + +#define THEBES_INLINE_DECL_REFCOUNTING(_class) \ + NS_INLINE_DECL_REFCOUNTING(_class) + #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ nsrefcnt AddRef(void) { \ diff --git a/gfx/thebes/public/gfxUserFontSet.h b/gfx/thebes/public/gfxUserFontSet.h index aece55f5789b..654350c89d8a 100644 --- a/gfx/thebes/public/gfxUserFontSet.h +++ b/gfx/thebes/public/gfxUserFontSet.h @@ -46,7 +46,6 @@ #include "nsCOMPtr.h" #include "nsIURI.h" #include "nsIFile.h" -#include "nsISupportsImpl.h" class nsIURI; class gfxMixedFontFamily; @@ -139,7 +138,7 @@ class THEBES_API gfxUserFontSet { public: - NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet) + THEBES_INLINE_DECL_REFCOUNTING(gfxUserFontSet) gfxUserFontSet(); virtual ~gfxUserFontSet(); diff --git a/gfx/thebes/src/gfxFontconfigUtils.h b/gfx/thebes/src/gfxFontconfigUtils.h index 4943f77b8cda..7dcb6a38758b 100644 --- a/gfx/thebes/src/gfxFontconfigUtils.h +++ b/gfx/thebes/src/gfxFontconfigUtils.h @@ -44,7 +44,6 @@ #include "nsAutoRef.h" #include "nsTArray.h" #include "nsTHashtable.h" -#include "nsISupportsImpl.h" #include @@ -88,7 +87,7 @@ class gfxIgnoreCaseCStringComparator class gfxFontNameList : public nsTArray { public: - NS_INLINE_DECL_REFCOUNTING(gfxFontNameList) + THEBES_INLINE_DECL_REFCOUNTING(gfxFontNameList) PRBool Exists(nsAString& aName); }; diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index 06b1da984218..3069a396e015 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -935,7 +935,7 @@ GetFontGroup(PangoContext *aContext) class gfxFcPangoFontSet { public: - NS_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) + THEBES_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) explicit gfxFcPangoFontSet(FcPattern *aPattern, gfxUserFontSet *aUserFontSet) diff --git a/layout/printing/nsPrintData.h b/layout/printing/nsPrintData.h index 97dfb4f468d8..bd6dbf322e38 100644 --- a/layout/printing/nsPrintData.h +++ b/layout/printing/nsPrintData.h @@ -44,7 +44,6 @@ #include "nsIPrintOptions.h" #include "nsTArray.h" #include "nsCOMArray.h" -#include "nsAutoPtr.h" // Classes class nsPrintObject; From b7634782ea06f5fe6d8f5aa766594606f2cd31b8 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 09:39:50 -0700 Subject: [PATCH 28/69] Backed out changeset e94819033c77 (Bug 551298) due to Linux debug mochitest-5 orange --- xpcom/glue/nsISupportsImpl.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index 69c5ed10b983..f510c8e4ef3f 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -316,13 +316,11 @@ public: public: \ void AddRef(void) { \ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ - NS_ASSERT_OWNINGTHREAD(_class); \ ++mRefCnt; \ NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ } \ void Release(void) { \ NS_PRECONDITION(0 != mRefCnt, "dup release"); \ - NS_ASSERT_OWNINGTHREAD(_class); \ --mRefCnt; \ NS_LOG_RELEASE(this, mRefCnt, #_class); \ if (mRefCnt == 0) { \ @@ -332,7 +330,6 @@ public: \ } \ protected: \ nsAutoRefCnt mRefCnt; \ - NS_DECL_OWNINGTHREAD \ public: /** From 1faa0a4f905c0e1c63eec2dc1c3c5a757f2265f0 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 09:40:30 -0700 Subject: [PATCH 29/69] Backed out changeset fe801c8a2090 (Bug 551298) due to Linux debug mochitest-5 orange --- gfx/thebes/public/gfxTypes.h | 22 +++++++++++++++++++++- xpcom/glue/nsISupportsImpl.h | 29 ----------------------------- xpcom/glue/nsISupportsUtils.h | 6 ++---- 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index b68c48f1e790..cb4dccebffa0 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -98,7 +98,27 @@ enum gfxBreakPriority { #include "nsAutoPtr.h" #define THEBES_INLINE_DECL_REFCOUNTING(_class) \ - NS_INLINE_DECL_REFCOUNTING(_class) +public: \ + nsrefcnt AddRef(void) { \ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + ++mRefCnt; \ + NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ + return mRefCnt; \ + } \ + nsrefcnt Release(void) { \ + NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + --mRefCnt; \ + NS_LOG_RELEASE(this, mRefCnt, #_class); \ + if (mRefCnt == 0) { \ + mRefCnt = 1; /* stabilize */ \ + NS_DELETEXPCOM(this); \ + return 0; \ + } \ + return mRefCnt; \ + } \ +protected: \ + nsAutoRefCnt mRefCnt; \ +public: #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index f510c8e4ef3f..fe0c719e62e9 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -303,35 +303,6 @@ public: */ #define NS_INIT_ISUPPORTS() ((void)0) -/** - * Use this macro to declare and implement the AddRef & Release methods for a - * given non-XPCOM _class. - * - * The implementations here should match NS_IMPL_ADDREF/NS_IMPL_RELEASE, minus - * the nsrefcnt return-value and the NS_ASSERT_OWNINGTHREAD() call. - * - * @param _class The name of the class implementing the method - */ -#define NS_INLINE_DECL_REFCOUNTING(_class) \ -public: \ - void AddRef(void) { \ - NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ - ++mRefCnt; \ - NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ - } \ - void Release(void) { \ - NS_PRECONDITION(0 != mRefCnt, "dup release"); \ - --mRefCnt; \ - NS_LOG_RELEASE(this, mRefCnt, #_class); \ - if (mRefCnt == 0) { \ - mRefCnt = 1; /* stabilize */ \ - NS_DELETEXPCOM(this); \ - } \ - } \ -protected: \ - nsAutoRefCnt mRefCnt; \ -public: - /** * Use this macro to implement the AddRef method for a given _class * @param _class The name of the class implementing the method diff --git a/xpcom/glue/nsISupportsUtils.h b/xpcom/glue/nsISupportsUtils.h index 7bfb89494650..e20aa5e3ece8 100644 --- a/xpcom/glue/nsISupportsUtils.h +++ b/xpcom/glue/nsISupportsUtils.h @@ -108,12 +108,10 @@ extern "C++" { // yet still denies you the ability to |AddRef()| an |nsCOMPtr|. template inline -void +nsrefcnt ns_if_addref( T expr ) { - if (expr) { - expr->AddRef(); - } + return expr ? expr->AddRef() : 0; } } /* extern "C++" */ From 53b4755d48d9fdc5cd26f8a0f5dd2abc545cd25e Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Thu, 1 Apr 2010 22:10:39 -0700 Subject: [PATCH 30/69] When backing out bug 554692, these files should have also been removed --- dom/src/geolocation/MaemoLocationProvider.cpp | 452 ------------------ dom/src/geolocation/MaemoLocationProvider.h | 121 ----- 2 files changed, 573 deletions(-) delete mode 100644 dom/src/geolocation/MaemoLocationProvider.cpp delete mode 100644 dom/src/geolocation/MaemoLocationProvider.h diff --git a/dom/src/geolocation/MaemoLocationProvider.cpp b/dom/src/geolocation/MaemoLocationProvider.cpp deleted file mode 100644 index 626d4f15d470..000000000000 --- a/dom/src/geolocation/MaemoLocationProvider.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Geolocation. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Oleg Romashin (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include -#include -#include "MaemoLocationProvider.h" -#include "nsIClassInfo.h" -#include "nsDOMClassInfoID.h" -#include "nsIDOMClassInfo.h" -#include "nsIPrefService.h" -#include "nsIPrefBranch.h" -#include "nsIServiceManager.h" -#include "nsServiceManagerUtils.h" - -//////////////////////////////////////////////////// -// nsGeoPositionCoords -//////////////////////////////////////////////////// - -class nsGeoPositionCoords : public nsIDOMGeoPositionCoords -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMGEOPOSITIONCOORDS - - nsGeoPositionCoords(double aLat, double aLong, double aAlt, double aHError, - double aVError, double aHeading, double aSpeed) : - mLat(aLat), mLong(aLong), mAlt(aAlt), mHError(aHError), - mVError(aVError), mHeading(aHeading), mSpeed(aSpeed) { }; -private: - ~nsGeoPositionCoords() { } - double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed; -}; - -NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords) -NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords) -NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords) -NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionCoords) -NS_INTERFACE_MAP_END - -NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionCoords) -NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionCoords) - -NS_IMETHODIMP -nsGeoPositionCoords::GetLatitude(double *aLatitude) -{ - *aLatitude = mLat; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionCoords::GetLongitude(double *aLongitude) -{ - *aLongitude = mLong; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionCoords::GetAltitude(double *aAltitude) -{ - *aAltitude = mAlt; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionCoords::GetAccuracy(double *aAccuracy) -{ - *aAccuracy = mHError; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionCoords::GetAltitudeAccuracy(double *aAltitudeAccuracy) -{ - *aAltitudeAccuracy = mVError; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionCoords::GetHeading(double *aHeading) -{ - *aHeading = mHeading; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPositionCoords::GetSpeed(double *aSpeed) -{ - *aSpeed = mSpeed; - return NS_OK; -} - -//////////////////////////////////////////////////// -// nsGeoPosition -//////////////////////////////////////////////////// - -class nsGeoPosition : public nsIDOMGeoPosition -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMGEOPOSITION - - nsGeoPosition(double aLat, double aLong, double aAlt, double aHError, - double aVError, double aHeading, double aSpeed, - long long aTimestamp): mTimestamp(aTimestamp) - { - mCoords = new nsGeoPositionCoords(aLat, aLong, aAlt, aHError, - aVError, aHeading, aSpeed); - NS_ASSERTION(mCoords, "null mCoords in nsGeoPosition"); - }; - -private: - ~nsGeoPosition() {} - long long mTimestamp; - nsRefPtr mCoords; -}; - -NS_INTERFACE_MAP_BEGIN(nsGeoPosition) -NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition) -NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition) -NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPosition) -NS_INTERFACE_MAP_END - -NS_IMPL_THREADSAFE_ADDREF(nsGeoPosition) -NS_IMPL_THREADSAFE_RELEASE(nsGeoPosition) - -NS_IMETHODIMP -nsGeoPosition::GetTimestamp(DOMTimeStamp* aTimestamp) -{ - *aTimestamp = mTimestamp; - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords) -{ - NS_IF_ADDREF(*aCoords = mCoords); - return NS_OK; -} - -NS_IMETHODIMP -nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress) -{ - *aAddress = nsnull; - return NS_OK; -} - -NS_IMPL_ISUPPORTS2(MaemoLocationProvider, nsIGeolocationProvider, nsITimerCallback) - -MaemoLocationProvider::MaemoLocationProvider() : - mLocationChanged(0), - mControlError(0), - mDeviceDisconnected(0), - mControlStopped(0), - mHasSeenLocation(PR_FALSE), - mHasGPS(PR_TRUE), - mGPSControl(nsnull), - mGPSDevice(nsnull), - mIgnoreMinorChanges(PR_FALSE), - mPrevLat(0.0), - mPrevLong(0.0), - mInterval(LOCATION_INTERVAL_5S), - mIgnoreBigHErr(PR_TRUE), - mMaxHErr(1000), - mIgnoreBigVErr(PR_TRUE), - mMaxVErr(100) -{ -} - -MaemoLocationProvider::~MaemoLocationProvider() -{ -} - -void MaemoLocationProvider::DeviceDisconnected(LocationGPSDevice* device, void* self) -{ -} - -void MaemoLocationProvider::ControlStopped(LocationGPSDControl* device, void* self) -{ - MaemoLocationProvider* provider = static_cast(self); - provider->StartControl(); -} - -void MaemoLocationProvider::ControlError(LocationGPSDControl* control, void* self) -{ -} - -void MaemoLocationProvider::LocationChanged(LocationGPSDevice* device, void* self) -{ - if (!device || !device->fix) - return; - - guint32 &fields = device->fix->fields; - if (!(fields & LOCATION_GPS_DEVICE_LATLONG_SET)) - return; - - if (!(device->fix->eph && !isnan(device->fix->eph))) - return; - - MaemoLocationProvider* provider = static_cast(self); - NS_ENSURE_TRUE(provider, ); - provider->LocationUpdate(device); -} - -nsresult -MaemoLocationProvider::LocationUpdate(LocationGPSDevice* aDev) -{ - double hErr = aDev->fix->eph/100; - if (mIgnoreBigHErr && hErr > (double)mMaxHErr) - hErr = (double)mMaxHErr; - - double vErr = aDev->fix->epv/2; - if (mIgnoreBigVErr && vErr > (double)mMaxVErr) - vErr = (double)mMaxVErr; - - double altitude = 0, speed = 0, track = 0; - if (aDev->fix->epv && !isnan(aDev->fix->epv)) - altitude = aDev->fix->altitude; - if (aDev->fix->eps && !isnan(aDev->fix->eps)) - speed = aDev->fix->speed; - if (aDev->fix->epd && !isnan(aDev->fix->epd)) - track = aDev->fix->track; - -#ifdef DEBUG - double dist = location_distance_between(mPrevLat, mPrevLong, aDev->fix->latitude, aDev->fix->longitude)*1000; - fprintf(stderr, "dist:%.9f, Lat: %.6f, Long:%.6f, HErr:%g, Alt:%.6f, VErr:%g, dir:%g[%g], sp:%g[%g]\n", - dist, aDev->fix->latitude, aDev->fix->longitude, - hErr, altitude, - aDev->fix->epv/2, track, aDev->fix->epd, - speed, aDev->fix->eps); - mPrevLat = aDev->fix->latitude; - mPrevLong = aDev->fix->longitude; -#endif - - nsRefPtr somewhere = new nsGeoPosition(aDev->fix->latitude, - aDev->fix->longitude, - altitude, - hErr, - vErr, - track, - speed, - PR_Now()); - Update(somewhere); - - return NS_OK; -} - -NS_IMETHODIMP -MaemoLocationProvider::Notify(nsITimer* aTimer) -{ - LocationChanged(mGPSDevice, this); - return NS_OK; -} - -nsresult -MaemoLocationProvider::StartControl() -{ - if (mGPSControl) - return NS_OK; - - mGPSControl = location_gpsd_control_get_default(); - NS_ENSURE_TRUE(mGPSControl, NS_ERROR_FAILURE); - - g_object_set(G_OBJECT(mGPSControl), - "preferred-interval", mInterval, - "preferred-method", LOCATION_METHOD_USER_SELECTED, - NULL); - - mControlError = g_signal_connect(mGPSControl, "error", - G_CALLBACK(ControlError), this); - - mControlStopped = g_signal_connect(mGPSControl, "gpsd_stopped", - G_CALLBACK(ControlStopped), this); - - location_gpsd_control_start(mGPSControl); - return NS_OK; -} - -nsresult -MaemoLocationProvider::StartDevice() -{ - if (mGPSDevice) - return NS_OK; - - mGPSDevice = (LocationGPSDevice*)g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL); - NS_ENSURE_TRUE(mGPSDevice, NS_ERROR_FAILURE); - - mLocationChanged = g_signal_connect(mGPSDevice, "changed", - G_CALLBACK(LocationChanged), this); - - mDeviceDisconnected = g_signal_connect(mGPSDevice, "disconnected", - G_CALLBACK(DeviceDisconnected), this); - return NS_OK; -} - -NS_IMETHODIMP MaemoLocationProvider::Startup() -{ - nsresult rv(NS_OK); - - PRInt32 freqVal = 5; - nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); - if (prefs) { - rv = prefs->GetIntPref("geo.location_update_freq", &freqVal); - switch (freqVal) { - case 0: - mInterval = LOCATION_INTERVAL_DEFAULT; - break; - case 1: - mInterval = LOCATION_INTERVAL_1S; - break; - case 2: - mInterval = LOCATION_INTERVAL_2S; - break; - case 5: - mInterval = LOCATION_INTERVAL_5S; - break; - case 10: - mInterval = LOCATION_INTERVAL_10S; - break; - case 20: - mInterval = LOCATION_INTERVAL_20S; - break; - case 30: - mInterval = LOCATION_INTERVAL_30S; - break; - case 60: - mInterval = LOCATION_INTERVAL_60S; - break; - case 120: - mInterval = LOCATION_INTERVAL_120S; - break; - default: - mInterval = LOCATION_INTERVAL_DEFAULT; - break; - } - } - - rv = StartControl(); - NS_ENSURE_SUCCESS(rv, rv); - - rv = StartDevice(); - NS_ENSURE_SUCCESS(rv, rv); - - if (prefs) - prefs->GetBoolPref("geo.herror.ignore.big", &mIgnoreBigHErr); - - if (mIgnoreBigHErr) - prefs->GetIntPref("geo.herror.max.value", &mMaxHErr); - - if (prefs) - prefs->GetBoolPref("geo.verror.ignore.big", &mIgnoreBigVErr); - - if (mIgnoreBigVErr) - prefs->GetIntPref("geo.verror.max.value", &mMaxVErr); - - if (mUpdateTimer) - return NS_OK; - - PRInt32 update = 0; //0 second no timer created - if (prefs) - prefs->GetIntPref("geo.default.update", &update); - - if (!update) - return NS_OK; - - mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); - - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; - - if (update) - mUpdateTimer->InitWithCallback(this, update, nsITimer::TYPE_REPEATING_SLACK); - - return NS_OK; -} - -NS_IMETHODIMP MaemoLocationProvider::Watch(nsIGeolocationUpdate *callback) -{ - if (mCallback) - return NS_OK; - - mCallback = callback; - return NS_OK; -} - -NS_IMETHODIMP MaemoLocationProvider::Shutdown() -{ - if (mUpdateTimer) - mUpdateTimer->Cancel(); - - g_signal_handler_disconnect(mGPSDevice, mLocationChanged); - g_signal_handler_disconnect(mGPSDevice, mDeviceDisconnected); - - g_signal_handler_disconnect(mGPSDevice, mControlError); - g_signal_handler_disconnect(mGPSDevice, mControlStopped); - - mHasSeenLocation = PR_FALSE; - mCallback = nsnull; - - if (mGPSControl) { - location_gpsd_control_stop(mGPSControl); - g_object_unref(mGPSControl); - mGPSControl = nsnull; - } - if (mGPSDevice) { - g_object_unref(mGPSDevice); - mGPSDevice = nsnull; - } - - return NS_OK; -} - -void MaemoLocationProvider::Update(nsIDOMGeoPosition* aPosition) -{ - mHasSeenLocation = PR_TRUE; - if (mCallback) - mCallback->Update(aPosition); -} - diff --git a/dom/src/geolocation/MaemoLocationProvider.h b/dom/src/geolocation/MaemoLocationProvider.h deleted file mode 100644 index 2df739b6454c..000000000000 --- a/dom/src/geolocation/MaemoLocationProvider.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Geolocation. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner (Original Author) - * Nino D'Aversa - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsCOMPtr.h" -#include "nsAutoPtr.h" -#include "nsCOMArray.h" -#include "nsTArray.h" -#include "nsITimer.h" -#include "nsIObserver.h" -#include "nsIURI.h" - -#include "nsWeakPtr.h" -#include "nsCycleCollectionParticipant.h" - -#include "nsIDOMGeoGeolocation.h" -#include "nsIDOMGeoPosition.h" -#include "nsIDOMGeoPositionError.h" -#include "nsIDOMGeoPositionCallback.h" -#include "nsIDOMGeoPositionErrorCallback.h" -#include "nsIDOMGeoPositionOptions.h" -#include "nsIDOMNavigatorGeolocation.h" -#include "nsIDOMGeoPositionCoords.h" - -#include "nsPIDOMWindow.h" - -#include "nsIGeolocationProvider.h" - - -extern "C" -{ -#include -#include -#include -#include -} - -class MaemoLocationProvider : public nsIGeolocationProvider, - public nsITimerCallback - -{ - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIGEOLOCATIONPROVIDER - NS_DECL_NSITIMERCALLBACK - - MaemoLocationProvider(); - - void Update(nsIDOMGeoPosition* aPosition); - - private: - ~MaemoLocationProvider(); - - nsresult StartControl(); - nsresult StartDevice(); - nsresult LocationUpdate(LocationGPSDevice* aDev); - - static void DeviceDisconnected(LocationGPSDevice* device, void* self); - static void ControlStopped(LocationGPSDControl* device, void* self); - static void ControlError(LocationGPSDControl* control, void* self); - static void LocationChanged(LocationGPSDevice* device, void* self); - - gulong mLocationChanged; - gulong mControlError; - gulong mDeviceDisconnected; - gulong mControlStopped; - - nsCOMPtr mCallback; - PRPackedBool mHasSeenLocation; - PRPackedBool mHasGPS; - - nsCOMPtr mUpdateTimer; - LocationGPSDControl* mGPSControl; - LocationGPSDevice* mGPSDevice; - - PRBool mIgnoreMinorChanges; - - double mPrevLat; - double mPrevLong; - - LocationGPSDControlInterval mInterval; - PRBool mIgnoreBigHErr; - PRInt32 mMaxHErr; - PRBool mIgnoreBigVErr; - PRInt32 mMaxVErr; - -}; From 53f422a3931923e780f88ab0baff6da583a17480 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 1 Apr 2010 10:47:37 -0700 Subject: [PATCH 31/69] Bug 554790 - Implement variadic ctypes functions. r=dwitte --- js/ctypes/CTypes.cpp | 231 ++++++++++++++++++----- js/ctypes/CTypes.h | 26 ++- js/ctypes/ctypes.jsm | 7 +- js/ctypes/tests/jsctypes-test.cpp | 65 +++++++ js/ctypes/tests/jsctypes-test.h | 8 +- js/ctypes/tests/unit/test_jsctypes.js.in | 96 +++++++++- 6 files changed, 376 insertions(+), 57 deletions(-) diff --git a/js/ctypes/CTypes.cpp b/js/ctypes/CTypes.cpp index 65a2b1e624e3..a1ec2a082ed6 100644 --- a/js/ctypes/CTypes.cpp +++ b/js/ctypes/CTypes.cpp @@ -146,6 +146,8 @@ namespace FunctionType { static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp); + static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval, + jsval* vp); } namespace CClosure { @@ -366,6 +368,7 @@ static JSPropertySpec sFunctionProps[] = { { "argTypes", 0, CTYPESPROP_FLAGS, FunctionType::ArgTypesGetter, NULL }, { "returnType", 0, CTYPESPROP_FLAGS, FunctionType::ReturnTypeGetter, NULL }, { "abi", 0, CTYPESPROP_FLAGS, FunctionType::ABIGetter, NULL }, + { "isVariadic", 0, CTYPESPROP_FLAGS, FunctionType::IsVariadicGetter, NULL }, { 0, 0, 0, NULL, NULL } }; @@ -2017,9 +2020,12 @@ BuildTypeName(JSContext* cx, JSObject* typeObj) for (PRUint32 i = 0; i < fninfo->mArgTypes.Length(); ++i) { JSString* argName = CType::GetName(cx, fninfo->mArgTypes[i]); result.Append(GetString(argName)); - if (i != fninfo->mArgTypes.Length() - 1) + if (i != fninfo->mArgTypes.Length() - 1 || + fninfo->mIsVariadic) result.Append(NS_LITERAL_STRING(", ")); } + if (fninfo->mIsVariadic) + result.Append(NS_LITERAL_STRING("...")); result.Append(')'); // Set 'currentType' to the return type, and let the loop process it. @@ -2110,9 +2116,12 @@ BuildTypeSource(JSContext* cx, JSObject* typeObj, bool makeShort) result.Append(NS_LITERAL_STRING(", [")); for (PRUint32 i = 0; i < fninfo->mArgTypes.Length(); ++i) { result.Append(BuildTypeSource(cx, fninfo->mArgTypes[i], true)); - if (i != fninfo->mArgTypes.Length() - 1) + if (i != fninfo->mArgTypes.Length() - 1 || + fninfo->mIsVariadic) result.Append(NS_LITERAL_STRING(", ")); } + if (fninfo->mIsVariadic) + result.Append(NS_LITERAL_STRING("\"...\"")); result.Append(']'); } @@ -2660,6 +2669,9 @@ CType::TypesEqual(JSContext* cx, JSObject* t1, JSObject* t2) if (f1->mArgTypes.Length() != f2->mArgTypes.Length()) return false; + if (f1->mIsVariadic != f2->mIsVariadic) + return false; + for (PRUint32 i = 0; i < f1->mArgTypes.Length(); ++i) { if (!TypesEqual(cx, f1->mArgTypes[i], f2->mArgTypes[i])) return false; @@ -4189,7 +4201,7 @@ struct AutoValue }; static bool -GetABI(JSContext* cx, jsval abiType, ffi_abi& result) +GetABI(JSContext* cx, jsval abiType, ffi_abi* result) { if (JSVAL_IS_PRIMITIVE(abiType)) return false; @@ -4201,11 +4213,11 @@ GetABI(JSContext* cx, jsval abiType, ffi_abi& result) // C calling convention (cdecl) on each platform. switch (abi) { case ABI_DEFAULT: - result = FFI_DEFAULT_ABI; + *result = FFI_DEFAULT_ABI; return true; case ABI_STDCALL: #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2) - result = FFI_STDCALL; + *result = FFI_STDCALL; return true; #endif case INVALID_ABI: @@ -4270,6 +4282,52 @@ PrepareReturnType(JSContext* cx, jsval type) return result; } +static JS_ALWAYS_INLINE bool +IsEllipsis(jsval v) +{ + if (!JSVAL_IS_STRING(v)) + return false; + JSString* str = JSVAL_TO_STRING(v); + if (JS_GetStringLength(str) != 3) + return false; + jschar* chars = JS_GetStringChars(str), dot('.'); + return (chars[0] == dot && + chars[1] == dot && + chars[2] == dot); +} + +static JSBool +PrepareCIF(JSContext* cx, + FunctionInfo* fninfo) +{ + ffi_abi abi; + if (!GetABI(cx, OBJECT_TO_JSVAL(fninfo->mABI), &abi)) { + JS_ReportError(cx, "Invalid ABI specification"); + return false; + } + + ffi_status status = + ffi_prep_cif(&fninfo->mCIF, + abi, + fninfo->mFFITypes.Length(), + CType::GetFFIType(cx, fninfo->mReturnType), + fninfo->mFFITypes.Elements()); + + switch (status) { + case FFI_OK: + return true; + case FFI_BAD_ABI: + JS_ReportError(cx, "Invalid ABI specification"); + return false; + case FFI_BAD_TYPEDEF: + JS_ReportError(cx, "Invalid type specification"); + return false; + default: + JS_ReportError(cx, "Unknown libffi error"); + return false; + } +} + static FunctionInfo* NewFunctionInfo(JSContext* cx, jsval abiType, @@ -4283,19 +4341,12 @@ NewFunctionInfo(JSContext* cx, return NULL; } - // determine the ABI - ffi_abi abi; - if (!GetABI(cx, abiType, abi)) { - JS_ReportError(cx, "Invalid ABI specification"); - return NULL; - } fninfo->mABI = JSVAL_TO_OBJECT(abiType); // prepare the result type fninfo->mReturnType = PrepareReturnType(cx, returnType); if (!fninfo->mReturnType) return NULL; - ffi_type* rtype = CType::GetFFIType(cx, fninfo->mReturnType); // prepare the argument types if (!fninfo->mArgTypes.SetCapacity(argLength) || @@ -4304,7 +4355,29 @@ NewFunctionInfo(JSContext* cx, return NULL; } + fninfo->mIsVariadic = false; + for (PRUint32 i = 0; i < argLength; ++i) { + if (IsEllipsis(argTypes[i])) { + fninfo->mIsVariadic = true; + if (i < 1) { + JS_ReportError(cx, "\"...\" may not be the first and only parameter " + "type of a variadic function declaration"); + return NULL; + } + if (i < argLength - 1) { + JS_ReportError(cx, "\"...\" must be the last parameter type of a " + "variadic function declaration"); + return NULL; + } + if (GetABICode(cx, fninfo->mABI) != ABI_DEFAULT) { + JS_ReportError(cx, "Variadic functions must use the __cdecl calling " + "convention"); + return NULL; + } + break; + } + JSObject* argType = PrepareType(cx, argTypes[i]); if (!argType) return NULL; @@ -4313,21 +4386,14 @@ NewFunctionInfo(JSContext* cx, fninfo->mFFITypes.AppendElement(CType::GetFFIType(cx, argType)); } - ffi_status status = ffi_prep_cif(&fninfo->mCIF, abi, - fninfo->mFFITypes.Length(), rtype, fninfo->mFFITypes.Elements()); - switch (status) { - case FFI_OK: + if (fninfo->mIsVariadic) + // wait to PrepareCIF until function is called return fninfo.forget(); - case FFI_BAD_ABI: - JS_ReportError(cx, "Invalid ABI specification"); + + if (!PrepareCIF(cx, fninfo)) return NULL; - case FFI_BAD_TYPEDEF: - JS_ReportError(cx, "Invalid type specification"); - return NULL; - default: - JS_ReportError(cx, "Unknown libffi error"); - return NULL; - } + + return fninfo.forget(); } JSBool @@ -4453,6 +4519,11 @@ FunctionType::ConstructData(JSContext* cx, PRFuncPtr* data = static_cast(CData::GetData(cx, result)); if (JSVAL_IS_OBJECT(arg) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(arg))) { + FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, obj); + if (fninfo->mIsVariadic) { + JS_ReportError(cx, "Can't declare a variadic callback function"); + return JS_FALSE; + } // Construct from a JS function, and allow an optional 'this' argument. JSObject* thisObj = NULL; if (argc == 2) { @@ -4493,6 +4564,35 @@ FunctionType::ConstructData(JSContext* cx, return JS_FALSE; } +typedef nsAutoTArray AutoValueAutoArray; + +static JSBool +ConvertArgument(JSContext* cx, + jsval arg, + JSObject* type, + AutoValueAutoArray* values, + AutoValueAutoArray* strings) +{ + AutoValue* value = values->AppendElement(); + + if (!value->SizeToType(cx, type)) { + JS_ReportAllocationOverflow(cx); + return false; + } + + bool freePointer = false; + if (!ImplicitConvert(cx, arg, type, value->mData, true, &freePointer)) + return false; + + if (freePointer) { + // ImplicitConvert converted a string for us, which we have to free. + // Keep track of it. + strings->AppendElement()->mData = *static_cast(value->mData); + } + + return true; +} + JSBool FunctionType::Call(JSContext* cx, JSObject* obj, @@ -4514,8 +4614,10 @@ FunctionType::Call(JSContext* cx, } FunctionInfo* fninfo = GetFunctionInfo(cx, typeObj); + PRUint32 argcFixed = fninfo->mArgTypes.Length(); - if (argc != fninfo->mArgTypes.Length()) { + if ((!fninfo->mIsVariadic && argc != argcFixed) || + (fninfo->mIsVariadic && argc < argcFixed)) { JS_ReportError(cx, "Number of arguments does not match declaration"); return false; } @@ -4532,25 +4634,41 @@ FunctionType::Call(JSContext* cx, } // prepare the values for each argument - nsAutoTArray values; - nsAutoTArray strings; - for (PRUint32 i = 0; i < fninfo->mArgTypes.Length(); ++i) { - AutoValue* value = values.AppendElement(); - bool freePointer = false; - if (!value->SizeToType(cx, fninfo->mArgTypes[i])) { - JS_ReportAllocationOverflow(cx); - return false; - } + AutoValueAutoArray values; + AutoValueAutoArray strings; - if (!ImplicitConvert(cx, argv[i], fninfo->mArgTypes[i], value->mData, true, - &freePointer)) + for (PRUint32 i = 0; i < argcFixed; ++i) + if (!ConvertArgument(cx, argv[i], fninfo->mArgTypes[i], &values, &strings)) return false; - if (freePointer) { - // ImplicitConvert converted a string for us, which we have to free. - // Keep track of it. - strings.AppendElement()->mData = *static_cast(value->mData); + if (fninfo->mIsVariadic) { + fninfo->mFFITypes.SetLength(argcFixed); + ASSERT_OK(fninfo->mFFITypes.SetCapacity(argc)); + + JSObject* obj; // Could reuse obj instead of declaring a second + JSObject* type; // JSObject*, but readability would suffer. + + for (PRUint32 i = argcFixed; i < argc; ++i) { + if (JSVAL_IS_PRIMITIVE(argv[i]) || + !CData::IsCData(cx, obj = JSVAL_TO_OBJECT(argv[i]))) { + // Since we know nothing about the CTypes of the ... arguments, + // they absolutely must be CData objects already. + JS_ReportError(cx, "argument %d of type %s is not a CData object", + i, JS_GetTypeName(cx, JS_TypeOfValue(cx, argv[i]))); + return false; + } + if (!(type = CData::GetCType(cx, obj)) || + !(type = PrepareType(cx, OBJECT_TO_JSVAL(type))) || + // Relying on ImplicitConvert only for the limited purpose of + // converting one CType to another (e.g., T[] to T*). + !ConvertArgument(cx, argv[i], type, &values, &strings)) { + // These functions report their own errors. + return false; + } + fninfo->mFFITypes.AppendElement(CType::GetFFIType(cx, type)); } + if (!PrepareCIF(cx, fninfo)) + return false; } // initialize a pointer to an appropriate location, for storing the result @@ -4590,13 +4708,21 @@ FunctionType::GetFunctionInfo(JSContext* cx, JSObject* obj) return static_cast(JSVAL_TO_PRIVATE(slot)); } -JSBool -FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) +static JSBool +CheckFunctionType(JSContext* cx, JSObject* obj) { if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) { JS_ReportError(cx, "not a FunctionType"); return JS_FALSE; } + return JS_TRUE; +} + +JSBool +FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) +{ + if (!CheckFunctionType(cx, obj)) + return JS_FALSE; // Check if we have a cached argTypes array. ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_ARGS_T, vp)); @@ -4630,10 +4756,8 @@ FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* v JSBool FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) { - if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) { - JS_ReportError(cx, "not a FunctionType"); + if (!CheckFunctionType(cx, obj)) return JS_FALSE; - } // Get the returnType object from the FunctionInfo. *vp = OBJECT_TO_JSVAL(GetFunctionInfo(cx, obj)->mReturnType); @@ -4643,16 +4767,24 @@ FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* JSBool FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) { - if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) { - JS_ReportError(cx, "not a FunctionType"); + if (!CheckFunctionType(cx, obj)) return JS_FALSE; - } // Get the abi object from the FunctionInfo. *vp = OBJECT_TO_JSVAL(GetFunctionInfo(cx, obj)->mABI); return JS_TRUE; } +JSBool +FunctionType::IsVariadicGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) +{ + if (!CheckFunctionType(cx, obj)) + return JS_FALSE; + + *vp = BOOLEAN_TO_JSVAL(GetFunctionInfo(cx, obj)->mIsVariadic); + return JS_TRUE; +} + /******************************************************************************* ** CClosure implementation *******************************************************************************/ @@ -4671,6 +4803,7 @@ CClosure::Create(JSContext* cx, // Get the FunctionInfo from the FunctionType. FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj); + JS_ASSERT(!fninfo->mIsVariadic); nsAutoPtr cinfo(new ClosureInfo()); if (!cinfo) { diff --git a/js/ctypes/CTypes.h b/js/ctypes/CTypes.h index e6fc2417f2c9..7215b56514cf 100644 --- a/js/ctypes/CTypes.h +++ b/js/ctypes/CTypes.h @@ -104,14 +104,34 @@ struct PropertySpec JSPropertyOp setter; }; -// Descriptor of ABI, return type, and argument types for a FunctionType. +// Descriptor of ABI, return type, argument types, and variadicity for a +// FunctionType. struct FunctionInfo { + // Initialized in NewFunctionInfo when !mIsVariadic, but only later, in + // FunctionType::Call, when mIsVariadic. Not always consistent with + // mFFITypes, due to lazy initialization when mIsVariadic. ffi_cif mCIF; - JSObject* mABI; + + // Calling convention of the function. Convert to ffi_abi using GetABI + // and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing. + JSObject* mABI; + + // The CType of the value returned by the function. JSObject* mReturnType; - nsTArray mArgTypes; + + // A fixed array of known parameter types, excluding any variadic + // parameters (if mIsVariadic). + nsTArray mArgTypes; + + // A variable array of ffi_type*s corresponding to both known parameter + // types and dynamic (variadic) parameter types. Longer than mArgTypes + // only if mIsVariadic. nsTArray mFFITypes; + + // Flag indicating whether the function behaves like a C function with + // ... as the final formal parameter. + bool mIsVariadic; }; // Parameters necessary for invoking a JS function from a C closure. diff --git a/js/ctypes/ctypes.jsm b/js/ctypes/ctypes.jsm index 285c91dfa5e1..d6e82db9780c 100644 --- a/js/ctypes/ctypes.jsm +++ b/js/ctypes/ctypes.jsm @@ -94,7 +94,8 @@ let EXPORTED_SYMBOLS = [ "ctypes" ]; * @returnType The return type of the function. Must be a type constant * from ctypes. * @argTypes Argument types. Must be a type constant (other than void_t) - * from ctypes. + * from ctypes, or the literal string "..." to denote a + * variadic function. * @returns A function object. * * A function object can then be used to call the C function it represents @@ -108,7 +109,9 @@ let EXPORTED_SYMBOLS = [ "ctypes" ]; * Arguments will be checked against the types supplied at declaration, and * some attempt to convert values (e.g. boolean true/false to integer 0/1) * will be made. Otherwise, if types do not match, or conversion fails, - * an exception will be thrown. + * an exception will be thrown. Arguments passed as variadic parameters + * must have an explicit ctypes type, since their types are not declared + * in the signature. */ // Initialize the ctypes object. You do not need to do this yourself. diff --git a/js/ctypes/tests/jsctypes-test.cpp b/js/ctypes/tests/jsctypes-test.cpp index 52f5d6d4ae1d..63d1032b9593 100644 --- a/js/ctypes/tests/jsctypes-test.cpp +++ b/js/ctypes/tests/jsctypes-test.cpp @@ -42,6 +42,7 @@ #include "nsCRTGlue.h" #include #include +#include void test_void_t_cdecl() @@ -334,3 +335,67 @@ test_closure_cdecl(PRInt8 i, PRInt32 (NS_STDCALL *f)(PRInt8)) } #endif /* defined(_WIN32) && !defined(__WIN64) */ +template struct PromotedTraits { + typedef T type; +}; +#define DECL_PROMOTED(FROM, TO) \ + template <> struct PromotedTraits { \ + typedef TO type; \ + } +DECL_PROMOTED(bool, int); +DECL_PROMOTED(char, int); +DECL_PROMOTED(short, int); + +PRInt32 +test_sum_va_cdecl(PRUint8 n, ...) +{ + va_list list; + PRInt32 sum = 0; + va_start(list, n); + for (PRUint8 i = 0; i < n; ++i) + sum += va_arg(list, PromotedTraits::type); + va_end(list); + return sum; +} + +PRUint8 +test_count_true_va_cdecl(PRUint8 n, ...) +{ + va_list list; + PRUint8 count = 0; + va_start(list, n); + for (PRUint8 i = 0; i < n; ++i) + if (va_arg(list, PromotedTraits::type)) + count += 1; + va_end(list); + return count; +} + +void +test_add_char_short_int_va_cdecl(PRUint32* result, ...) +{ + va_list list; + va_start(list, result); + *result += va_arg(list, PromotedTraits::type); + *result += va_arg(list, PromotedTraits::type); + *result += va_arg(list, PromotedTraits::type); + va_end(list); +} + +PRInt32* +test_vector_add_va_cdecl(PRUint8 num_vecs, + PRUint8 vec_len, + PRInt32* result, ...) +{ + va_list list; + va_start(list, result); + PRUint8 i; + for (i = 0; i < vec_len; ++i) + result[i] = 0; + for (i = 0; i < num_vecs; ++i) { + PRInt32* vec = va_arg(list, PRInt32*); + for (PRUint8 j = 0; j < vec_len; ++j) + result[j] += vec[j]; + } + return result; +} diff --git a/js/ctypes/tests/jsctypes-test.h b/js/ctypes/tests/jsctypes-test.h index b3ad8c4f986f..1ba322fa1b7a 100644 --- a/js/ctypes/tests/jsctypes-test.h +++ b/js/ctypes/tests/jsctypes-test.h @@ -195,5 +195,11 @@ NS_EXTERN_C NS_EXPORT PRInt32 test_callme(PRInt8); NS_EXPORT void* test_getfn(); -} + EXPORT_CDECL(PRInt32) test_sum_va_cdecl(PRUint8 n, ...); + EXPORT_CDECL(PRUint8) test_count_true_va_cdecl(PRUint8 n, ...); + EXPORT_CDECL(void) test_add_char_short_int_va_cdecl(PRUint32* result, ...); + EXPORT_CDECL(PRInt32*) test_vector_add_va_cdecl(PRUint8 num_vecs, + PRUint8 vec_len, + PRInt32* result, ...); +} diff --git a/js/ctypes/tests/unit/test_jsctypes.js.in b/js/ctypes/tests/unit/test_jsctypes.js.in index ed08e057678b..8813c58e8535 100644 --- a/js/ctypes/tests/unit/test_jsctypes.js.in +++ b/js/ctypes/tests/unit/test_jsctypes.js.in @@ -53,8 +53,10 @@ function do_check_throws(f, type, stack) try { f(); } catch (exc) { - if (exc instanceof type) + if (exc instanceof type) { + do_check_true(true); return; + } do_throw("expected " + type.name + " exception, caught " + exc, stack); } do_throw("expected " + type.name + " exception, none thrown", stack); @@ -189,6 +191,7 @@ function run_test() run_struct_tests(library); run_function_tests(library); run_closure_tests(library); + run_variadic_tests(library); // test the string version of ctypes.open() as well let libpath = libfile.path; @@ -1663,7 +1666,8 @@ function run_FunctionType_tests() { run_type_ctor_class_tests(ctypes.FunctionType, ctypes.FunctionType(ctypes.default_abi, ctypes.void_t), ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.int32_t ]), - [ "abi", "returnType", "argTypes" ], undefined, undefined, undefined, undefined); + [ "abi", "returnType", "argTypes", "isVariadic" ], + undefined, undefined, undefined, undefined); do_check_throws(function() { ctypes.FunctionType(); }, Error); do_check_throws(function() { @@ -2111,6 +2115,94 @@ function run_single_closure_tests(library, abi, suffix) do_check_eq(test_closure(-52, closure2), -52 + thisobj.a); } +function run_variadic_tests(library) { + let sum_va_type = ctypes.FunctionType(ctypes.default_abi, + ctypes.int32_t, + [ctypes.uint8_t, "..."]), + sum_va = library.declare("test_sum_va_cdecl", ctypes.default_abi, ctypes.int32_t, + ctypes.uint8_t, "..."); + + do_check_eq(sum_va_type.toSource(), + 'ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.uint8_t, "..."])'); + do_check_eq(sum_va.constructor.name, "int32_t(*)(uint8_t, ...)"); + do_check_true(sum_va.constructor.isVariadic); + + do_check_eq(sum_va(3, + ctypes.int32_t(1), + ctypes.int32_t(2), + ctypes.int32_t(3)), + 6); + + do_check_throws(function() { + ctypes.FunctionType(ctypes.default_abi, ctypes.bool, + [ctypes.bool, "...", ctypes.bool]); + }, Error); + + do_check_throws(function() { + ctypes.FunctionType(ctypes.default_abi, ctypes.bool, ["..."]); + }, Error); + +#ifdef _WIN32 +#ifndef _WIN64 + do_check_throws(function() { + ctypes.FunctionType(ctypes.stdcall_abi, ctypes.bool, + [ctypes.bool, "..."]); + }, Error); +#endif +#endif + + do_check_throws(function() { + // No variadic closure callbacks allowed. + sum_va_type(function(){}); + }, Error); + + let count_true_va = library.declare("test_sum_va_cdecl", ctypes.default_abi, ctypes.uint8_t, + ctypes.uint8_t, "..."); + do_check_eq(count_true_va(8, + ctypes.bool(false), + ctypes.bool(false), + ctypes.bool(false), + ctypes.bool(true), + ctypes.bool(true), + ctypes.bool(false), + ctypes.bool(true), + ctypes.bool(true)), + 4); + + let add_char_short_int_va = library.declare("test_add_char_short_int_va_cdecl", + ctypes.default_abi, ctypes.void_t, + ctypes.uint32_t.ptr, "..."), + result = ctypes.uint32_t(3); + + add_char_short_int_va(result.address(), + ctypes.char(5), + ctypes.short(7), + ctypes.uint32_t(11)); + + do_check_eq(result.value, 3 + 5 + 7 + 11); + + let result = ctypes.int32_t.array(3)([1,1,1]), + v1 = ctypes.int32_t.array(4)([1,2,3,5]), + v2 = ctypes.int32_t.array(3)([7,11,13]), + vector_add_va = library.declare("test_vector_add_va_cdecl", + ctypes.default_abi, ctypes.int32_t.ptr, + ctypes.uint8_t, ctypes.uint8_t, "..."), + // Note that vector_add_va zeroes out result first. + vec_sum = vector_add_va(2, 3, result, v1, v2); + do_check_eq(vec_sum.contents, 8); + do_check_eq(result[0], 8); + do_check_eq(result[1], 13); + do_check_eq(result[2], 16); + + do_check_true(!!(sum_va_type().value = sum_va_type())); + let sum_notva_type = ctypes.FunctionType(sum_va_type.abi, + sum_va_type.returnType, + [ctypes.uint8_t]); + do_check_throws(function() { + sum_va_type().value = sum_notva_type(); + }, Error); +} + // bug 522360 - try loading system library without full path function run_load_system_library() { From e2e3aec31a6027ff56a979e28e149fb2af343752 Mon Sep 17 00:00:00 2001 From: Dan Witte Date: Thu, 1 Apr 2010 10:59:18 -0700 Subject: [PATCH 32/69] Bug 555644 - Fix toSource() on ctypes.float types. r=benjamn --- js/ctypes/CTypes.cpp | 16 +++++++++------- js/ctypes/tests/unit/test_jsctypes.js.in | 13 +++++++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/js/ctypes/CTypes.cpp b/js/ctypes/CTypes.cpp index a1ec2a082ed6..046f5d9f368e 100644 --- a/js/ctypes/CTypes.cpp +++ b/js/ctypes/CTypes.cpp @@ -43,7 +43,7 @@ #include "nsUTF8Utils.h" #include "nsCRTGlue.h" #include "prlog.h" -#include "prdtoa.h" +#include "jsdtoa.h" #include #if defined(XP_WIN) || defined(XP_OS2) @@ -2218,12 +2218,14 @@ BuildDataSource(JSContext* cx, JSObject* typeObj, void* data, bool isImplicit) #define DEFINE_FLOAT_TYPE(name, type, ffiType) \ case TYPE_##name: { \ /* Serialize as a primitive double. */ \ - PRFloat64 fp = *static_cast(data); \ - PRIntn decpt, sign; \ - char buf[128]; \ - PRStatus rv = PR_dtoa(fp, 0, 0, &decpt, &sign, NULL, buf, sizeof(buf)); \ - JS_ASSERT(rv == PR_SUCCESS); \ - result.AppendASCII(buf); \ + double fp = *static_cast(data); \ + char buf[DTOSTR_STANDARD_BUFFER_SIZE]; \ + char* str = JS_dtostr(buf, sizeof(buf), DTOSTR_STANDARD, 0, fp); \ + JS_ASSERT(str); \ + if (!str) \ + break; \ + \ + result.AppendASCII(str); \ break; \ } #define DEFINE_CHAR_TYPE(name, type, ffiType) \ diff --git a/js/ctypes/tests/unit/test_jsctypes.js.in b/js/ctypes/tests/unit/test_jsctypes.js.in index 8813c58e8535..19d799ecb94b 100644 --- a/js/ctypes/tests/unit/test_jsctypes.js.in +++ b/js/ctypes/tests/unit/test_jsctypes.js.in @@ -953,6 +953,19 @@ function run_float_tests(library, t, name, size) { for (let i = 0; i < vals.length; i++) do_check_throws(function () { d.value = vals[i]; }, TypeError); + // Check that values roundtrip through toSource() correctly. + function test_roundtrip(t, val) + { + let f1 = t(val); + eval("let f2 = " + f1.toSource()); + do_check_eq(f1.value, f2.value); + } + let vals = [Infinity, -Infinity, -0, 0, 1, -1, 1/3, -1/3, 1/4, -1/4, + 1e-14, -1e-14, 0xfffffffffffff000, -0xfffffffffffff000]; + for (let i = 0; i < vals.length; i++) + test_roundtrip(t, vals[i]); + do_check_eq(t(NaN).toSource(), t.toSource() + "(NaN)"); + do_check_true(d.address().constructor === t.ptr); do_check_eq(d.address().contents, d.value); do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value + ")"); From 098d13a7bdec0438b731c11f85003a43287c4281 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 11:05:40 -0700 Subject: [PATCH 33/69] Bug 551298, patch A: Move THEBES_INLINE_DECL_REFCOUNTING to xpcom (with s/THEBES/NS/). r=bsmedberg --- gfx/thebes/public/gfxTypes.h | 22 +--------------------- xpcom/glue/nsISupportsImpl.h | 29 +++++++++++++++++++++++++++++ xpcom/glue/nsISupportsUtils.h | 6 ++++-- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index cb4dccebffa0..b68c48f1e790 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -98,27 +98,7 @@ enum gfxBreakPriority { #include "nsAutoPtr.h" #define THEBES_INLINE_DECL_REFCOUNTING(_class) \ -public: \ - nsrefcnt AddRef(void) { \ - NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ - ++mRefCnt; \ - NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ - return mRefCnt; \ - } \ - nsrefcnt Release(void) { \ - NS_PRECONDITION(0 != mRefCnt, "dup release"); \ - --mRefCnt; \ - NS_LOG_RELEASE(this, mRefCnt, #_class); \ - if (mRefCnt == 0) { \ - mRefCnt = 1; /* stabilize */ \ - NS_DELETEXPCOM(this); \ - return 0; \ - } \ - return mRefCnt; \ - } \ -protected: \ - nsAutoRefCnt mRefCnt; \ -public: + NS_INLINE_DECL_REFCOUNTING(_class) #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index fe0c719e62e9..f510c8e4ef3f 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -303,6 +303,35 @@ public: */ #define NS_INIT_ISUPPORTS() ((void)0) +/** + * Use this macro to declare and implement the AddRef & Release methods for a + * given non-XPCOM _class. + * + * The implementations here should match NS_IMPL_ADDREF/NS_IMPL_RELEASE, minus + * the nsrefcnt return-value and the NS_ASSERT_OWNINGTHREAD() call. + * + * @param _class The name of the class implementing the method + */ +#define NS_INLINE_DECL_REFCOUNTING(_class) \ +public: \ + void AddRef(void) { \ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + ++mRefCnt; \ + NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ + } \ + void Release(void) { \ + NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + --mRefCnt; \ + NS_LOG_RELEASE(this, mRefCnt, #_class); \ + if (mRefCnt == 0) { \ + mRefCnt = 1; /* stabilize */ \ + NS_DELETEXPCOM(this); \ + } \ + } \ +protected: \ + nsAutoRefCnt mRefCnt; \ +public: + /** * Use this macro to implement the AddRef method for a given _class * @param _class The name of the class implementing the method diff --git a/xpcom/glue/nsISupportsUtils.h b/xpcom/glue/nsISupportsUtils.h index e20aa5e3ece8..7bfb89494650 100644 --- a/xpcom/glue/nsISupportsUtils.h +++ b/xpcom/glue/nsISupportsUtils.h @@ -108,10 +108,12 @@ extern "C++" { // yet still denies you the ability to |AddRef()| an |nsCOMPtr|. template inline -nsrefcnt +void ns_if_addref( T expr ) { - return expr ? expr->AddRef() : 0; + if (expr) { + expr->AddRef(); + } } } /* extern "C++" */ From 3d2f471ff8dfe4848b7dd40f4622907b5c11eb31 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 11:05:40 -0700 Subject: [PATCH 34/69] Bug 551298, patch A followup i: Add thread safety assertions to AddRef/Release implementations. r=bsmedberg --- xpcom/glue/nsISupportsImpl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xpcom/glue/nsISupportsImpl.h b/xpcom/glue/nsISupportsImpl.h index f510c8e4ef3f..69c5ed10b983 100644 --- a/xpcom/glue/nsISupportsImpl.h +++ b/xpcom/glue/nsISupportsImpl.h @@ -316,11 +316,13 @@ public: public: \ void AddRef(void) { \ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ ++mRefCnt; \ NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ } \ void Release(void) { \ NS_PRECONDITION(0 != mRefCnt, "dup release"); \ + NS_ASSERT_OWNINGTHREAD(_class); \ --mRefCnt; \ NS_LOG_RELEASE(this, mRefCnt, #_class); \ if (mRefCnt == 0) { \ @@ -330,6 +332,7 @@ public: \ } \ protected: \ nsAutoRefCnt mRefCnt; \ + NS_DECL_OWNINGTHREAD \ public: /** From d509dc0e1612304c6935550bd7980a42d0fd4ad7 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 11:05:40 -0700 Subject: [PATCH 35/69] Bug 551298, patch B: Replace uses of THEBES_INLINE_DECL_REFCOUNTING with NS_INLINE_DECL_REFCOUNTING. r=roc --- content/svg/content/src/nsSVGMatrix.cpp | 1 + content/svg/content/src/nsSVGMatrix.h | 1 + gfx/layers/Layers.h | 6 ++++-- gfx/thebes/public/gfxASurface.h | 1 + gfx/thebes/public/gfxContext.h | 3 ++- gfx/thebes/public/gfxFont.h | 7 ++++--- gfx/thebes/public/gfxGdkNativeRenderer.h | 1 + gfx/thebes/public/gfxPath.h | 3 ++- gfx/thebes/public/gfxPattern.h | 4 +++- gfx/thebes/public/gfxRect.h | 1 + gfx/thebes/public/gfxTypes.h | 10 ---------- gfx/thebes/public/gfxUserFontSet.h | 3 ++- gfx/thebes/src/gfxFontconfigUtils.h | 3 ++- gfx/thebes/src/gfxPangoFonts.cpp | 2 +- layout/printing/nsPrintData.h | 1 + 15 files changed, 26 insertions(+), 21 deletions(-) diff --git a/content/svg/content/src/nsSVGMatrix.cpp b/content/svg/content/src/nsSVGMatrix.cpp index ee155e5aa7ac..c7e7d75612d1 100644 --- a/content/svg/content/src/nsSVGMatrix.cpp +++ b/content/svg/content/src/nsSVGMatrix.cpp @@ -41,6 +41,7 @@ #include "nsSVGValue.h" #include #include "nsContentUtils.h" +#include "nsISupportsImpl.h" const double radPerDegree = 2.0*3.1415926535 / 360.0; diff --git a/content/svg/content/src/nsSVGMatrix.h b/content/svg/content/src/nsSVGMatrix.h index 6d1f5d2f2612..c95002031716 100644 --- a/content/svg/content/src/nsSVGMatrix.h +++ b/content/svg/content/src/nsSVGMatrix.h @@ -71,6 +71,7 @@ #include "nsIDOMSVGMatrix.h" #include "gfxMatrix.h" +#include "nsAutoPtr.h" nsresult NS_NewSVGMatrix(nsIDOMSVGMatrix** result, diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index a3759ceeebde..b5d674be34b4 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -42,6 +42,8 @@ #include "nsRegion.h" #include "nsPoint.h" #include "nsRect.h" +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" #include "gfx3DMatrix.h" class gfxContext; @@ -106,7 +108,7 @@ class ImageContainer; * root layer, and each container layer holds a reference to its children. */ class THEBES_API LayerManager { - THEBES_INLINE_DECL_REFCOUNTING(LayerManager) + NS_INLINE_DECL_REFCOUNTING(LayerManager) public: enum LayersBackend { @@ -181,7 +183,7 @@ public: * surface. */ class THEBES_API Layer { - THEBES_INLINE_DECL_REFCOUNTING(Layer) + NS_INLINE_DECL_REFCOUNTING(Layer) public: virtual ~Layer() {} diff --git a/gfx/thebes/public/gfxASurface.h b/gfx/thebes/public/gfxASurface.h index 4c2143d646aa..c84f4ea14a60 100644 --- a/gfx/thebes/public/gfxASurface.h +++ b/gfx/thebes/public/gfxASurface.h @@ -40,6 +40,7 @@ #include "gfxTypes.h" #include "gfxRect.h" +#include "nsAutoPtr.h" typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_user_data_key cairo_user_data_key_t; diff --git a/gfx/thebes/public/gfxContext.h b/gfx/thebes/public/gfxContext.h index 23f2f068db8c..f9e95d2dfeb8 100644 --- a/gfx/thebes/public/gfxContext.h +++ b/gfx/thebes/public/gfxContext.h @@ -48,6 +48,7 @@ #include "gfxMatrix.h" #include "gfxPattern.h" #include "gfxPath.h" +#include "nsISupportsImpl.h" typedef struct _cairo cairo_t; @@ -66,7 +67,7 @@ typedef struct _cairo cairo_t; * as opposed to app units. */ class THEBES_API gfxContext { - THEBES_INLINE_DECL_REFCOUNTING(gfxContext) + NS_INLINE_DECL_REFCOUNTING(gfxContext) public: /** diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index 370654c53e02..f808c32ce9f6 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -55,6 +55,7 @@ #include "gfxFontConstants.h" #include "gfxPlatform.h" #include "nsIAtom.h" +#include "nsISupportsImpl.h" #ifdef DEBUG #include @@ -160,7 +161,7 @@ struct THEBES_API gfxFontStyle { class gfxFontEntry { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry) + NS_INLINE_DECL_REFCOUNTING(gfxFontEntry) gfxFontEntry(const nsAString& aName, gfxFontFamily *aFamily = nsnull, PRBool aIsStandardFace = PR_FALSE) : @@ -289,7 +290,7 @@ struct FontSearch { class gfxFontFamily { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontFamily) + NS_INLINE_DECL_REFCOUNTING(gfxFontFamily) gfxFontFamily(const nsAString& aName) : mName(aName), @@ -955,7 +956,7 @@ protected: }; class THEBES_API gfxTextRunFactory { - THEBES_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) + NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory) public: // Flags in the mask 0xFFFF0000 are reserved for textrun clients diff --git a/gfx/thebes/public/gfxGdkNativeRenderer.h b/gfx/thebes/public/gfxGdkNativeRenderer.h index 68cf01570061..ca5bef4337aa 100644 --- a/gfx/thebes/public/gfxGdkNativeRenderer.h +++ b/gfx/thebes/public/gfxGdkNativeRenderer.h @@ -39,6 +39,7 @@ #define GFXGDKNATIVERENDER_H_ #include "gfxColor.h" +#include "nsAutoPtr.h" #include class gfxASurface; diff --git a/gfx/thebes/public/gfxPath.h b/gfx/thebes/public/gfxPath.h index 1a5cc2e9f729..127b81ea4d24 100644 --- a/gfx/thebes/public/gfxPath.h +++ b/gfx/thebes/public/gfxPath.h @@ -38,6 +38,7 @@ #define GFX_PATH_H #include "gfxTypes.h" +#include "nsISupportsImpl.h" class gfxContext; struct gfxPoint; @@ -48,7 +49,7 @@ typedef struct cairo_path cairo_path_t; * of a gfxContext. */ class THEBES_API gfxPath { - THEBES_INLINE_DECL_REFCOUNTING(gfxPath) + NS_INLINE_DECL_REFCOUNTING(gfxPath) friend class gfxContext; diff --git a/gfx/thebes/public/gfxPattern.h b/gfx/thebes/public/gfxPattern.h index 26f67b35f1d2..b378b815c02a 100644 --- a/gfx/thebes/public/gfxPattern.h +++ b/gfx/thebes/public/gfxPattern.h @@ -42,6 +42,8 @@ #include "gfxColor.h" #include "gfxMatrix.h" +#include "nsISupportsImpl.h" +#include "nsAutoPtr.h" class gfxContext; class gfxASurface; @@ -49,7 +51,7 @@ typedef struct _cairo_pattern cairo_pattern_t; class THEBES_API gfxPattern { - THEBES_INLINE_DECL_REFCOUNTING(gfxPattern) + NS_INLINE_DECL_REFCOUNTING(gfxPattern) public: gfxPattern(cairo_pattern_t *aPattern); diff --git a/gfx/thebes/public/gfxRect.h b/gfx/thebes/public/gfxRect.h index c024211aa5bd..7da3e1f2678a 100644 --- a/gfx/thebes/public/gfxRect.h +++ b/gfx/thebes/public/gfxRect.h @@ -40,6 +40,7 @@ #include "gfxTypes.h" #include "gfxPoint.h" +#include "nsDebug.h" struct THEBES_API gfxCorner { typedef int Corner; diff --git a/gfx/thebes/public/gfxTypes.h b/gfx/thebes/public/gfxTypes.h index b68c48f1e790..1e1f0862cb3d 100644 --- a/gfx/thebes/public/gfxTypes.h +++ b/gfx/thebes/public/gfxTypes.h @@ -90,16 +90,6 @@ enum gfxBreakPriority { eNormalBreak }; -/** - * Define refcounting for Thebes. For now use the stuff from nsISupportsImpl - * even though it forces the functions to be virtual... - */ -#include "nsISupportsImpl.h" -#include "nsAutoPtr.h" - -#define THEBES_INLINE_DECL_REFCOUNTING(_class) \ - NS_INLINE_DECL_REFCOUNTING(_class) - #define THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ public: \ nsrefcnt AddRef(void) { \ diff --git a/gfx/thebes/public/gfxUserFontSet.h b/gfx/thebes/public/gfxUserFontSet.h index 654350c89d8a..aece55f5789b 100644 --- a/gfx/thebes/public/gfxUserFontSet.h +++ b/gfx/thebes/public/gfxUserFontSet.h @@ -46,6 +46,7 @@ #include "nsCOMPtr.h" #include "nsIURI.h" #include "nsIFile.h" +#include "nsISupportsImpl.h" class nsIURI; class gfxMixedFontFamily; @@ -138,7 +139,7 @@ class THEBES_API gfxUserFontSet { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxUserFontSet) + NS_INLINE_DECL_REFCOUNTING(gfxUserFontSet) gfxUserFontSet(); virtual ~gfxUserFontSet(); diff --git a/gfx/thebes/src/gfxFontconfigUtils.h b/gfx/thebes/src/gfxFontconfigUtils.h index 7dcb6a38758b..4943f77b8cda 100644 --- a/gfx/thebes/src/gfxFontconfigUtils.h +++ b/gfx/thebes/src/gfxFontconfigUtils.h @@ -44,6 +44,7 @@ #include "nsAutoRef.h" #include "nsTArray.h" #include "nsTHashtable.h" +#include "nsISupportsImpl.h" #include @@ -87,7 +88,7 @@ class gfxIgnoreCaseCStringComparator class gfxFontNameList : public nsTArray { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFontNameList) + NS_INLINE_DECL_REFCOUNTING(gfxFontNameList) PRBool Exists(nsAString& aName); }; diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index 3069a396e015..06b1da984218 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -935,7 +935,7 @@ GetFontGroup(PangoContext *aContext) class gfxFcPangoFontSet { public: - THEBES_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) + NS_INLINE_DECL_REFCOUNTING(gfxFcPangoFontSet) explicit gfxFcPangoFontSet(FcPattern *aPattern, gfxUserFontSet *aUserFontSet) diff --git a/layout/printing/nsPrintData.h b/layout/printing/nsPrintData.h index bd6dbf322e38..97dfb4f468d8 100644 --- a/layout/printing/nsPrintData.h +++ b/layout/printing/nsPrintData.h @@ -44,6 +44,7 @@ #include "nsIPrintOptions.h" #include "nsTArray.h" #include "nsCOMArray.h" +#include "nsAutoPtr.h" // Classes class nsPrintObject; From f138b54154d2852d06fe051407abdb2a5d2be072 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 11:05:40 -0700 Subject: [PATCH 36/69] Bug 551298, patch C: Use NS_INLINE_DECL_REFCOUNTING in /layout/ directory. r=roc --- layout/style/nsCSSValue.cpp | 6 ++-- layout/style/nsCSSValue.h | 65 ++++------------------------------ layout/style/nsStyleStruct.cpp | 21 ----------- layout/style/nsStyleStruct.h | 42 +++------------------- 4 files changed, 14 insertions(+), 120 deletions(-) diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index 548a969c429c..f2a940779659 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -506,8 +506,7 @@ nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer, : mURI(aURI), mString(aString), mReferrer(aReferrer), - mOriginPrincipal(aOriginPrincipal), - mRefCnt(0) + mOriginPrincipal(aOriginPrincipal) { NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal"); mString->AddRef(); @@ -593,7 +592,6 @@ nsCSSValueGradient::nsCSSValueGradient(PRBool aIsRadial, mBgPosY(eCSSUnit_None), mAngle(eCSSUnit_None), mRadialShape(eCSSUnit_None), - mRadialSize(eCSSUnit_None), - mRefCnt(0) + mRadialSize(eCSSUnit_None) { } diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 35db8b4d3003..4404beef5087 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -51,6 +51,7 @@ #include "nsCRTGlue.h" #include "nsStringBuffer.h" #include "nsTArray.h" +#include "nsISupportsImpl.h" class imgIRequest; class nsIDocument; @@ -379,26 +380,9 @@ public: nsCOMPtr mReferrer; nsCOMPtr mOriginPrincipal; - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::URL", sizeof(*this)); - } - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::URL"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::URL"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(URL) + protected: - nsrefcnt mRefCnt; // not to be implemented URL(const URL& aOther); @@ -420,25 +404,7 @@ public: // Override AddRef and Release to not only log ourselves correctly, but // also so that we delete correctly without a virtual destructor - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Image", sizeof(*this)); - } - - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Image"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Image"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(Image) }; private: @@ -529,28 +495,9 @@ struct nsCSSValueGradient { return !(*this == aOther); } - void AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); - return; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Gradient", sizeof(*this)); - } - void Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsCSSValue::Gradient"); - return; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Gradient"); - if (mRefCnt == 0) - delete this; - } + NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient) private: - nsrefcnt mRefCnt; - // not to be implemented nsCSSValueGradient(const nsCSSValueGradient& aOther); nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther); @@ -588,6 +535,8 @@ struct nsCSSValue::Array { return PR_TRUE; } + // XXXdholbert This uses a 16-bit ref count to save space. Should we use + // a variant of NS_INLINE_DECL_REFCOUNTING that takes a type as an argument? void AddRef() { if (mRefCnt == PR_UINT16_MAX) { NS_WARNING("refcount overflow, leaking nsCSSValue::Array"); diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 1368487368d5..4eeb50f86ae2 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1317,7 +1317,6 @@ nsStyleGradient::nsStyleGradient(void) : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR) , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) , mRepeating(PR_FALSE) - , mRefCnt(0) { } @@ -2318,26 +2317,6 @@ nsChangeHint nsStyleTextReset::MaxDifference() } #endif -// -------------------- -// nsCSSShadowArray -// nsCSSShadowItem -// - -nsrefcnt -nsCSSShadowArray::Release() -{ - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - mRefCnt--; - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; -} - // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though. // XXXbz can this not return a more specific hint? If that's ever diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 46be0ae3db1b..77f8e7e0910e 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -163,38 +163,14 @@ public: // stops are in the order specified in the stylesheet nsTArray mStops; - nsrefcnt AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsStyleGradient"); - return mRefCnt; - } - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsStyleGradient", sizeof(*this)); - return mRefCnt; - } - - nsrefcnt Release() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsStyleGradient"); - return mRefCnt; - } - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsStyleGradient"); - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } - PRBool operator==(const nsStyleGradient& aOther) const; PRBool operator!=(const nsStyleGradient& aOther) const { return !(*this == aOther); }; -private: - nsrefcnt mRefCnt; + NS_INLINE_DECL_REFCOUNTING(nsStyleGradient) +private: ~nsStyleGradient() {} // Not to be implemented @@ -671,7 +647,7 @@ class nsCSSShadowArray { } nsCSSShadowArray(PRUint32 aArrayLen) : - mLength(aArrayLen), mRefCnt(0) + mLength(aArrayLen) { MOZ_COUNT_CTOR(nsCSSShadowArray); for (PRUint32 i = 1; i < mLength; ++i) { @@ -687,15 +663,6 @@ class nsCSSShadowArray { } } - nsrefcnt AddRef() { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking object"); - return mRefCnt; - } - return ++mRefCnt; - } - nsrefcnt Release(); - PRUint32 Length() const { return mLength; } nsCSSShadowItem* ShadowAt(PRUint32 i) { NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!"); @@ -706,9 +673,10 @@ class nsCSSShadowArray { return &mArray[i]; } + NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray) + private: PRUint32 mLength; - PRUint32 mRefCnt; nsCSSShadowItem mArray[1]; // This MUST be the last item }; From d3484c464738971a69fa3b8ebdd3bada7e24437d Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 11:05:40 -0700 Subject: [PATCH 37/69] Bug 551298, patch C bustage-followup: Use fully qualified class name when logging AddRefs names to prevent name-collision in bloat hash map. --- layout/style/nsCSSValue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 4404beef5087..9c6a4278f2ca 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -380,7 +380,7 @@ public: nsCOMPtr mReferrer; nsCOMPtr mOriginPrincipal; - NS_INLINE_DECL_REFCOUNTING(URL) + NS_INLINE_DECL_REFCOUNTING(nsCSSValue::URL) protected: @@ -404,7 +404,7 @@ public: // Override AddRef and Release to not only log ourselves correctly, but // also so that we delete correctly without a virtual destructor - NS_INLINE_DECL_REFCOUNTING(Image) + NS_INLINE_DECL_REFCOUNTING(nsCSSValue::Image) }; private: From 6219dad1909355d337b020d5fd08e386bdf97a86 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 1 Apr 2010 11:05:40 -0700 Subject: [PATCH 38/69] Bug 551298, patch D: Use NS_INLINE_DECL_REFCOUNTING in /content/ directory. r=sicking --- content/smil/nsSMILInstanceTime.h | 34 +------------- content/xbl/src/nsXBLBinding.h | 21 +-------- content/xbl/src/nsXBLInsertionPoint.cpp | 13 ------ content/xbl/src/nsXBLInsertionPoint.h | 11 +---- content/xbl/src/nsXBLPrototypeBinding.cpp | 17 +------ .../src/xslt/txMozillaStylesheetCompiler.cpp | 44 ++----------------- .../xslt/txStandaloneStylesheetCompiler.cpp | 21 +-------- content/xslt/src/xslt/txStylesheet.h | 20 ++------- .../xslt/src/xslt/txStylesheetCompiler.cpp | 21 --------- content/xslt/src/xslt/txStylesheetCompiler.h | 19 +++----- content/xul/templates/src/nsRDFBinding.h | 21 ++------- 11 files changed, 22 insertions(+), 220 deletions(-) diff --git a/content/smil/nsSMILInstanceTime.h b/content/smil/nsSMILInstanceTime.h index 6b05ace864d6..b76e87641720 100644 --- a/content/smil/nsSMILInstanceTime.h +++ b/content/smil/nsSMILInstanceTime.h @@ -124,36 +124,7 @@ public: PRUint32 Serial() const { return mSerial; } void SetSerial(PRUint32 aIndex) { mSerial = aIndex; } - nsrefcnt AddRef() - { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); - return mRefCnt; - } - NS_ASSERT_OWNINGTHREAD(_class); - NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), - "nsSMILInstanceTime addref isn't thread-safe!"); - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsSMILInstanceTime", sizeof(*this)); - return mRefCnt; - } - - nsrefcnt Release() - { - if (mRefCnt == PR_UINT32_MAX) { - NS_WARNING("refcount overflow, leaking nsSMILInstanceTime"); - return mRefCnt; - } - NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), - "nsSMILInstanceTime release isn't thread-safe!"); - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsSMILInstanceTime"); - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsSMILInstanceTime) protected: void SetBaseInterval(nsSMILInterval* aBaseInterval); @@ -162,9 +133,6 @@ protected: nsSMILTimeValue mTime; - nsAutoRefCnt mRefCnt; - NS_DECL_OWNINGTHREAD - // Internal flags used for represent behaviour of different instance times` enum { // Indicates if this instance time should be removed when the owning timed diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index 492c9757ee5d..d88633a70899 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -46,6 +46,7 @@ #include "nsClassHashtable.h" #include "nsTArray.h" #include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" class nsXBLPrototypeBinding; class nsIContent; @@ -77,24 +78,7 @@ public: * which are queued to fire their constructors. */ - nsrefcnt AddRef() - { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLBinding", sizeof(nsXBLBinding)); - return mRefCnt; - } - - nsrefcnt Release() - { - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLBinding"); - if (mRefCnt == 0) { - mRefCnt = 1; - delete this; - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsXBLBinding) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding) @@ -172,7 +156,6 @@ public: // MEMBER VARIABLES protected: - nsAutoRefCnt mRefCnt; nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo nsCOMPtr mContent; // Strong. Our anonymous content stays around with us. nsRefPtr mNextBinding; // Strong. The derived binding owns the base class bindings. diff --git a/content/xbl/src/nsXBLInsertionPoint.cpp b/content/xbl/src/nsXBLInsertionPoint.cpp index 62e703195086..d3d0dc582fa8 100644 --- a/content/xbl/src/nsXBLInsertionPoint.cpp +++ b/content/xbl/src/nsXBLInsertionPoint.cpp @@ -57,19 +57,6 @@ nsXBLInsertionPoint::~nsXBLInsertionPoint() } } -nsrefcnt -nsXBLInsertionPoint::Release() -{ - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPoint"); - if (mRefCnt == 0) { - mRefCnt = 1; - delete this; - return 0; - } - return mRefCnt; -} - NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) diff --git a/content/xbl/src/nsXBLInsertionPoint.h b/content/xbl/src/nsXBLInsertionPoint.h index c1f05045a4df..5ec9239bd3f3 100644 --- a/content/xbl/src/nsXBLInsertionPoint.h +++ b/content/xbl/src/nsXBLInsertionPoint.h @@ -50,15 +50,7 @@ public: nsXBLInsertionPoint(nsIContent* aParentElement, PRUint32 aIndex, nsIContent* aDefContent); ~nsXBLInsertionPoint(); - nsrefcnt AddRef() - { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPoint", - sizeof(nsXBLInsertionPoint)); - return mRefCnt; - } - - nsrefcnt Release(); + NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPoint) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint) @@ -90,7 +82,6 @@ public: void UnbindDefaultContent(); protected: - nsAutoRefCnt mRefCnt; nsIContent* mParentElement; // This ref is weak. The parent of the element. PRInt32 mIndex; // The index of this insertion point. -1 is a pseudo-point. nsCOMArray mElements; // An array of elements present at the insertion point. diff --git a/content/xbl/src/nsXBLPrototypeBinding.cpp b/content/xbl/src/nsXBLPrototypeBinding.cpp index 8b6e97d2b036..4f417c8e1c60 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -207,27 +207,12 @@ public: nsXBLInsertionPointEntry::ReleasePool(); } - nsrefcnt AddRef() { - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsXBLInsertionPointEntry", sizeof(nsXBLInsertionPointEntry)); - return mRefCnt; - } - - nsrefcnt Release() { - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsXBLInsertionPointEntry"); - if (mRefCnt == 0) { - Destroy(this); - return 0; - } - return mRefCnt; - } + NS_INLINE_DECL_REFCOUNTING(nsXBLInsertionPointEntry) protected: nsCOMPtr mInsertionParent; nsCOMPtr mDefaultContent; PRUint32 mInsertionIndex; - nsAutoRefCnt mRefCnt; nsXBLInsertionPointEntry(nsIContent* aParent) : mInsertionParent(aParent), diff --git a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp index daf934456161..2ab7c3f11795 100644 --- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp @@ -404,14 +404,12 @@ public: txCompileObserver(txMozillaXSLTProcessor* aProcessor, nsILoadGroup* aLoadGroup); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txCompileObserver) nsresult startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsIPrincipal* aSourcePrincipal); -protected: - nsAutoRefCnt mRefCnt; - private: nsRefPtr mProcessor; nsCOMPtr mLoadGroup; @@ -429,23 +427,6 @@ txCompileObserver::txCompileObserver(txMozillaXSLTProcessor* aProcessor, { } -nsrefcnt -txCompileObserver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txCompileObserver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - nsresult txCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -658,11 +639,11 @@ class txSyncCompileObserver : public txACompileObserver public: txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txSyncCompileObserver) protected: nsRefPtr mProcessor; - nsAutoRefCnt mRefCnt; }; txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) @@ -670,23 +651,6 @@ txSyncCompileObserver::txSyncCompileObserver(txMozillaXSLTProcessor* aProcessor) { } -nsrefcnt -txSyncCompileObserver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txSyncCompileObserver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - nsresult txSyncCompileObserver::loadURI(const nsAString& aUri, const nsAString& aReferrerUri, diff --git a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp index 11347fbbfd06..f68ad544ccad 100644 --- a/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStandaloneStylesheetCompiler.cpp @@ -64,7 +64,8 @@ class txDriver : public txACompileObserver const XML_Char *aSystemId, const XML_Char *aPublicId); - TX_DECL_ACOMPILEOBSERVER; + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txDriver) nsRefPtr mCompiler; protected: @@ -73,7 +74,6 @@ class txDriver : public txACompileObserver // keep track of the nsresult returned by the handlers, expat forgets them nsresult mRV; XML_Parser mExpatParser; - nsAutoRefCnt mRefCnt; }; nsresult @@ -338,23 +338,6 @@ txDriver::createErrorString() * txACompileObserver implementation */ -nsrefcnt -txDriver::AddRef() -{ - return ++mRefCnt; -} - -nsrefcnt -txDriver::Release() -{ - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - void txDriver::onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, const PRUnichar *aErrorText, const PRUnichar *aParam) diff --git a/content/xslt/src/xslt/txStylesheet.h b/content/xslt/src/xslt/txStylesheet.h index 5f6228f1fbe9..cd159e8f7306 100644 --- a/content/xslt/src/xslt/txStylesheet.h +++ b/content/xslt/src/xslt/txStylesheet.h @@ -44,6 +44,7 @@ #include "txList.h" #include "txXSLTPatterns.h" #include "nsTPtrArray.h" +#include "nsISupportsImpl.h" class txInstruction; class txToplevelItem; @@ -67,20 +68,8 @@ public: txStylesheet(); ~txStylesheet(); nsresult init(); - - nsrefcnt AddRef() - { - return ++mRefCnt; - } - nsrefcnt Release() - { - if (--mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; - } + + NS_INLINE_DECL_REFCOUNTING(txStylesheet) txInstruction* findTemplate(const txXPathNode& aNode, const txExpandedName& aMode, @@ -159,9 +148,6 @@ private: nsTPtrArray& aFrameStripSpaceTests); nsresult addAttributeSet(txAttributeSetItem* aAttributeSetItem); - // Refcount - nsAutoRefCnt mRefCnt; - // List of ImportFrames txList mImportFrames; diff --git a/content/xslt/src/xslt/txStylesheetCompiler.cpp b/content/xslt/src/xslt/txStylesheetCompiler.cpp index 759c5cb4306d..d0050683fd0b 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txStylesheetCompiler.cpp @@ -69,27 +69,6 @@ txStylesheetCompiler::txStylesheetCompiler(const nsAString& aStylesheetURI, mStatus = init(aStylesheetURI, aStylesheet, aInsertPosition); } -nsrefcnt -txStylesheetCompiler::AddRef() -{ - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "txStylesheetCompiler", sizeof(*this)); - return mRefCnt; -} - -nsrefcnt -txStylesheetCompiler::Release() -{ - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "txStylesheetCompiler"); - if (mRefCnt == 0) { - mRefCnt = 1; //stabilize - delete this; - return 0; - } - return mRefCnt; -} - void txStylesheetCompiler::setBaseURI(const nsString& aBaseURI) { diff --git a/content/xslt/src/xslt/txStylesheetCompiler.h b/content/xslt/src/xslt/txStylesheetCompiler.h index fc23fb4d3d89..4d71484af266 100644 --- a/content/xslt/src/xslt/txStylesheetCompiler.h +++ b/content/xslt/src/xslt/txStylesheetCompiler.h @@ -77,8 +77,8 @@ public: class txACompileObserver { public: - virtual nsrefcnt AddRef() = 0; - virtual nsrefcnt Release() = 0; + virtual void AddRef() = 0; + virtual void Release() = 0; virtual nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, @@ -90,13 +90,11 @@ public: }; #define TX_DECL_ACOMPILEOBSERVER \ - nsrefcnt AddRef(); \ - nsrefcnt Release(); \ nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, \ txStylesheetCompiler* aCompiler); \ void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, \ const PRUnichar *aErrorText = nsnull, \ - const PRUnichar *aParam = nsnull) + const PRUnichar *aParam = nsnull); class txStylesheetCompilerState : public txIParseContext { @@ -215,8 +213,6 @@ public: txStylesheet* aStylesheet, txListIterator* aInsertPosition, txACompileObserver* aObserver); - virtual nsrefcnt AddRef(); - virtual nsrefcnt Release(); void setBaseURI(const nsString& aBaseURI); @@ -235,12 +231,8 @@ public: txStylesheet* getStylesheet(); - // txACompileObserver - nsresult loadURI(const nsAString& aUri, const nsAString& aReferrerUri, - txStylesheetCompiler* aCompiler); - void onDoneCompiling(txStylesheetCompiler* aCompiler, nsresult aResult, - const PRUnichar *aErrorText = nsnull, - const PRUnichar *aParam = nsnull); + TX_DECL_ACOMPILEOBSERVER + NS_INLINE_DECL_REFCOUNTING(txStylesheetCompiler) private: nsresult startElementInternal(PRInt32 aNamespaceID, nsIAtom* aLocalName, @@ -253,7 +245,6 @@ private: nsresult ensureNewElementContext(); nsresult maybeDoneCompiling(); - nsAutoRefCnt mRefCnt; nsString mCharacters; nsresult mStatus; }; diff --git a/content/xul/templates/src/nsRDFBinding.h b/content/xul/templates/src/nsRDFBinding.h index 2a8ab79973fc..82ad20068ddf 100644 --- a/content/xul/templates/src/nsRDFBinding.h +++ b/content/xul/templates/src/nsRDFBinding.h @@ -40,6 +40,7 @@ #include "nsAutoPtr.h" #include "nsIAtom.h" #include "nsIRDFResource.h" +#include "nsISupportsImpl.h" class nsXULTemplateResultRDF; class nsBindingValues; @@ -95,9 +96,6 @@ class RDFBindingSet { protected: - // results hold a reference to a binding set in their nsBindingValues fields - PRInt32 mRefCnt; - // the number of bindings PRInt32 mCount; @@ -107,8 +105,7 @@ protected: public: RDFBindingSet() - : mRefCnt(0), - mCount(0), + : mCount(0), mFirst(nsnull) { MOZ_COUNT_CTOR(RDFBindingSet); @@ -116,19 +113,7 @@ public: ~RDFBindingSet(); - PRInt32 AddRef() { - mRefCnt++; - NS_LOG_ADDREF(this, mRefCnt, "RDFBindingSet", sizeof(*this)); - return mRefCnt; - } - - PRInt32 Release() - { - PRInt32 refcnt = --mRefCnt; - NS_LOG_RELEASE(this, refcnt, "RDFBindingSet"); - if (refcnt == 0) delete this; - return refcnt; - } + NS_INLINE_DECL_REFCOUNTING(RDFBindingSet) PRInt32 Count() const { return mCount; } From 3ffa140c87393442a282dc581a412c7c93fe4fd9 Mon Sep 17 00:00:00 2001 From: Joel Maher Date: Thu, 1 Apr 2010 12:34:10 -0700 Subject: [PATCH 39/69] Bug 553700 Allow xpcshell harness to chunk tests r=ted --- testing/xpcshell/runxpcshelltests.py | 126 +++++++++++++++++---------- 1 file changed, 80 insertions(+), 46 deletions(-) diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index a9db3e727343..beb696e52f97 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -38,7 +38,7 @@ # # ***** END LICENSE BLOCK ***** */ -import re, sys, os, os.path, logging, shutil, signal +import re, sys, os, os.path, logging, shutil, signal, math from glob import glob from optparse import OptionParser from subprocess import Popen, PIPE, STDOUT @@ -57,24 +57,73 @@ class XPCShellTests(object): self.log.setLevel(logging.INFO) self.log.addHandler(handler) - def readManifest(self, manifest): + def readManifest(self): """ - Given a manifest file containing a list of test directories, - return a list of absolute paths to the directories contained within. + For a given manifest file, read the contents and populate self.testdirs """ - manifestdir = os.path.dirname(manifest) - testdirs = [] + manifestdir = os.path.dirname(self.manifest) try: - f = open(manifest, "r") + f = open(self.manifest, "r") for line in f: - dir = line.rstrip() - path = os.path.join(manifestdir, dir) + path = os.path.join(manifestdir, line.rstrip()) if os.path.isdir(path): - testdirs.append(path) + self.testdirs.append(path) f.close() except: pass # just eat exceptions - return testdirs + + def buildTestList(self): + """ + Builds a dict of {"testdir" : ["testfile1", "testfile2", ...], "testdir2"...}. + If manifest is given override testdirs to build initial list of directories and tests. + If testpath is given, use that, otherwise chunk if requested. + The resulting set of tests end up in self.alltests + """ + self.buildTestPath() + + self.alltests = {} + if self.manifest is not None: + self.readManifest() + + for dir in self.testdirs: + tests = self.getTestFiles(dir) + if tests: + self.alltests[os.path.abspath(dir)] = tests + + if self.singleFile is None and self.totalChunks > 1: + self.chunkTests() + + def chunkTests(self): + """ + Split the list of tests up into [totalChunks] pieces and filter the + self.alltests based on thisChunk, so we only run a subset. + """ + totalTests = 0 + for dir in self.alltests: + totalTests += len(self.alltests[dir]) + + testsPerChunk = math.ceil(totalTests / float(self.totalChunks)) + start = int(round((self.thisChunk-1) * testsPerChunk)) + end = start + testsPerChunk + currentCount = 0 + + templist = {} + for dir in self.alltests: + startPosition = 0 + dirCount = len(self.alltests[dir]) + endPosition = dirCount + if currentCount < start and currentCount + dirCount >= start: + startPosition = int(start - currentCount) + if currentCount + dirCount > end: + endPosition = int(end - currentCount) + if end - currentCount < 0 or (currentCount + dirCount < start): + endPosition = 0 + + if startPosition is not endPosition: + templist[dir] = self.alltests[dir][startPosition:endPosition] + currentCount += dirCount + + self.alltests = templist def setAbsPath(self): """ @@ -167,7 +216,7 @@ class XPCShellTests(object): |singleFile| will be the optional test only, or |None|. """ self.singleFile = None - if self.testPath: + if self.testPath is not None: if self.testPath.endswith('.js'): # Split into path and file. if self.testPath.find('/') == -1: @@ -209,10 +258,10 @@ class XPCShellTests(object): On a remote system, this is overloaded to find files in the remote directory structure. """ - testfiles = sorted(glob(os.path.join(testdir, "test_*.js"))) + testfiles = sorted(glob(os.path.join(os.path.abspath(testdir), "test_*.js"))) if self.singleFile: if self.singleFile in [os.path.basename(x) for x in testfiles]: - testfiles = [os.path.join(testdir, self.singleFile)] + testfiles = os.path.abspath([os.path.join(testdir, self.singleFile)]) else: # not in this dir? skip it return None @@ -313,7 +362,8 @@ class XPCShellTests(object): def runTests(self, xpcshell, xrePath=None, symbolsPath=None, manifest=None, testdirs=[], testPath=None, interactive=False, logfiles=True, - debuggerInfo=None): + thisChunk=1, totalChunks=1, debugger=None, + debuggerArgs=None, debuggerInteractive=False): """Run xpcshell tests. |xpcshell|, is the xpcshell executable to use to run the tests. @@ -341,7 +391,9 @@ class XPCShellTests(object): self.testPath = testPath self.interactive = interactive self.logfiles = logfiles - self.debuggerInfo = debuggerInfo + self.totalChunks = totalChunks + self.thisChunk = thisChunk + self.debuggerInfo = getDebuggerInfo(self.oldcwd, debugger, debuggerArgs, debuggerInteractive) if not testdirs and not manifest: # nothing to test! @@ -356,39 +408,26 @@ class XPCShellTests(object): self.buildEnvironment() pStdout, pStderr = self.getPipes() - # Override testdirs. - if manifest is not None: - testdirs = self.readManifest(os.path.abspath(manifest)) - - self.buildTestPath() - - # Process each test directory individually. - for testdir in testdirs: - self.buildXpcsCmd(testdir) + self.buildTestList() + for testdir in sorted(self.alltests.keys()): if self.testPath and not testdir.endswith(self.testPath): continue - testdir = os.path.abspath(testdir) - + self.buildXpcsCmd(testdir) testHeadFiles = self.getHeadFiles(testdir) testTailFiles = self.getTailFiles(testdir) - - testfiles = self.getTestFiles(testdir) - if testfiles == None: - continue - cmdH = self.buildCmdHead(testHeadFiles, testTailFiles, self.xpcsCmd) # Now execute each test individually. - for test in testfiles: + for test in self.alltests[testdir]: # create a temp dir that the JS harness can stick a profile in self.profileDir = self.setupProfileDir() self.leakLogFile = self.setupLeakLogging() # The test file will have to be loaded after the head files. cmdT = ['-e', 'const _TEST_FILE = ["%s"];' % - replaceBackSlashes(os.path.join(testdir, test))] + replaceBackSlashes(test)] try: proc = self.launchProcess(cmdH + cmdT + self.xpcsRunArgs, @@ -455,6 +494,12 @@ class XPCShellOptions(OptionParser): self.add_option("--test-path", type="string", dest="testPath", default=None, help="single path and/or test filename to test") + self.add_option("--total-chunks", + type = "int", dest = "totalChunks", default=1, + help = "how many chunks to split the tests up into") + self.add_option("--this-chunk", + type = "int", dest = "thisChunk", default=1, + help = "which chunk to run between 1 and --total-chunks") def main(): parser = XPCShellOptions() @@ -468,23 +513,12 @@ def main(): sys.exit(1) xpcsh = XPCShellTests() - debuggerInfo = getDebuggerInfo(xpcsh.oldcwd, options.debugger, options.debuggerArgs, - options.debuggerInteractive); if options.interactive and not options.testPath: print >>sys.stderr, "Error: You must specify a test filename in interactive mode!" sys.exit(1) - - if not xpcsh.runTests(args[0], - xrePath=options.xrePath, - symbolsPath=options.symbolsPath, - manifest=options.manifest, - testdirs=args[1:], - testPath=options.testPath, - interactive=options.interactive, - logfiles=options.logfiles, - debuggerInfo=debuggerInfo): + if not xpcsh.runTests(args[0], **options.__dict__): sys.exit(1) if __name__ == '__main__': From fcca584eab0d28010503daebdc2e8d68b64bf7af Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Thu, 1 Apr 2010 16:13:07 -0400 Subject: [PATCH 40/69] Bug 549094 - Change the value of editor.singleLine.pasteNewlines to match the Firefox value across all Gecko based applications; r=bzbarsky --- browser/app/profile/firefox.js | 3 --- modules/libpref/src/init/all.js | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 58d5a463b245..d66b9d3de730 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -844,9 +844,6 @@ pref("browser.zoom.siteSpecific", true); // Whether or not to update background tabs to the current zoom level. pref("browser.zoom.updateBackgroundTabs", true); -// replace newlines with spaces when pasting into fields -pref("editor.singleLine.pasteNewlines", 2); - // The breakpad report server to link to in about:crashes pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/"); diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 39f7eb288673..2557f0a548f5 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -329,7 +329,7 @@ pref("extensions.spellcheck.inline.max-misspellings", 500); // belong in comm-central/editor/ui/composer.js pref("editor.use_custom_colors", false); -pref("editor.singleLine.pasteNewlines", 1); +pref("editor.singleLine.pasteNewlines", 2); pref("editor.quotesPreformatted", false); pref("editor.use_css", true); pref("editor.css.default_length_unit", "px"); @@ -2414,7 +2414,6 @@ pref("network.hosts.smtp_server", "localhost"); pref("network.hosts.pop_server", "pop"); pref("network.protocol-handler.warn-external.file", false); pref("browser.drag_out_of_frame_style", 1); -pref("editor.singleLine.pasteNewlines", 0); // Middle-mouse handling pref("middlemouse.paste", true); From 01826d9bd43407004c5ef93aff288c62f26754e6 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Thu, 1 Apr 2010 15:51:49 -0500 Subject: [PATCH 41/69] Bug 556198: Build jemalloc into mozilla-runtime. r=bsmedberg --- ipc/app/Makefile.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ipc/app/Makefile.in b/ipc/app/Makefile.in index 2992de99e77c..ada8f88474b1 100644 --- a/ipc/app/Makefile.in +++ b/ipc/app/Makefile.in @@ -92,6 +92,8 @@ OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 v OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32) endif +LIBS += $(JEMALLOC_LIBS) + include $(topsrcdir)/config/rules.mk ifeq ($(OS_ARCH),WINNT) From fff7c7543ec4967d2c07d0bf0a5fcd03b8c044d6 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 2 Apr 2010 00:56:22 -0700 Subject: [PATCH 42/69] Bug 554692 - Maemo location provider. r=oleg --HG-- extra : rebase_source : ea58c30392f9450eba80070d5a4be75028df7fd0 --- configure.in | 7 + dom/src/geolocation/MaemoLocationProvider.cpp | 409 ++++++++++++++++++ dom/src/geolocation/MaemoLocationProvider.h | 120 +++++ dom/src/geolocation/Makefile.in | 5 + dom/src/geolocation/nsGeolocation.cpp | 11 +- 5 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 dom/src/geolocation/MaemoLocationProvider.cpp create mode 100644 dom/src/geolocation/MaemoLocationProvider.h diff --git a/configure.in b/configure.in index 1b35ec1c7dfa..2f23b4738a10 100644 --- a/configure.in +++ b/configure.in @@ -6595,6 +6595,13 @@ if test $MOZ_PLATFORM_MAEMO; then if test -z "$_LIB_FOUND"; then AC_MSG_ERROR([Hildon FM-2 is required when building for Maemo]) fi + + PKG_CHECK_MODULES(LIBLOCATION,liblocation, _LIB_FOUND=1, _LIB_FOUND=) + MOZ_PLATFORM_MAEMO_LIBS="$MOZ_PLATFORM_MAEMO_LIBS $LIBLOCATION_LIBS" + MOZ_PLATFORM_MAEMO_CFLAGS="$MOZ_PLATFORM_MAEMO_CFLAGS $LIBLOCATION_CFLAGS" + if test -z "$_LIB_FOUND"; then + AC_MSG_ERROR([liblocation is required when building for Maemo]) + fi fi AC_SUBST(MOZ_PLATFORM_MAEMO_LIBS) diff --git a/dom/src/geolocation/MaemoLocationProvider.cpp b/dom/src/geolocation/MaemoLocationProvider.cpp new file mode 100644 index 000000000000..edd5be808c52 --- /dev/null +++ b/dom/src/geolocation/MaemoLocationProvider.cpp @@ -0,0 +1,409 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Geolocation. + * + * The Initial Developer of the Original Code is Mozilla Corporation + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Oleg Romashin (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include "MaemoLocationProvider.h" +#include "nsIClassInfo.h" +#include "nsDOMClassInfoID.h" +#include "nsIDOMClassInfo.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIServiceManager.h" +#include "nsServiceManagerUtils.h" + +//////////////////////////////////////////////////// +// nsGeoPositionCoords +//////////////////////////////////////////////////// + +class nsGeoPositionCoords : public nsIDOMGeoPositionCoords +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMGEOPOSITIONCOORDS + + nsGeoPositionCoords(double aLat, double aLong, double aAlt, double aHError, + double aVError, double aHeading, double aSpeed) : + mLat(aLat), mLong(aLong), mAlt(aAlt), mHError(aHError), + mVError(aVError), mHeading(aHeading), mSpeed(aSpeed) { }; +private: + ~nsGeoPositionCoords() { } + double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed; +}; + +NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords) +NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords) +NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords) +NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPositionCoords) +NS_INTERFACE_MAP_END + +NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionCoords) +NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionCoords) + +NS_IMETHODIMP +nsGeoPositionCoords::GetLatitude(double *aLatitude) +{ + *aLatitude = mLat; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionCoords::GetLongitude(double *aLongitude) +{ + *aLongitude = mLong; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionCoords::GetAltitude(double *aAltitude) +{ + *aAltitude = mAlt; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionCoords::GetAccuracy(double *aAccuracy) +{ + *aAccuracy = mHError; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionCoords::GetAltitudeAccuracy(double *aAltitudeAccuracy) +{ + *aAltitudeAccuracy = mVError; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionCoords::GetHeading(double *aHeading) +{ + *aHeading = mHeading; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPositionCoords::GetSpeed(double *aSpeed) +{ + *aSpeed = mSpeed; + return NS_OK; +} + +//////////////////////////////////////////////////// +// nsGeoPosition +//////////////////////////////////////////////////// + +class nsGeoPosition : public nsIDOMGeoPosition +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMGEOPOSITION + + nsGeoPosition(double aLat, double aLong, double aAlt, double aHError, + double aVError, double aHeading, double aSpeed, + long long aTimestamp): mTimestamp(aTimestamp) + { + mCoords = new nsGeoPositionCoords(aLat, aLong, aAlt, aHError, + aVError, aHeading, aSpeed); + NS_ASSERTION(mCoords, "null mCoords in nsGeoPosition"); + }; + +private: + ~nsGeoPosition() {} + long long mTimestamp; + nsRefPtr mCoords; +}; + +NS_INTERFACE_MAP_BEGIN(nsGeoPosition) +NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition) +NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition) +NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoPosition) +NS_INTERFACE_MAP_END + +NS_IMPL_THREADSAFE_ADDREF(nsGeoPosition) +NS_IMPL_THREADSAFE_RELEASE(nsGeoPosition) + +NS_IMETHODIMP +nsGeoPosition::GetTimestamp(DOMTimeStamp* aTimestamp) +{ + *aTimestamp = mTimestamp; + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPosition::GetCoords(nsIDOMGeoPositionCoords * *aCoords) +{ + NS_IF_ADDREF(*aCoords = mCoords); + return NS_OK; +} + +NS_IMETHODIMP +nsGeoPosition::GetAddress(nsIDOMGeoPositionAddress** aAddress) +{ + *aAddress = nsnull; + return NS_OK; +} + +NS_IMPL_ISUPPORTS2(MaemoLocationProvider, nsIGeolocationProvider, nsITimerCallback) + +MaemoLocationProvider::MaemoLocationProvider() : + mLocationChanged(0), + mControlError(0), + mDeviceDisconnected(0), + mControlStopped(0), + mHasSeenLocation(PR_FALSE), + mHasGPS(PR_TRUE), + mGPSControl(nsnull), + mGPSDevice(nsnull), + mIgnoreMinorChanges(PR_FALSE), + mPrevLat(0.0), + mPrevLong(0.0), + mIgnoreBigHErr(PR_TRUE), + mMaxHErr(1000), + mIgnoreBigVErr(PR_TRUE), + mMaxVErr(100) +{ +} + +MaemoLocationProvider::~MaemoLocationProvider() +{ +} + +void MaemoLocationProvider::DeviceDisconnected(LocationGPSDevice* device, void* self) +{ +} + +void MaemoLocationProvider::ControlStopped(LocationGPSDControl* device, void* self) +{ + MaemoLocationProvider* provider = static_cast(self); + provider->StartControl(); +} + +void MaemoLocationProvider::ControlError(LocationGPSDControl* control, void* self) +{ +} + +void MaemoLocationProvider::LocationChanged(LocationGPSDevice* device, void* self) +{ + if (!device || !device->fix) + return; + + guint32 &fields = device->fix->fields; + if (!(fields & LOCATION_GPS_DEVICE_LATLONG_SET)) + return; + + if (!(device->fix->eph && !isnan(device->fix->eph))) + return; + + MaemoLocationProvider* provider = static_cast(self); + NS_ENSURE_TRUE(provider, ); + provider->LocationUpdate(device); +} + +nsresult +MaemoLocationProvider::LocationUpdate(LocationGPSDevice* aDev) +{ + double hErr = aDev->fix->eph/100; + if (mIgnoreBigHErr && hErr > (double)mMaxHErr) + hErr = (double)mMaxHErr; + + double vErr = aDev->fix->epv/2; + if (mIgnoreBigVErr && vErr > (double)mMaxVErr) + vErr = (double)mMaxVErr; + + double altitude = 0, speed = 0, track = 0; + if (aDev->fix->epv && !isnan(aDev->fix->epv)) + altitude = aDev->fix->altitude; + if (aDev->fix->eps && !isnan(aDev->fix->eps)) + speed = aDev->fix->speed; + if (aDev->fix->epd && !isnan(aDev->fix->epd)) + track = aDev->fix->track; + +#ifdef DEBUG + double dist = location_distance_between(mPrevLat, mPrevLong, aDev->fix->latitude, aDev->fix->longitude)*1000; + fprintf(stderr, "dist:%.9f, Lat: %.6f, Long:%.6f, HErr:%g, Alt:%.6f, VErr:%g, dir:%g[%g], sp:%g[%g]\n", + dist, aDev->fix->latitude, aDev->fix->longitude, + hErr, altitude, + aDev->fix->epv/2, track, aDev->fix->epd, + speed, aDev->fix->eps); + mPrevLat = aDev->fix->latitude; + mPrevLong = aDev->fix->longitude; +#endif + + nsRefPtr somewhere = new nsGeoPosition(aDev->fix->latitude, + aDev->fix->longitude, + altitude, + hErr, + vErr, + track, + speed, + PR_Now()); + Update(somewhere); + + return NS_OK; +} + +NS_IMETHODIMP +MaemoLocationProvider::Notify(nsITimer* aTimer) +{ + LocationChanged(mGPSDevice, this); + return NS_OK; +} + +nsresult +MaemoLocationProvider::StartControl() +{ + if (mGPSControl) + return NS_OK; + + mGPSControl = location_gpsd_control_get_default(); + NS_ENSURE_TRUE(mGPSControl, NS_ERROR_FAILURE); + + mControlError = g_signal_connect(mGPSControl, "error", + G_CALLBACK(ControlError), this); + + mControlStopped = g_signal_connect(mGPSControl, "gpsd_stopped", + G_CALLBACK(ControlStopped), this); + + location_gpsd_control_start(mGPSControl); + return NS_OK; +} + +nsresult +MaemoLocationProvider::StartDevice() +{ + if (mGPSDevice) + return NS_OK; + + mGPSDevice = (LocationGPSDevice*)g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL); + NS_ENSURE_TRUE(mGPSDevice, NS_ERROR_FAILURE); + + mLocationChanged = g_signal_connect(mGPSDevice, "changed", + G_CALLBACK(LocationChanged), this); + + mDeviceDisconnected = g_signal_connect(mGPSDevice, "disconnected", + G_CALLBACK(DeviceDisconnected), this); + return NS_OK; +} + +NS_IMETHODIMP MaemoLocationProvider::Startup() +{ + nsresult rv(NS_OK); + + nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (!prefs) + return NS_ERROR_FAILURE; + + rv = StartControl(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = StartDevice(); + NS_ENSURE_SUCCESS(rv, rv); + + prefs->GetBoolPref("geo.herror.ignore.big", &mIgnoreBigHErr); + + if (mIgnoreBigHErr) + prefs->GetIntPref("geo.herror.max.value", &mMaxHErr); + + prefs->GetBoolPref("geo.verror.ignore.big", &mIgnoreBigVErr); + + if (mIgnoreBigVErr) + prefs->GetIntPref("geo.verror.max.value", &mMaxVErr); + + if (mUpdateTimer) + return NS_OK; + + PRInt32 update = 0; //0 second no timer created + prefs->GetIntPref("geo.default.update", &update); + + if (!update) + return NS_OK; + + mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); + + if (NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + if (update) + mUpdateTimer->InitWithCallback(this, update, nsITimer::TYPE_REPEATING_SLACK); + + return NS_OK; +} + +NS_IMETHODIMP MaemoLocationProvider::Watch(nsIGeolocationUpdate *callback) +{ + if (mCallback) + return NS_OK; + + mCallback = callback; + return NS_OK; +} + +NS_IMETHODIMP MaemoLocationProvider::Shutdown() +{ + if (mUpdateTimer) + mUpdateTimer->Cancel(); + + g_signal_handler_disconnect(mGPSDevice, mLocationChanged); + g_signal_handler_disconnect(mGPSDevice, mDeviceDisconnected); + + g_signal_handler_disconnect(mGPSDevice, mControlError); + g_signal_handler_disconnect(mGPSDevice, mControlStopped); + + mHasSeenLocation = PR_FALSE; + mCallback = nsnull; + + if (mGPSControl) { + location_gpsd_control_stop(mGPSControl); + g_object_unref(mGPSControl); + mGPSControl = nsnull; + } + if (mGPSDevice) { + g_object_unref(mGPSDevice); + mGPSDevice = nsnull; + } + + return NS_OK; +} + +void MaemoLocationProvider::Update(nsIDOMGeoPosition* aPosition) +{ + mHasSeenLocation = PR_TRUE; + if (mCallback) + mCallback->Update(aPosition); +} + diff --git a/dom/src/geolocation/MaemoLocationProvider.h b/dom/src/geolocation/MaemoLocationProvider.h new file mode 100644 index 000000000000..780f1e955393 --- /dev/null +++ b/dom/src/geolocation/MaemoLocationProvider.h @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Geolocation. + * + * The Initial Developer of the Original Code is Mozilla Corporation + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner (Original Author) + * Nino D'Aversa + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsCOMArray.h" +#include "nsTArray.h" +#include "nsITimer.h" +#include "nsIObserver.h" +#include "nsIURI.h" + +#include "nsWeakPtr.h" +#include "nsCycleCollectionParticipant.h" + +#include "nsIDOMGeoGeolocation.h" +#include "nsIDOMGeoPosition.h" +#include "nsIDOMGeoPositionError.h" +#include "nsIDOMGeoPositionCallback.h" +#include "nsIDOMGeoPositionErrorCallback.h" +#include "nsIDOMGeoPositionOptions.h" +#include "nsIDOMNavigatorGeolocation.h" +#include "nsIDOMGeoPositionCoords.h" + +#include "nsPIDOMWindow.h" + +#include "nsIGeolocationProvider.h" + + +extern "C" +{ +#include +#include +#include +#include +} + +class MaemoLocationProvider : public nsIGeolocationProvider, + public nsITimerCallback + +{ + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGEOLOCATIONPROVIDER + NS_DECL_NSITIMERCALLBACK + + MaemoLocationProvider(); + + void Update(nsIDOMGeoPosition* aPosition); + + private: + ~MaemoLocationProvider(); + + nsresult StartControl(); + nsresult StartDevice(); + nsresult LocationUpdate(LocationGPSDevice* aDev); + + static void DeviceDisconnected(LocationGPSDevice* device, void* self); + static void ControlStopped(LocationGPSDControl* device, void* self); + static void ControlError(LocationGPSDControl* control, void* self); + static void LocationChanged(LocationGPSDevice* device, void* self); + + gulong mLocationChanged; + gulong mControlError; + gulong mDeviceDisconnected; + gulong mControlStopped; + + nsCOMPtr mCallback; + PRPackedBool mHasSeenLocation; + PRPackedBool mHasGPS; + + nsCOMPtr mUpdateTimer; + LocationGPSDControl* mGPSControl; + LocationGPSDevice* mGPSDevice; + + PRBool mIgnoreMinorChanges; + + double mPrevLat; + double mPrevLong; + + PRBool mIgnoreBigHErr; + PRInt32 mMaxHErr; + PRBool mIgnoreBigVErr; + PRInt32 mMaxVErr; + +}; diff --git a/dom/src/geolocation/Makefile.in b/dom/src/geolocation/Makefile.in index e8eb3d2f8f3d..c48c6a3e99ad 100644 --- a/dom/src/geolocation/Makefile.in +++ b/dom/src/geolocation/Makefile.in @@ -65,6 +65,11 @@ ifdef WINCE_WINDOWS_MOBILE CPPSRCS += WinMobileLocationProvider.cpp endif +ifdef MOZ_PLATFORM_MAEMO +CPPSRCS += MaemoLocationProvider.cpp +LOCAL_INCLUDES += $(MOZ_PLATFORM_MAEMO_CFLAGS) +endif + EXTRA_COMPONENTS = \ NetworkGeolocationProvider.js \ GPSDGeolocationProvider.js \ diff --git a/dom/src/geolocation/nsGeolocation.cpp b/dom/src/geolocation/nsGeolocation.cpp index 00cd3af3d9d3..6d07f66aa71a 100644 --- a/dom/src/geolocation/nsGeolocation.cpp +++ b/dom/src/geolocation/nsGeolocation.cpp @@ -57,6 +57,10 @@ #include "WinMobileLocationProvider.h" #endif +#ifdef MOZ_PLATFORM_MAEMO +#include "MaemoLocationProvider.h" +#endif + #include "nsIDOMDocument.h" #include "nsIDocument.h" @@ -406,12 +410,17 @@ nsresult nsGeolocationService::Init() // we should move these providers outside of this file! dft - // if WINCE, see if we should try the WINCE location provider #ifdef WINCE_WINDOWS_MOBILE provider = new WinMobileLocationProvider(); if (provider) mProviders.AppendObject(provider); #endif + +#ifdef MOZ_PLATFORM_MAEMO + provider = new MaemoLocationProvider(); + if (provider) + mProviders.AppendObject(provider); +#endif return NS_OK; } From e06c8ff57cd8f92f3154819916587a6ebc2895c0 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 1 Apr 2010 23:17:13 +0200 Subject: [PATCH 43/69] Bug 556572: Support none-multiple of 4 strides. r=joedrew --- gfx/layers/opengl/ImageLayerOGL.cpp | 33 ++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index 1d53be97b571..d85d9099142a 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -214,7 +214,20 @@ PlanarYCbCrImageOGL::AllocateTextures() mManager->MakeCurrent(); sglWrapper.GenTextures(3, mTextures); - sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mData.mYStride); + GLint alignment; + + if (!((ptrdiff_t)mData.mYStride & 0x7) && !((ptrdiff_t)mData.mYChannel & 0x7)) { + alignment = 8; + } else if (!((ptrdiff_t)mData.mYStride & 0x3)) { + alignment = 4; + } else if (!((ptrdiff_t)mData.mYStride & 0x1)) { + alignment = 2; + } else { + alignment = 1; + } + + // Set texture alignment for Y plane. + sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment); sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[0]); @@ -232,8 +245,21 @@ PlanarYCbCrImageOGL::AllocateTextures() LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE, mData.mYChannel); + + if (!((ptrdiff_t)mData.mCbCrStride & 0x7) && + !((ptrdiff_t)mData.mCbChannel & 0x7) && + !((ptrdiff_t)mData.mCrChannel & 0x7)) { + alignment = 8; + } else if (!((ptrdiff_t)mData.mCbCrStride & 0x3)) { + alignment = 4; + } else if (!((ptrdiff_t)mData.mCbCrStride & 0x1)) { + alignment = 2; + } else { + alignment = 1; + } - sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mData.mCbCrStride); + // Set texture alignment for Cb/Cr plane + sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment); sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, mTextures[1]); @@ -269,7 +295,8 @@ PlanarYCbCrImageOGL::AllocateTextures() LOCAL_GL_UNSIGNED_BYTE, mData.mCrChannel); - sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0); + // Reset alignment to default + sglWrapper.PixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); } void From 0291fc7a4ff9cf8d6f9e8d906ddd2b4e9c0409dd Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 1 Apr 2010 23:17:15 +0200 Subject: [PATCH 44/69] Bug 556584: Allow opaque containers to draw their contents directly to their parent layer. r=joedrew --- gfx/layers/opengl/ContainerLayerOGL.cpp | 151 ++++++++++++------------ 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp index c93d623c56ae..673b05107220 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -132,54 +132,57 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) * Setup our temporary texture for rendering the contents of this container. */ GLuint containerSurface; - - sglWrapper.GenTextures(1, &containerSurface); - sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); - sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D, - 0, - LOCAL_GL_RGBA, - mVisibleRect.width, - mVisibleRect.height, - 0, - LOCAL_GL_BGRA, - LOCAL_GL_UNSIGNED_BYTE, - NULL); - sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); - sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); - - /** - * Create the framebuffer and bind it to make our content render into our - * framebuffer. - */ GLuint frameBuffer; - sglWrapper.GenFramebuffersEXT(1, &frameBuffer); - sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, frameBuffer); - sglWrapper.FramebufferTexture2DEXT(LOCAL_GL_FRAMEBUFFER_EXT, - LOCAL_GL_COLOR_ATTACHMENT0_EXT, - LOCAL_GL_TEXTURE_2D, - containerSurface, - 0); - - NS_ASSERTION( - sglWrapper.CheckFramebufferStatusEXT(LOCAL_GL_FRAMEBUFFER_EXT) == - LOCAL_GL_FRAMEBUFFER_COMPLETE, "Error setting up framebuffer."); - RGBLayerProgram *rgbProgram = static_cast(mManager)->GetRGBLayerProgram(); YCbCrLayerProgram *yCbCrProgram = static_cast(mManager)->GetYCbCrLayerProgram(); - /** - * Store old shader program variables and set the ones used for rendering - * this container's content. - */ - - rgbProgram->Activate(); - rgbProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, - (GLfloat)GetVisibleRect().y); - yCbCrProgram->Activate(); - yCbCrProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, - (GLfloat)GetVisibleRect().y); + if (GetOpacity() != 1.0) { + sglWrapper.GenTextures(1, &containerSurface); + sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); + sglWrapper.TexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + LOCAL_GL_RGBA, + mVisibleRect.width, + mVisibleRect.height, + 0, + LOCAL_GL_BGRA, + LOCAL_GL_UNSIGNED_BYTE, + NULL); + sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); + sglWrapper.TexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); + + /** + * Create the framebuffer and bind it to make our content render into our + * framebuffer. + */ + sglWrapper.GenFramebuffersEXT(1, &frameBuffer); + sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, frameBuffer); + sglWrapper.FramebufferTexture2DEXT(LOCAL_GL_FRAMEBUFFER_EXT, + LOCAL_GL_COLOR_ATTACHMENT0_EXT, + LOCAL_GL_TEXTURE_2D, + containerSurface, + 0); + + NS_ASSERTION( + sglWrapper.CheckFramebufferStatusEXT(LOCAL_GL_FRAMEBUFFER_EXT) == + LOCAL_GL_FRAMEBUFFER_COMPLETE, "Error setting up framebuffer."); + + /** + * Store old shader program variables and set the ones used for rendering + * this container's content. + */ + + rgbProgram->Activate(); + rgbProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, + (GLfloat)GetVisibleRect().y); + yCbCrProgram->Activate(); + yCbCrProgram->PushRenderTargetOffset((GLfloat)GetVisibleRect().x, + (GLfloat)GetVisibleRect().y); + } else { + frameBuffer = aPreviousFrameBuffer; + } /** * Render this container's contents. @@ -200,45 +203,47 @@ ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) layerToRender = layerToRender->GetNextSibling(); } - // Unbind the current framebuffer and rebind the previous one. - sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, aPreviousFrameBuffer); - sglWrapper.DeleteFramebuffersEXT(1, &frameBuffer); + if (GetOpacity() != 1.0) { + // Unbind the current framebuffer and rebind the previous one. + sglWrapper.BindFramebufferEXT(LOCAL_GL_FRAMEBUFFER_EXT, aPreviousFrameBuffer); + sglWrapper.DeleteFramebuffersEXT(1, &frameBuffer); - // Restore old shader program variables. - yCbCrProgram->Activate(); - yCbCrProgram->PopRenderTargetOffset(); + // Restore old shader program variables. + yCbCrProgram->Activate(); + yCbCrProgram->PopRenderTargetOffset(); - rgbProgram->Activate(); - rgbProgram->PopRenderTargetOffset(); + rgbProgram->Activate(); + rgbProgram->PopRenderTargetOffset(); - /** - * Render the contents of this container to our destination. - */ - float quadTransform[4][4]; - /* - * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position - * and size. - */ - memset(&quadTransform, 0, sizeof(quadTransform)); - quadTransform[0][0] = (float)GetVisibleRect().width; - quadTransform[1][1] = (float)GetVisibleRect().height; - quadTransform[2][2] = 1.0f; - quadTransform[3][0] = (float)GetVisibleRect().x; - quadTransform[3][1] = (float)GetVisibleRect().y; - quadTransform[3][3] = 1.0f; + /** + * Render the contents of this container to our destination. + */ + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)GetVisibleRect().width; + quadTransform[1][1] = (float)GetVisibleRect().height; + quadTransform[2][2] = 1.0f; + quadTransform[3][0] = (float)GetVisibleRect().x; + quadTransform[3][1] = (float)GetVisibleRect().y; + quadTransform[3][3] = 1.0f; - rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]); + rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]); - sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); + sglWrapper.BindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); - rgbProgram->SetLayerOpacity(GetOpacity()); - rgbProgram->SetLayerTransform(&mTransform._11); - rgbProgram->Apply(); + rgbProgram->SetLayerOpacity(GetOpacity()); + rgbProgram->SetLayerTransform(&mTransform._11); + rgbProgram->Apply(); - sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + sglWrapper.DrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); - // Clean up resources. - sglWrapper.DeleteTextures(1, &containerSurface); + // Clean up resources. + sglWrapper.DeleteTextures(1, &containerSurface); + } } } /* layers */ From e84fd2f2840304d86fa2b5614e5a59cbd674f61e Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Thu, 1 Apr 2010 14:36:26 -0700 Subject: [PATCH 45/69] b=548200; incorrect static array size; r=joe,sr=roc --- content/canvas/src/CustomQS_WebGL.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index 2d479060e59d..c8b8962c5327 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -310,12 +310,12 @@ nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *v if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull)) return JS_FALSE; - if (argc < 7 || (argc > 7 && argc < 9)) + if (argc < 7) return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); jsval *argv = JS_ARGV(cx, vp); - int32 intargs[8]; + int32 intargs[9]; // convert the first six args, they must be ints for (jsuint i = 0; i < 6; ++i) { From d0a3d6d01916b5e6c50c731f409728e2dfa38498 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Thu, 1 Apr 2010 17:53:56 -0400 Subject: [PATCH 46/69] Optimize Core Graphics drawing model OOPP implementation. b=555835 r=josh --- dom/plugins/PluginInstanceChild.cpp | 67 ++++++++++++++++++---------- dom/plugins/PluginInstanceChild.h | 5 +++ dom/plugins/PluginInstanceParent.cpp | 14 ++++-- dom/plugins/PluginInstanceParent.h | 1 + layout/generic/Makefile.in | 1 + layout/generic/nsPluginUtilsOSX.h | 3 ++ layout/generic/nsPluginUtilsOSX.mm | 6 ++- 7 files changed, 68 insertions(+), 29 deletions(-) diff --git a/dom/plugins/PluginInstanceChild.cpp b/dom/plugins/PluginInstanceChild.cpp index c5c84757cbce..3ac521ffb148 100644 --- a/dom/plugins/PluginInstanceChild.cpp +++ b/dom/plugins/PluginInstanceChild.cpp @@ -80,6 +80,7 @@ using mozilla::gfx::SharedDIB; #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg") #elif defined(XP_MACOSX) #include +#include "nsPluginUtilsOSX.h" #endif // defined(XP_MACOSX) PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface, @@ -99,6 +100,10 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface, , mWinlessPopupSurrogateHWND(0) #endif // OS_WIN , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex") +#if defined(OS_MACOSX) + , mShColorSpace(NULL) + , mShContext(NULL) +#endif { memset(&mWindow, 0, sizeof(mWindow)); mData.ndata = (void*) this; @@ -127,6 +132,14 @@ PluginInstanceChild::~PluginInstanceChild() #if defined(OS_WIN) DestroyPluginWindow(); #endif +#if defined(OS_MACOSX) + if (mShColorSpace) { + ::CGColorSpaceRelease(mShColorSpace); + } + if (mShContext) { + ::CGContextRelease(mShContext); + } +#endif } void @@ -585,28 +598,34 @@ PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, PLUGIN_LOG_DEBUG_FUNCTION; AssertPluginThread(); - // We return access to the shared memory buffer after returning. - NPCocoaEvent evcopy = event.event; if (evcopy.type == NPCocoaEventDrawRect) { - CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if (!cSpace) { - PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); - *handled = false; - *rtnmem = mem; - return true; - } - void* cgContextByte = mem.get(); - CGContextRef ctxt = ::CGBitmapContextCreate(cgContextByte, mWindow.width, mWindow.height, 8, mWindow.width * 4, cSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); - ::CGColorSpaceRelease(cSpace); - if (!ctxt) { - PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); - *handled = false; - *rtnmem = mem; - return true; + if (!mShColorSpace) { + mShColorSpace = CreateSystemColorSpace(); + if (!mShColorSpace) { + PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); + *handled = false; + *rtnmem = mem; + return true; + } } - evcopy.data.draw.context = ctxt; + if (!mShContext) { + void* cgContextByte = mem.get(); + mShContext = ::CGBitmapContextCreate(cgContextByte, + mWindow.width, mWindow.height, 8, + mWindow.width * 4, mShColorSpace, + kCGImageAlphaPremultipliedFirst | + kCGBitmapByteOrder32Host); + + if (!mShContext) { + PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); + *handled = false; + *rtnmem = mem; + return true; + } + } + evcopy.data.draw.context = mShContext; } else { PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem.")); *handled = false; @@ -620,11 +639,6 @@ PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, *handled = mPluginIface->event(&mData, reinterpret_cast(&evcopy)); } - // Some events need cleaning up. - if (evcopy.type == NPCocoaEventDrawRect) { - ::CGContextRelease(evcopy.data.draw.context); - } - *rtnmem = mem; return true; } @@ -779,6 +793,13 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) mWindow.clipRect = aWindow.clipRect; mWindow.type = aWindow.type; + if (mShContext) { + // Release the shared context so that it is reallocated + // with the new size. + ::CGContextRelease(mShContext); + mShContext = NULL; + } + if (mPluginIface->setwindow) (void) mPluginIface->setwindow(&mData, &mWindow); diff --git a/dom/plugins/PluginInstanceChild.h b/dom/plugins/PluginInstanceChild.h index ad4ffeebfe43..47bee12bc60b 100644 --- a/dom/plugins/PluginInstanceChild.h +++ b/dom/plugins/PluginInstanceChild.h @@ -320,6 +320,11 @@ private: HBITMAP bmp; } mAlphaExtract; #endif // defined(OS_WIN) +#if defined(OS_MACOSX) +private: + CGColorSpaceRef mShColorSpace; + CGContextRef mShContext; +#endif }; } // namespace plugins diff --git a/dom/plugins/PluginInstanceParent.cpp b/dom/plugins/PluginInstanceParent.cpp index b8ce74cb7fd4..0e4e6e7b7352 100644 --- a/dom/plugins/PluginInstanceParent.cpp +++ b/dom/plugins/PluginInstanceParent.cpp @@ -61,6 +61,7 @@ UINT gOOPPStopNativeLoopEvent = #include #elif defined(XP_MACOSX) #include +#include "nsPluginUtilsOSX.h" #endif // defined(XP_MACOSX) using namespace mozilla::plugins; @@ -80,6 +81,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent, #if defined(XP_MACOSX) , mShWidth(0) , mShHeight(0) + , mShColorSpace(NULL) #endif { } @@ -93,6 +95,9 @@ PluginInstanceParent::~PluginInstanceParent() NS_ASSERTION(!(mPluginHWND || mPluginWndProc), "Subclass was not reset correctly before the dtor was reached!"); #endif +#if defined(OS_MACOSX) + ::CGColorSpaceRelease(mShColorSpace); +#endif } bool @@ -693,15 +698,16 @@ PluginInstanceParent::NPP_HandleEvent(void* event) char* shContextByte = mShSurface.get(); - CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if (!cSpace) { + if (!mShColorSpace) { + mShColorSpace = CreateSystemColorSpace(); + } + if (!mShColorSpace) { PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); return true; } CGContextRef shContext = ::CGBitmapContextCreate(shContextByte, - mShWidth, mShHeight, 8, mShWidth*4, cSpace, + mShWidth, mShHeight, 8, mShWidth*4, mShColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); - ::CGColorSpaceRelease(cSpace); if (!shContext) { PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); return true; diff --git a/dom/plugins/PluginInstanceParent.h b/dom/plugins/PluginInstanceParent.h index 006860011e69..1e33f5a9b7db 100644 --- a/dom/plugins/PluginInstanceParent.h +++ b/dom/plugins/PluginInstanceParent.h @@ -285,6 +285,7 @@ private: Shmem mShSurface; size_t mShWidth; size_t mShHeight; + CGColorSpaceRef mShColorSpace; #endif // definied(OS_MACOSX) }; diff --git a/layout/generic/Makefile.in b/layout/generic/Makefile.in index 9c243918895c..71520d1b8527 100644 --- a/layout/generic/Makefile.in +++ b/layout/generic/Makefile.in @@ -69,6 +69,7 @@ EXPORTS = \ nsIScrollableFrame.h \ nsIStatefulFrame.h \ nsFrameSelection.h \ + nsPluginUtilsOSX.h \ $(NULL) ifdef IBMBIDI diff --git a/layout/generic/nsPluginUtilsOSX.h b/layout/generic/nsPluginUtilsOSX.h index 621d172e7122..6b31fc203869 100644 --- a/layout/generic/nsPluginUtilsOSX.h +++ b/layout/generic/nsPluginUtilsOSX.h @@ -64,6 +64,9 @@ NPBool NS_NPAPI_ConvertPointCocoa(void* inView, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); +// Get the system color space. +CGColorSpaceRef CreateSystemColorSpace(); + // Manages a CARenderer struct _CGLPBufferObject; struct _CGLContextObject; diff --git a/layout/generic/nsPluginUtilsOSX.mm b/layout/generic/nsPluginUtilsOSX.mm index 6e6c01075b43..b4269ccf32a3 100644 --- a/layout/generic/nsPluginUtilsOSX.mm +++ b/layout/generic/nsPluginUtilsOSX.mm @@ -221,15 +221,17 @@ nsCARenderer::~nsCARenderer() { Destroy(); } -CGColorSpaceRef CreateSystemColorSpace () { +CGColorSpaceRef CreateSystemColorSpace() { CMProfileRef system_profile = NULL; CGColorSpaceRef cspace = NULL; if (::CMGetSystemProfile(&system_profile) == noErr) { // Create a colorspace with the systems profile cspace = ::CGColorSpaceCreateWithPlatformColorSpace(system_profile); - ::CMCloseProfile(system_profile); + } else { + // Default to generic + cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); } return cspace; From 7e6d78cb76ac47e704e5b492a415a6f9d451be86 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Wed, 17 Mar 2010 20:08:56 +0100 Subject: [PATCH 47/69] Bug 545228 - Firefox leaks the world on Windows 7. r=robarnold --- .../wintaskbar/WindowsPreviewPerTab.jsm | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/browser/components/wintaskbar/WindowsPreviewPerTab.jsm b/browser/components/wintaskbar/WindowsPreviewPerTab.jsm index 1bffc98e1047..9e1ea1501a34 100644 --- a/browser/components/wintaskbar/WindowsPreviewPerTab.jsm +++ b/browser/components/wintaskbar/WindowsPreviewPerTab.jsm @@ -180,6 +180,12 @@ PreviewController.prototype = { this.linkedBrowser.removeEventListener("pageshow", this, false); this.linkedBrowser.removeEventListener("DOMTitleChanged", this, false); this.linkedBrowser.removeEventListener("MozAfterPaint", this, false); + + // Break cycles, otherwise we end up leaking the window with everything + // attached to it. + delete this.win; + delete this.preview; + delete this.dirtyRegion; }, get wrappedJSObject() { return this; @@ -383,7 +389,6 @@ function TabWindow(win) { this.tabbrowser.tabContainer.addEventListener(this.events[i], this, false); this.tabbrowser.addTabsProgressListener(this); - AeroPeek.windows.push(this); let tabs = this.tabbrowser.tabs; for (let i = 0; i < tabs.length; i++) @@ -402,6 +407,8 @@ TabWindow.prototype = { let tabs = this.tabbrowser.tabs; + this.tabbrowser.removeTabsProgressListener(this); + for (let i = 0; i < this.events.length; i++) this.tabbrowser.tabContainer.removeEventListener(this.events[i], this, false); @@ -589,6 +596,17 @@ var AeroPeek = { this.enabled = this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME); }, + destroy: function destroy() { + this._enabled = false; + + this.prefs.removeObserver(TOGGLE_PREF_NAME, this); + this.prefs.removeObserver(DISABLE_THRESHOLD_PREF_NAME, this); + this.prefs.removeObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this); + + if (this.cacheTimer) + this.cacheTimer.cancel(); + }, + get enabled() { return this._enabled; }, @@ -636,7 +654,10 @@ var AeroPeek = { return; win.gTaskbarTabGroup.destroy(); - win.gTaskbarTabGroup = null; + delete win.gTaskbarTabGroup; + + if (this.windows.length == 0) + this.destroy(); }, resetCacheTimer: function () { From 9d61d8ef0600fa4c6dd10aa9f56fc3d7252c02f5 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Fri, 2 Apr 2010 00:42:22 +0200 Subject: [PATCH 48/69] Bug 529823 - ensure that xpcshell tests using do_get_profile will fire profile shutdown notifications. r=ted --- testing/xpcshell/head.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index e9a474616145..d27eb89ad054 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -433,6 +433,16 @@ function do_register_cleanup(aFunction) * @return nsILocalFile of the profile directory. */ function do_get_profile() { + // Since we have a profile, we will notify profile shutdown topics at + // the end of the current test, to ensure correct cleanup on shutdown. + do_register_cleanup(function() { + let obsSvc = Components.classes["@mozilla.org/observer-service;1"]. + getService(Components.interfaces.nsIObserverService); + obsSvc.notifyObservers(null, "profile-change-net-teardown", null); + obsSvc.notifyObservers(null, "profile-change-teardown", null); + obsSvc.notifyObservers(null, "profile-before-change", null); + }); + let env = Components.classes["@mozilla.org/process/environment;1"] .getService(Components.interfaces.nsIEnvironment); // the python harness sets this in the environment for us From c92ceba9fdf094d781e2390f9cf427c9ed1835db Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Fri, 2 Apr 2010 00:42:25 +0200 Subject: [PATCH 49/69] Bug 556376 - Provide a common head for Places xpcshell-tests. r=dietrich on code changes, blanket-rs=places-team for test changes --- .../places/tests/unit/head_bookmarks.js | 313 ++--------- .../places/tests/unit/test_384370.js | 2 +- ...41-import-export-corrupt-bookmarks-html.js | 2 +- .../unit/test_bookmarksRestoreNotification.js | 10 +- .../places/tests/unit/test_bookmarks_html.js | 2 +- .../unit/test_browserGlue_distribution.js | 11 +- .../tests/unit/test_browserGlue_prefs.js | 3 +- toolkit/components/places/src/utils.js | 156 ++---- toolkit/components/places/tests/Makefile.in | 8 + .../places/tests/autocomplete/head_000.js | 141 ----- .../tests/autocomplete/head_autocomplete.js | 103 +--- .../places/tests/bookmarks/head_bookmarks.js | 168 +----- .../bookmarks/test_405938_restore_queries.js | 2 +- .../test_417228-exclude-from-backup.js | 2 +- .../bookmarks/test_417228-other-roots.js | 2 +- .../test_424958-json-quoted-folders.js | 2 +- .../places/tests/bookmarks/test_448584.js | 2 +- .../places/tests/bookmarks/test_458683.js | 2 +- .../tests/bookmarks/test_restore_guids.js | 2 +- .../tests/expiration/head_expiration.js | 282 +--------- .../expiration/test_annos_expire_history.js | 2 - .../expiration/test_annos_expire_never.js | 2 - .../expiration/test_annos_expire_policy.js | 5 +- .../expiration/test_annos_expire_session.js | 2 - .../tests/expiration/test_notifications.js | 2 - .../test_notifications_onDeleteURI.js | 2 - .../test_notifications_onDeleteVisits.js | 2 - .../tests/expiration/test_pref_interval.js | 1 - .../tests/expiration/test_pref_maxpages.js | 2 - .../tests/expiration/test_removeAllPages.js | 5 +- .../components/places/tests/head_common.js | 504 ++++++++++++++++++ .../places/tests/network/head_network.js | 292 +--------- .../tests/network/test_history_redirects.js | 6 +- .../places/tests/queries/head_queries.js | 353 ++++-------- .../places/tests/queries/stub-test.js | 19 +- .../queries/test_abstime-annotation-domain.js | 14 +- .../queries/test_abstime-annotation-uri.js | 14 +- .../queries/test_containersQueries_sorting.js | 6 +- .../queries/test_excludeReadOnlyFolders.js | 148 ++--- .../tests/queries/test_onlyBookmarked.js | 26 +- .../tests/queries/test_querySerialization.js | 16 +- .../tests/queries/test_redirectsMode.js | 14 +- .../test_results-as-tag-contents-query.js | 18 +- .../tests/queries/test_results-as-visit.js | 8 +- .../tests/queries/test_searchterms-domain.js | 12 +- .../tests/queries/test_searchterms-uri.js | 12 +- .../places/tests/queries/test_sorting.js | 260 ++++----- .../places/tests/queries/test_tags.js | 120 ++--- .../components/places/tests/sync/head_sync.js | 169 +----- ...sync_after_shutdown_with_removeAllPages.js | 8 +- .../places/tests/unit/head_bookmarks.js | 307 +---------- .../places/tests/unit/test_412132.js | 20 +- .../unit/test_doSetAndLoadFaviconForPage.js | 2 +- ...est_doSetAndLoadFaviconForPage_failures.js | 6 +- .../places/tests/unit/test_history.js | 2 +- 55 files changed, 1173 insertions(+), 2423 deletions(-) delete mode 100644 toolkit/components/places/tests/autocomplete/head_000.js create mode 100644 toolkit/components/places/tests/head_common.js diff --git a/browser/components/places/tests/unit/head_bookmarks.js b/browser/components/places/tests/unit/head_bookmarks.js index cf6674f19155..32447e7c2dfa 100644 --- a/browser/components/places/tests/unit/head_bookmarks.js +++ b/browser/components/places/tests/unit/head_bookmarks.js @@ -37,48 +37,24 @@ * * ***** END LICENSE BLOCK ***** */ -version(170); +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; -const NS_APP_BOOKMARKS_50_FILE = "BMarks"; +Cu.import("resource://gre/modules/Services.jsm"); -var Ci = Components.interfaces; -var Cc = Components.classes; -var Cr = Components.results; - -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +// Import common head. +let (commonFile = do_get_file("../../test_places/head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -var gProfD = do_get_profile(); -var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); +// Put any other stuff relative to this test folder below. -var dirProvider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_BOOKMARKS_50_FILE) { - var bmarks = gProfD.clone(); - bmarks.append("bookmarks.html"); - return bmarks; - } - return null; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(dirProvider); -var XULAppInfo = { +// Needed by some test that relies on having an app registered. +let (XULAppInfo = { vendor: "Mozilla", name: "PlacesTest", ID: "{230de50e-4cd1-11dc-8314-0800200c9a66}", @@ -91,80 +67,29 @@ var XULAppInfo = { OS: "XPCShell", XPCOMABI: "noarch-spidermonkey", - QueryInterface: function QueryInterface(iid) { - if (iid.equals(Ci.nsIXULAppInfo) || - iid.equals(Ci.nsIXULRuntime) || - iid.equals(Ci.nsISupports)) - return this; - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; - -var XULAppInfoFactory = { - createInstance: function (outer, iid) { - if (outer != null) - throw Cr.NS_ERROR_NO_AGGREGATION; - return XULAppInfo.QueryInterface(iid); - } -}; - -var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); -registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"), - "XULAppInfo", "@mozilla.org/xre/app-info;1", - XULAppInfoFactory); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIXULAppInfo, + Ci.nsIXULRuntime, + ]) +}) { + let XULAppInfoFactory = { + createInstance: function (outer, iid) { + if (outer != null) + throw Cr.NS_ERROR_NO_AGGREGATION; + return XULAppInfo.QueryInterface(iid); + } + }; + let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"), + "XULAppInfo", "@mozilla.org/xre/app-info;1", + XULAppInfoFactory); } -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks. - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup. - dump_table("moz_bookmarks"); - dump_table("moz_places"); - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - var cc = root.childCount; - // Dump contents if found. - for (var i = 0; i < cc ; i++) { - var node = root.getChild(i); - print("Found unexpected child at " + i + ": " + node.title); - } - do_check_eq(cc, 0); - root.containerOpen = false; -} - -let gTestDir = do_get_cwd(); const FILENAME_BOOKMARKS_HTML = "bookmarks.html"; -let backup_date = new Date().toLocaleFormat("%Y-%m-%d"); -const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json"; +let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) { + const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json"; +} // Smart bookmarks constants. const SMART_BOOKMARKS_VERSION = 2; @@ -174,179 +99,3 @@ const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator. // Default bookmarks constants. const DEFAULT_BOOKMARKS_ON_TOOLBAR = 2; const DEFAULT_BOOKMARKS_ON_MENU = 3; - -/** - * Creates a bookmarks.html file in the profile folder from a given source file. - * - * @param aFilename - * Name of the file to copy to the profile folder. This file must - * exist in the directory that contains the test files. - * - * @return nsIFile object for the file. - */ -function create_bookmarks_html(aFilename) { - if (!aFilename) - do_throw("you must pass a filename to create_bookmarks_html function"); - remove_bookmarks_html(); - let bookmarksHTMLFile = gTestDir.clone(); - bookmarksHTMLFile.append(aFilename); - do_check_true(bookmarksHTMLFile.exists()); - bookmarksHTMLFile.copyTo(gProfD, FILENAME_BOOKMARKS_HTML); - let profileBookmarksHTMLFile = gProfD.clone(); - profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); - do_check_true(profileBookmarksHTMLFile.exists()); - return profileBookmarksHTMLFile; -} - -/** - * Remove bookmarks.html file from the profile folder. - */ -function remove_bookmarks_html() { - let profileBookmarksHTMLFile = gProfD.clone(); - profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); - if (profileBookmarksHTMLFile.exists()) { - profileBookmarksHTMLFile.remove(false); - do_check_false(profileBookmarksHTMLFile.exists()); - } -} - -/** - * Check bookmarks.html file exists in the profile folder. - * - * @return nsIFile object for the file. - */ -function check_bookmarks_html() { - let profileBookmarksHTMLFile = gProfD.clone(); - profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); - do_check_true(profileBookmarksHTMLFile.exists()); - return profileBookmarksHTMLFile; -} - -/** - * Creates a JSON backup in the profile folder folder from a given source file. - * - * @param aFilename - * Name of the file to copy to the profile folder. This file must - * exist in the directory that contains the test files. - * - * @return nsIFile object for the file. - */ -function create_JSON_backup(aFilename) { - if (!aFilename) - do_throw("you must pass a filename to create_JSON_backup function"); - remove_all_JSON_backups(); - let bookmarksBackupDir = gProfD.clone(); - bookmarksBackupDir.append("bookmarkbackups"); - if (!bookmarksBackupDir.exists()) { - bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); - do_check_true(bookmarksBackupDir.exists()); - } - let bookmarksJSONFile = gTestDir.clone(); - bookmarksJSONFile.append(aFilename); - do_check_true(bookmarksJSONFile.exists()); - bookmarksJSONFile.copyTo(bookmarksBackupDir, FILENAME_BOOKMARKS_JSON); - let profileBookmarksJSONFile = bookmarksBackupDir.clone(); - profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); - do_check_true(profileBookmarksJSONFile.exists()); - return profileBookmarksJSONFile; -} - -/** - * Remove bookmarksbackup dir and all backups from the profile folder. - */ -function remove_all_JSON_backups() { - let bookmarksBackupDir = gProfD.clone(); - bookmarksBackupDir.append("bookmarkbackups"); - if (bookmarksBackupDir.exists()) { - bookmarksBackupDir.remove(true); - do_check_false(bookmarksBackupDir.exists()); - } -} - -/** - * Check a JSON backup file for today exists in the profile folder. - * - * @return nsIFile object for the file. - */ -function check_JSON_backup() { - let profileBookmarksJSONFile = gProfD.clone(); - profileBookmarksJSONFile.append("bookmarkbackups"); - profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); - do_check_true(profileBookmarksJSONFile.exists()); - return profileBookmarksJSONFile; -} - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_browserGlue_smartBookmarks.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} diff --git a/browser/components/places/tests/unit/test_384370.js b/browser/components/places/tests/unit/test_384370.js index 6b94290346b2..2bc13b6c948e 100644 --- a/browser/components/places/tests/unit/test_384370.js +++ b/browser/components/places/tests/unit/test_384370.js @@ -73,7 +73,7 @@ function run_test() { //var bookmarksFileOld = do_get_file("bookmarks.large.html"); var bookmarksFileOld = do_get_file("bookmarks.preplaces.html"); // file pointer to a new places-exported json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.exported.json"); // create bookmarks.exported.json diff --git a/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js b/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js index b7399cbbd0b9..841b68756688 100644 --- a/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js +++ b/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js @@ -90,7 +90,7 @@ function run_test() { stmt.finalize(); // Export bookmarks - var bookmarksFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var bookmarksFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); bookmarksFile.append("bookmarks.exported.html"); if (bookmarksFile.exists()) bookmarksFile.remove(false); diff --git a/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js b/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js index f360f0c59693..8b43edb68cf3 100644 --- a/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js +++ b/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js @@ -115,7 +115,7 @@ var tests = [ data: NSIOBSERVER_DATA_JSON, folderId: null, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { PlacesUtils.restoreBookmarksFromJSONFile(this.file); @@ -169,7 +169,7 @@ var tests = [ data: NSIOBSERVER_DATA_HTML, folderId: null, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { importer.importHTMLFromFile(this.file, false); @@ -223,7 +223,7 @@ var tests = [ data: NSIOBSERVER_DATA_HTML_INIT, folderId: null, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { importer.importHTMLFromFile(this.file, true); @@ -284,7 +284,7 @@ var tests = [ finalTopic: NSIOBSERVER_TOPIC_FAILED, data: NSIOBSERVER_DATA_HTML, run: function () { - this.file = dirSvc.get("ProfD", Ci.nsILocalFile); + this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder, "test folder", @@ -407,7 +407,7 @@ function checkBookmarksExist() { * @return The nsILocalFile */ function createFile(aBasename) { - var file = dirSvc.get("ProfD", Ci.nsILocalFile); + var file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); file.append(aBasename); if (file.exists()) file.remove(false); diff --git a/browser/components/places/tests/unit/test_bookmarks_html.js b/browser/components/places/tests/unit/test_bookmarks_html.js index 1c2d94af38c6..2a0922c4f5d8 100644 --- a/browser/components/places/tests/unit/test_bookmarks_html.js +++ b/browser/components/places/tests/unit/test_bookmarks_html.js @@ -104,7 +104,7 @@ function run_test() { // file pointer to legacy bookmarks file var bookmarksFileOld = do_get_file("bookmarks.preplaces.html"); // file pointer to a new places-exported bookmarks file - var bookmarksFileNew = dirSvc.get("ProfD", Ci.nsILocalFile); + var bookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile); bookmarksFileNew.append("bookmarks.exported.html"); // create bookmarks.exported.html diff --git a/browser/components/places/tests/unit/test_browserGlue_distribution.js b/browser/components/places/tests/unit/test_browserGlue_distribution.js index f32857a3f611..e95b61d5aedf 100644 --- a/browser/components/places/tests/unit/test_browserGlue_distribution.js +++ b/browser/components/places/tests/unit/test_browserGlue_distribution.js @@ -47,14 +47,13 @@ const PREF_BMPROCESSED = "distribution.516444.bookmarksProcessed"; const PREF_DISTRIBUTION_ID = "distribution.id"; const TOPIC_FINAL_UI_STARTUP = "final-ui-startup"; -const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete"; const TOPIC_CUSTOMIZATION_COMPLETE = "distribution-customization-complete"; function run_test() { do_test_pending(); // Copy distribution.ini file to our app dir. - let distroDir = dirSvc.get("XCurProcD", Ci.nsIFile); + let distroDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile); distroDir.append("distribution"); let iniFile = distroDir.clone(); iniFile.append("distribution.ini"); @@ -97,13 +96,13 @@ function run_test() { TOPIC_FINAL_UI_STARTUP, null); // Test will continue on customization complete notification. - let observer = { + let cObserver = { observe: function(aSubject, aTopic, aData) { os.removeObserver(this, TOPIC_CUSTOMIZATION_COMPLETE); - continue_test(); + do_execute_soon(continue_test); } } - os.addObserver(observer, TOPIC_CUSTOMIZATION_COMPLETE, false); + os.addObserver(cObserver, TOPIC_CUSTOMIZATION_COMPLETE, false); } } os.addObserver(observer, TOPIC_PLACES_INIT_COMPLETE, false); @@ -145,7 +144,7 @@ function continue_test() { do_register_cleanup(function() { // Remove the distribution file, even if the test failed, otherwise all // next tests will import it. - let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile); + let iniFile = Services.dirsvc.get("XCurProcD", Ci.nsIFile); iniFile.append("distribution"); iniFile.append("distribution.ini"); iniFile.remove(false); diff --git a/browser/components/places/tests/unit/test_browserGlue_prefs.js b/browser/components/places/tests/unit/test_browserGlue_prefs.js index 4dad44c9e625..9a4c668f107d 100644 --- a/browser/components/places/tests/unit/test_browserGlue_prefs.js +++ b/browser/components/places/tests/unit/test_browserGlue_prefs.js @@ -63,8 +63,7 @@ const PREF_IMPORT_BOOKMARKS_HTML = "browser.places.importBookmarksHTML"; const PREF_RESTORE_DEFAULT_BOOKMARKS = "browser.bookmarks.restore_default_bookmarks"; const PREF_SMART_BOOKMARKS_VERSION = "browser.places.smartBookmarksVersion"; const PREF_AUTO_EXPORT_HTML = "browser.bookmarks.autoExportHTML"; -const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete"; -const TOPIC_PLACES_DATABASE_LOCKED = "places-database-locked"; + let tests = []; //------------------------------------------------------------------------------ diff --git a/toolkit/components/places/src/utils.js b/toolkit/components/places/src/utils.js index 6dcce29100d1..46e718489cb1 100644 --- a/toolkit/components/places/src/utils.js +++ b/toolkit/components/places/src/utils.js @@ -40,10 +40,6 @@ * * ***** END LICENSE BLOCK ***** */ -function LOG(str) { - dump("*** " + str + "\n"); -} - var EXPORTED_SYMBOLS = ["PlacesUtils"]; var Ci = Components.interfaces; @@ -52,6 +48,8 @@ var Cr = Components.results; var Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); const EXCLUDE_FROM_BACKUP_ANNO = "places/excludeFromBackup"; const POST_DATA_ANNO = "bookmarkProperties/POSTData"; @@ -106,66 +104,6 @@ var PlacesUtils = { // Place entries as raw URL text TYPE_UNICODE: "text/unicode", - /** - * The Bookmarks Service. - */ - get bookmarks() { - delete this.bookmarks; - return this.bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - }, - - /** - * The Nav History Service. - */ - get history() { - delete this.history; - return this.history = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - }, - - /** - * The Live Bookmark Service. - */ - get livemarks() { - delete this.livemarks; - return this.livemarks = Cc["@mozilla.org/browser/livemark-service;2"]. - getService(Ci.nsILivemarkService); - }, - - /** - * The Annotations Service. - */ - get annotations() { - delete this.annotations; - return this.annotations = Cc["@mozilla.org/browser/annotation-service;1"]. - getService(Ci.nsIAnnotationService); - }, - - /** - * The Favicons Service - */ - get favicons() { - delete this.favicons; - return this.favicons = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); - }, - - /** - * The Places Tagging Service - */ - get tagging() { - delete this.tagging; - return this.tagging = Cc["@mozilla.org/browser/tagging-service;1"]. - getService(Ci.nsITaggingService); - }, - - get observerSvc() { - delete this.observerSvc; - return this.observerSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - }, - /** * Makes a URI from a spec. * @param aSpec @@ -173,21 +111,7 @@ var PlacesUtils = { * @returns A URI object for the spec. */ _uri: function PU__uri(aSpec) { - return Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService). - newURI(aSpec, null, null); - }, - - /** - * String bundle helpers - */ - get _bundle() { - const PLACES_STRING_BUNDLE_URI = - "chrome://places/locale/places.properties"; - delete this._bundle; - return this._bundle = Cc["@mozilla.org/intl/stringbundle;1"]. - getService(Ci.nsIStringBundleService). - createBundle(PLACES_STRING_BUNDLE_URI); + return NetUtil.newURI(aSpec); }, getFormattedString: function PU_getFormattedString(key, params) { @@ -298,7 +222,7 @@ var PlacesUtils = { this.annotations.addObserver(this, false); // observe shutdown, so we can remove the anno observer - this.observerSvc.addObserver(this, "xpcom-shutdown", false); + Services.obs.addObserver(this, "xpcom-shutdown", false); var readOnly = this.annotations.getItemsWithAnnotation(READ_ONLY_ANNO); this.__defineGetter__("_readOnly", function() readOnly); @@ -312,7 +236,7 @@ var PlacesUtils = { observe: function PU_observe(aSubject, aTopic, aData) { if (aTopic == "xpcom-shutdown") { this.annotations.removeObserver(this); - this.observerSvc.removeObserver(this, "xpcom-shutdown"); + Services.obs.removeObserver(this, "xpcom-shutdown"); } }, @@ -717,7 +641,6 @@ var PlacesUtils = { } break; default: - LOG("Cannot unwrap data of type " + type); throw Cr.NS_ERROR_INVALID_ARG; } return nodes; @@ -1495,9 +1418,7 @@ var PlacesUtils = { } return true; }); - } catch(ex) { - LOG(ex); - } + } catch(ex) {} if (annos.length != 0) aJSNode.annos = annos; } @@ -1682,9 +1603,9 @@ var PlacesUtils = { restoreBookmarksFromJSONFile: function PU_restoreBookmarksFromJSONFile(aFile) { let failed = false; - this.observerSvc.notifyObservers(null, - RESTORE_BEGIN_NSIOBSERVER_TOPIC, - RESTORE_NSIOBSERVER_DATA); + Services.obs.notifyObservers(null, + RESTORE_BEGIN_NSIOBSERVER_TOPIC, + RESTORE_NSIOBSERVER_DATA); try { // open file stream @@ -1710,17 +1631,17 @@ var PlacesUtils = { } catch (exc) { failed = true; - this.observerSvc.notifyObservers(null, - RESTORE_FAILED_NSIOBSERVER_TOPIC, - RESTORE_NSIOBSERVER_DATA); + Services.obs.notifyObservers(null, + RESTORE_FAILED_NSIOBSERVER_TOPIC, + RESTORE_NSIOBSERVER_DATA); Cu.reportError("Bookmarks JSON restore failed: " + exc); throw exc; } finally { if (!failed) { - this.observerSvc.notifyObservers(null, - RESTORE_SUCCESS_NSIOBSERVER_TOPIC, - RESTORE_NSIOBSERVER_DATA); + Services.obs.notifyObservers(null, + RESTORE_SUCCESS_NSIOBSERVER_TOPIC, + RESTORE_NSIOBSERVER_DATA); } } }, @@ -1763,9 +1684,7 @@ var PlacesUtils = { }, get folder() { - let dirSvc = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); - let bookmarksBackupDir = dirSvc.get("ProfD", Ci.nsILocalFile); + let bookmarksBackupDir = Services.dirsvc.get("ProfD", Ci.nsILocalFile); bookmarksBackupDir.append("bookmarkbackups"); if (!bookmarksBackupDir.exists()) { bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700); @@ -2014,3 +1933,46 @@ var PlacesUtils = { Cu.import("resource://gre/modules/PlacesDBUtils.jsm"); } }; + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "history", + "@mozilla.org/browser/nav-history-service;1", + "nsINavHistoryService"); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "bhistory", function() { + return PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory); +}); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "ghistory2", function() { + return PlacesUtils.history.QueryInterface(Ci.nsIGlobalHistory2); +}); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "ghistory3", function() { + return PlacesUtils.history.QueryInterface(Ci.nsIGlobalHistory3); +}); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "favicons", + "@mozilla.org/browser/favicon-service;1", + "nsIFaviconService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "bookmarks", + "@mozilla.org/browser/nav-bookmarks-service;1", + "nsINavBookmarksService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "annotations", + "@mozilla.org/browser/annotation-service;1", + "nsIAnnotationService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "tagging", + "@mozilla.org/browser/tagging-service;1", + "nsITaggingService"); + +XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "livemarks", + "@mozilla.org/browser/livemark-service;2", + "nsILivemarkService"); + +XPCOMUtils.defineLazyGetter(PlacesUtils, "_bundle", function() { + const PLACES_STRING_BUNDLE_URI = "chrome://places/locale/places.properties"; + return Cc["@mozilla.org/intl/stringbundle;1"]. + getService(Ci.nsIStringBundleService). + createBundle(PLACES_STRING_BUNDLE_URI); +}); diff --git a/toolkit/components/places/tests/Makefile.in b/toolkit/components/places/tests/Makefile.in index 51db1fe4b8d8..894be665c7aa 100644 --- a/toolkit/components/places/tests/Makefile.in +++ b/toolkit/components/places/tests/Makefile.in @@ -56,6 +56,11 @@ XPCSHELL_TESTS = \ network \ $(NULL) +# Files in the main "tests" folder. +XPCSHELL_TESTS_COMMON = \ + head_common.js \ + $(NULL) + # Simple MochiTests MOCHI_TESTS = \ mochitest/test_bug_411966.html \ @@ -77,3 +82,6 @@ include $(topsrcdir)/config/rules.mk libs:: $(MOCHI_TESTS) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) + +libs:: $(XPCSHELL_TESTS_COMMON) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/xpcshell/$(MODULE) diff --git a/toolkit/components/places/tests/autocomplete/head_000.js b/toolkit/components/places/tests/autocomplete/head_000.js deleted file mode 100644 index 11c2f66ba3c7..000000000000 --- a/toolkit/components/places/tests/autocomplete/head_000.js +++ /dev/null @@ -1,141 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Places. - * - * The Initial Developer of the Original Code is - * Google Inc. - * Portions created by the Initial Developer are Copyright (C) 2005 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brian Ryner - * Dietrich Ayala - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - -const Ci = Components.interfaces; -const Cc = Components.classes; -const Cr = Components.results; - -var profDir = do_get_profile(); - -let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -let provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - let histFile = profDir.clone(); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -// Delete a previously created sqlite file -function clearDB() { - try { - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} diff --git a/toolkit/components/places/tests/autocomplete/head_autocomplete.js b/toolkit/components/places/tests/autocomplete/head_autocomplete.js index a2607e70a4c4..db3209d5a063 100644 --- a/toolkit/components/places/tests/autocomplete/head_autocomplete.js +++ b/toolkit/components/places/tests/autocomplete/head_autocomplete.js @@ -35,22 +35,27 @@ * * ***** END LICENSE BLOCK ***** */ +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + + /** * Header file for autocomplete testcases that create a set of pages with uris, * titles, tags and tests that a given search term matches certain pages. */ -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); - -const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK; -const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED; -const TRANSITION_BOOKMARK = Ci.nsINavHistoryService.TRANSITION_BOOKMARK; -const TRANSITION_EMBED = Ci.nsINavHistoryService.TRANSITION_EMBED; -const TRANSITION_FRAMED_LINK = Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK; -const TRANSITION_REDIRECT_PERMANENT = Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT; -const TRANSITION_REDIRECT_TEMPORARY = Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY; -const TRANSITION_DOWNLOAD = Ci.nsINavHistoryService.TRANSITION_DOWNLOAD; - let current_test = 0; function AutoCompleteInput(aSearches) { @@ -72,12 +77,14 @@ AutoCompleteInput.prototype = { setSelectedIndex: function() {}, get searchCount() { return this.searches.length; }, getSearchAt: function(aIndex) this.searches[aIndex], - QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteInput, Ci.nsIAutoCompletePopup]) + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIAutoCompleteInput, + Ci.nsIAutoCompletePopup, + ]) }; -function toURI(aSpec) -{ - return iosvc.newURI(aSpec, null, null); +function toURI(aSpec) { + return uri(aSpec); } let appendTags = true; @@ -188,72 +195,6 @@ let gDate = new Date(Date.now() - 1000 * 60 * 60) * 1000; // Store the page info for each uri let gPages = []; -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Sets title synchronously for a page in moz_places synchronously. - * History.SetPageTitle uses LAZY_ADD so we can't rely on it. - * - * @param aURI - * An nsIURI to set the title for. - * @param aTitle - * The title to set the page to. - * @throws if the page is not found in the database. - * - * @note this function only exists because we have no API to do this. It should - * be added in bug 421897. - */ -function setPageTitle(aURI, aTitle) { - let dbConn = DBConn(); - // Check that the page exists. - let stmt = dbConn.createStatement( - "SELECT id FROM moz_places_view WHERE url = :url"); - stmt.params.url = aURI.spec; - try { - if (!stmt.executeStep()) { - do_throw("Unable to find page " + aURIString); - return; - } - } - finally { - stmt.finalize(); - } - - // Update the title - stmt = dbConn.createStatement( - "UPDATE moz_places_view SET title = :title WHERE url = :url"); - stmt.params.title = aTitle; - stmt.params.url = aURI.spec; - try { - stmt.execute(); - } - finally { - stmt.finalize(); - } -} /** * Adds a livemark container with a single child, and creates various properties diff --git a/toolkit/components/places/tests/bookmarks/head_bookmarks.js b/toolkit/components/places/tests/bookmarks/head_bookmarks.js index 7aa7828290c4..419f21f48ac2 100644 --- a/toolkit/components/places/tests/bookmarks/head_bookmarks.js +++ b/toolkit/components/places/tests/bookmarks/head_bookmarks.js @@ -37,169 +37,17 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -do_get_profile(); - -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - - try { - return dbConn = storageService.openDatabase(file); - } - catch(ex) {} - - return null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_384228.js", - "test_395593.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} +// Put any other stuff relative to this test folder below. diff --git a/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js b/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js index 1872659e34be..46228c8b29fe 100644 --- a/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js +++ b/toolkit/components/places/tests/bookmarks/test_405938_restore_queries.js @@ -222,7 +222,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js b/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js index 895074cd285c..b21f27351a04 100644 --- a/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js +++ b/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js @@ -145,7 +145,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js b/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js index b665674e2a7b..ce90f547562e 100644 --- a/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js +++ b/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js @@ -157,7 +157,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js b/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js index 60220d682a69..9526fef29c52 100644 --- a/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js +++ b/toolkit/components/places/tests/bookmarks/test_424958-json-quoted-folders.js @@ -91,7 +91,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_448584.js b/toolkit/components/places/tests/bookmarks/test_448584.js index 859d15b03818..ad82bae8ed50 100644 --- a/toolkit/components/places/tests/bookmarks/test_448584.js +++ b/toolkit/components/places/tests/bookmarks/test_448584.js @@ -103,7 +103,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_458683.js b/toolkit/components/places/tests/bookmarks/test_458683.js index a1e42a4767d7..a3415ee9e83f 100644 --- a/toolkit/components/places/tests/bookmarks/test_458683.js +++ b/toolkit/components/places/tests/bookmarks/test_458683.js @@ -134,7 +134,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/bookmarks/test_restore_guids.js b/toolkit/components/places/tests/bookmarks/test_restore_guids.js index 2f2cb6e05261..5eec3c7d54da 100644 --- a/toolkit/components/places/tests/bookmarks/test_restore_guids.js +++ b/toolkit/components/places/tests/bookmarks/test_restore_guids.js @@ -79,7 +79,7 @@ function run_test() { do_check_eq(typeof PlacesUtils, "object"); // make json file - var jsonFile = dirSvc.get("ProfD", Ci.nsILocalFile); + var jsonFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); jsonFile.append("bookmarks.json"); if (jsonFile.exists()) jsonFile.remove(false); diff --git a/toolkit/components/places/tests/expiration/head_expiration.js b/toolkit/components/places/tests/expiration/head_expiration.js index 0a7829f94a8b..799f84b1dd47 100644 --- a/toolkit/components/places/tests/expiration/head_expiration.js +++ b/toolkit/components/places/tests/expiration/head_expiration.js @@ -37,245 +37,21 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -// If there's no location registered for the profile direcotry, register one now. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var profileDir = null; -try { - profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile); -} catch (e) {} -if (!profileDir) { - // Register our own provider for the profile directory. - // It will simply return the current directory. - var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_USER_PROFILE_50_DIR) - return dirSvc.get("CurProcD", Ci.nsIFile); - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("CurProcD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); -} +// Put any other stuff relative to this test folder below. -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = DBConn() - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // Print the column names. - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // Print the row. - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); -} - -/** - * Function tests to see if the place associated with the bookmark with id - * aBookmarkId has the uri aExpectedURI. The event will call do_test_finished() - * if aFinish is true. - * - * @param aBookmarkId - * The bookmark to check against. - * @param aExpectedURI - * The URI we expect to be in moz_places. - * @param aExpected - * Indicates if we expect to get a result or not. - * @param [optional] aFinish - * Indicates if the test should be completed or not. - */ -function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFinish) -{ - let db = DBConn(); - let stmt = db.createStatement( - "SELECT moz_places.url " + - "FROM moz_bookmarks INNER JOIN moz_places " + - "ON moz_bookmarks.fk = moz_places.id " + - "WHERE moz_bookmarks.id = ?1" - ); - stmt.bindInt64Parameter(0, aBookmarkId); - - if (aExpected) { - do_check_true(stmt.executeStep()); - do_check_eq(stmt.getUTF8String(0), aExpectedURI); - } - else { - do_check_false(stmt.executeStep()); - } - stmt.reset(); - stmt.finalize(); - - if (aFinish) - do_test_finished(); -} - -/** - * Function tests to see if the place associated with the visit with id aVisitId - * has the uri aExpectedURI. The event will call do_test_finished() if aFinish is - * true. - * - * @param aVisitId - * The visit to check against. - * @param aExpectedURI - * The URI we expect to be in moz_places. - * @param aExpected - * Indicates if we expect to get a result or not. - * @param [optional] aFinish - * Indicates if the test should be completed or not. - */ -function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) -{ - let db = DBConn(); - let stmt = db.createStatement( - "SELECT moz_places.url " + - "FROM moz_historyvisits INNER JOIN moz_places " + - "ON moz_historyvisits.place_id = moz_places.id " + - "WHERE moz_historyvisits.id = ?1" - ); - stmt.bindInt64Parameter(0, aVisitId); - - if (aExpected) { - do_check_true(stmt.executeStep()); - do_check_eq(stmt.getUTF8String(0), aExpectedURI); - } - else { - do_check_false(stmt.executeStep()); - } - stmt.reset(); - stmt.finalize(); - - if (aFinish) - do_test_finished(); -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - - try { - return dbConn = storageService.openDatabase(file); - } - catch(ex) {} - - return null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// Simulates a Places shutdown. -function shutdownPlaces() -{ - const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown"; - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsIObserver); - hs.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let expire = Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsIObserver); - expire.observe(null, TOPIC_XPCOM_SHUTDOWN, null); -} // Simulates an expiration at shutdown. function shutdownExpiration() @@ -285,6 +61,7 @@ function shutdownExpiration() expire.observe(null, TOPIC_XPCOM_SHUTDOWN, null); } + /** * Causes expiration component to start, otherwise it would wait for the first * history notification. @@ -293,6 +70,7 @@ function force_expiration_start() { Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsISupports); } + /** * Forces an expiration run. */ @@ -304,66 +82,48 @@ function force_expiration_step(aLimit) { expire.observe(null, TOPIC_DEBUG_START_EXPIRATION, aLimit); } -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let observer = { - observe: function(aSubject, aTopic, aData) { - os.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } - }; - os.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages(); -} /** * Expiration preferences helpers. */ -let prefs = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); function setInterval(aNewInterval) { - prefs.setIntPref("places.history.expiration.interval_seconds", aNewInterval); + Services.prefs.setIntPref("places.history.expiration.interval_seconds", aNewInterval); } function getInterval() { - return prefs.getIntPref("places.history.expiration.interval_seconds"); + return Services.prefs.getIntPref("places.history.expiration.interval_seconds"); } function clearInterval() { try { - prefs.clearUserPref("places.history.expiration.interval_seconds"); + Services.prefs.clearUserPref("places.history.expiration.interval_seconds"); } catch(ex) {} } + function setMaxPages(aNewMaxPages) { - prefs.setIntPref("places.history.expiration.max_pages", aNewMaxPages); + Services.prefs.setIntPref("places.history.expiration.max_pages", aNewMaxPages); } function getMaxPages() { - return prefs.getIntPref("places.history.expiration.max_pages"); + return Services.prefs.getIntPref("places.history.expiration.max_pages"); } function clearMaxPages() { try { - prefs.clearUserPref("places.history.expiration.max_pages"); + Services.prefs.clearUserPref("places.history.expiration.max_pages"); } catch(ex) {} } + function setHistoryEnabled(aHistoryEnabled) { - prefs.setBoolPref("places.history.enabled", aHistoryEnabled); + Services.prefs.setBoolPref("places.history.enabled", aHistoryEnabled); } function getHistoryEnabled() { - return prefs.getBoolPref("places.history.enabled"); + return Services.prefs.getBoolPref("places.history.enabled"); } function clearHistoryEnabled() { try { - prefs.clearUserPref("places.history.enabled"); + Services.prefs.clearUserPref("places.history.enabled"); } catch(ex) {} } diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_history.js b/toolkit/components/places/tests/expiration/test_annos_expire_history.js index 2c7a8b1ab4a5..981661ad80a3 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_history.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_history.js @@ -45,8 +45,6 @@ * This expiration policy is only valid for page annotations. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_never.js b/toolkit/components/places/tests/expiration/test_annos_expire_never.js index f0fec795abcd..6bc53a0e08c7 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_never.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_never.js @@ -48,8 +48,6 @@ * the item is removed, thus expiration won't handle this case at all. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_policy.js b/toolkit/components/places/tests/expiration/test_annos_expire_policy.js index 4dec324314ef..b96ee9aca1e6 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_policy.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_policy.js @@ -47,8 +47,6 @@ * - EXPIRE_MONTHS: annotation would be expired after 180 days */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. @@ -76,7 +74,6 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, if (aLastModifiedAgeInDays) lastModifiedDate = (now - (aLastModifiedAgeInDays * 86400 * 1000)) * 1000; - let dbConn = DBConn(); let sql; if (typeof(aIdentifier) == "number") { // Item annotation. @@ -100,7 +97,7 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, else do_throw("Wrong identifier type"); - let stmt = dbConn.createStatement(sql); + let stmt = DBConn().createStatement(sql); stmt.params.id = (typeof(aIdentifier) == "number") ? aIdentifier : aIdentifier.spec; stmt.params.expire_date = expireDate; diff --git a/toolkit/components/places/tests/expiration/test_annos_expire_session.js b/toolkit/components/places/tests/expiration/test_annos_expire_session.js index 31ae86fa1f0b..0529149d9e63 100644 --- a/toolkit/components/places/tests/expiration/test_annos_expire_session.js +++ b/toolkit/components/places/tests/expiration/test_annos_expire_session.js @@ -43,8 +43,6 @@ * Session annotations should be expired when browsing session ends. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_notifications.js b/toolkit/components/places/tests/expiration/test_notifications.js index 6040bbf4aa57..8b9e704d2515 100644 --- a/toolkit/components/places/tests/expiration/test_notifications.js +++ b/toolkit/components/places/tests/expiration/test_notifications.js @@ -43,8 +43,6 @@ * Ensure that History (through category cache) notifies us just once. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js b/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js index b4dffe9981ed..04c07dc1d2db 100644 --- a/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js +++ b/toolkit/components/places/tests/expiration/test_notifications_onDeleteURI.js @@ -43,8 +43,6 @@ * Expiring a full page should fire an onDeleteURI notification. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js b/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js index c71747d352c8..13c9ab64e6e6 100644 --- a/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js +++ b/toolkit/components/places/tests/expiration/test_notifications_onDeleteVisits.js @@ -44,8 +44,6 @@ * onDeleteVisits notification. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_pref_interval.js b/toolkit/components/places/tests/expiration/test_pref_interval.js index ba7774baf269..e88e4eef8032 100644 --- a/toolkit/components/places/tests/expiration/test_pref_interval.js +++ b/toolkit/components/places/tests/expiration/test_pref_interval.js @@ -47,7 +47,6 @@ * If the pref is set to a number <= 0 we will use the default value. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; const MAX_WAIT_SECONDS = 4; const INTERVAL_CUSHION = 2; diff --git a/toolkit/components/places/tests/expiration/test_pref_maxpages.js b/toolkit/components/places/tests/expiration/test_pref_maxpages.js index 6c7f194f1ecb..54fbf712f60b 100644 --- a/toolkit/components/places/tests/expiration/test_pref_maxpages.js +++ b/toolkit/components/places/tests/expiration/test_pref_maxpages.js @@ -47,8 +47,6 @@ * If the pref is set to a number < 0 we will use the default value. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. diff --git a/toolkit/components/places/tests/expiration/test_removeAllPages.js b/toolkit/components/places/tests/expiration/test_removeAllPages.js index d7914996f82d..cdf6302b0b1d 100644 --- a/toolkit/components/places/tests/expiration/test_removeAllPages.js +++ b/toolkit/components/places/tests/expiration/test_removeAllPages.js @@ -44,8 +44,6 @@ * annos. */ -const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. @@ -73,7 +71,6 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, if (aLastModifiedAgeInDays) lastModifiedDate = (now - (aLastModifiedAgeInDays * 86400 * 1000)) * 1000; - let dbConn = DBConn(); let sql; if (typeof(aIdentifier) == "number") { // Item annotation. @@ -97,7 +94,7 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy, else do_throw("Wrong identifier type"); - let stmt = dbConn.createStatement(sql); + let stmt = DBConn().createStatement(sql); stmt.params.id = (typeof(aIdentifier) == "number") ? aIdentifier : aIdentifier.spec; stmt.params.expire_date = expireDate; diff --git a/toolkit/components/places/tests/head_common.js b/toolkit/components/places/tests/head_common.js new file mode 100644 index 000000000000..51cd5c0a1ad3 --- /dev/null +++ b/toolkit/components/places/tests/head_common.js @@ -0,0 +1,504 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Places Unit Tests Code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +const NS_APP_USER_PROFILE_50_DIR = "ProfD"; +const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; +const NS_APP_HISTORY_50_FILE = "UHist"; +const NS_APP_BOOKMARKS_50_FILE = "BMarks"; + +const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; +const TOPIC_SHUTDOWN = "xpcom-shutdown"; +const TOPIC_PLACES_INIT_COMPLETE = "places-init-complete"; +const TOPIC_PLACES_DATABASE_LOCKED = "places-database-locked"; + +// Shortcuts to transactions type. +const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK; +const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED; +const TRANSITION_BOOKMARK = Ci.nsINavHistoryService.TRANSITION_BOOKMARK; +const TRANSITION_EMBED = Ci.nsINavHistoryService.TRANSITION_EMBED; +const TRANSITION_FRAMED_LINK = Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK; +const TRANSITION_REDIRECT_PERMANENT = Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT; +const TRANSITION_REDIRECT_TEMPORARY = Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY; +const TRANSITION_DOWNLOAD = Ci.nsINavHistoryService.TRANSITION_DOWNLOAD; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyGetter(this, "Services", function() { + Cu.import("resource://gre/modules/Services.jsm"); + return Services; +}); + +XPCOMUtils.defineLazyGetter(this, "NetUtil", function() { + Cu.import("resource://gre/modules/NetUtil.jsm"); + return NetUtil; +}); + +XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() { + Cu.import("resource://gre/modules/utils.js"); + return PlacesUtils; +}); + + +function LOG(aMsg) { + aMsg = ("*** PLACES TESTS: " + aMsg); + Services.console.logStringMessage(aMsg); + print(aMsg); +} + + +let gTestDir = do_get_cwd(); + + +// Initialize profile. +let gProfD = do_get_profile(); + +// Add our own dirprovider for old history.dat. +let (provider = { + getFile: function(prop, persistent) { + persistent.value = true; + if (prop == NS_APP_HISTORY_50_FILE) { + let histFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + histFile.append("history.dat"); + return histFile; + } + throw Cr.NS_ERROR_FAILURE; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]) + }) +{ + Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIDirectoryService). + QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); +} + + +// Remove any old database. +clearDB(); + + +/** + * Shortcut to create a nsIURI. + * + * @param aSpec + * URLString of the uri. + */ +function uri(aSpec) NetUtil.newURI(aSpec); + + +/** + * Gets the database connection. If the Places connection is invalid it will + * try to create a new connection. + * + * @return The database connection or null if unable to get one. + */ +function DBConn() { + let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) + .DBConnection; + if (db.connectionReady) + return db; + + // If the database has been closed, then we need to open a new connection. + let file = Services.dirsvc.get('ProfD', Ci.nsIFile); + file.append("places.sqlite"); + return Services.storage.openDatabase(file); +}; + + +/** + * Reads the data from the specified nsIFile, and returns an array of bytes. + * + * @param aFile + * The nsIFile to read from. + */ +function readFileData(aFile) { + let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + // init the stream as RD_ONLY, -1 == default permissions. + inputStream.init(aFile, 0x01, -1, null); + let size = inputStream.available(); + + // use a binary input stream to grab the bytes. + let bis = Cc["@mozilla.org/binaryinputstream;1"]. + createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(inputStream); + + let bytes = bis.readByteArray(size); + + if (size != bytes.length) + throw "Didn't read expected number of bytes"; + + return bytes; +} + + +/** + * Compares two arrays, and returns true if they are equal. + * + * @param aArray1 + * First array to compare. + * @param aArray2 + * Second array to compare. + */ +function compareArrays(aArray1, aArray2) { + if (aArray1.length != aArray2.length) { + print("compareArrays: array lengths differ\n"); + return false; + } + + for (let i = 0; i < aArray1.length; i++) { + if (aArray1[i] != aArray2[i]) { + print("compareArrays: arrays differ at index " + i + ": " + + "(" + aArray1[i] + ") != (" + aArray2[i] +")\n"); + return false; + } + } + + return true; +} + + +/** + * Deletes a previously created sqlite file from the profile folder. + */ +function clearDB() { + try { + let file = Services.dirsvc.get('ProfD', Ci.nsIFile); + file.append("places.sqlite"); + if (file.exists()) + file.remove(false); + } catch(ex) { dump("Exception: " + ex); } +} + + +/** + * Dumps the rows of a table out to the console. + * + * @param aName + * The name of the table or view to output. + */ +function dump_table(aName) +{ + let stmt = DBConn().createStatement("SELECT * FROM " + aName); + + print("\n*** Printing data from " + aName); + let count = 0; + while (stmt.executeStep()) { + let columns = stmt.numEntries; + + if (count == 0) { + // Print the column names. + for (let i = 0; i < columns; i++) + dump(stmt.getColumnName(i) + "\t"); + dump("\n"); + } + + // Print the rows. + for (let i = 0; i < columns; i++) { + switch (stmt.getTypeOfIndex(i)) { + case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: + dump("NULL\t"); + break; + case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: + dump(stmt.getInt64(i) + "\t"); + break; + case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: + dump(stmt.getDouble(i) + "\t"); + break; + case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: + dump(stmt.getString(i) + "\t"); + break; + } + } + dump("\n"); + + count++; + } + print("*** There were a total of " + count + " rows of data.\n"); + + stmt.finalize(); +} + + +/** + * Removes all bookmarks and checks for correct cleanup + */ +function remove_all_bookmarks() { + let PU = PlacesUtils; + // Clear all bookmarks + PU.bookmarks.removeFolderChildren(PU.bookmarks.bookmarksMenuFolder); + PU.bookmarks.removeFolderChildren(PU.bookmarks.toolbarFolder); + PU.bookmarks.removeFolderChildren(PU.bookmarks.unfiledBookmarksFolder); + // Check for correct cleanup + check_no_bookmarks(); +} + + +/** + * Checks that we don't have any bookmark + */ +function check_no_bookmarks() { + let query = PlacesUtils.history.getNewQuery(); + let folders = [ + PlacesUtils.bookmarks.toolbarFolder, + PlacesUtils.bookmarks.bookmarksMenuFolder, + PlacesUtils.bookmarks.unfiledBookmarksFolder, + ]; + query.setFolders(folders, 3); + let options = PlacesUtils.history.getNewQueryOptions(); + options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; + let root = PlacesUtils.history.executeQuery(query, options).root; + root.containerOpen = true; + do_check_eq(root.childCount, 0); + root.containerOpen = false; +} + + + +/** + * Sets title synchronously for a page in moz_places synchronously. + * History.SetPageTitle uses LAZY_ADD so we can't rely on it. + * + * @param aURI + * An nsIURI to set the title for. + * @param aTitle + * The title to set the page to. + * @throws if the page is not found in the database. + * + * @note this function only exists because we have no API to do this. It should + * be added in bug 421897. + */ +function setPageTitle(aURI, aTitle) { + // Check that the page exists. + let stmt = DBConn().createStatement( + "SELECT id FROM moz_places_view WHERE url = :url" + ); + stmt.params.url = aURI.spec; + try { + if (!stmt.executeStep()) { + do_throw("Unable to find page " + aURI.spec); + return; + } + } + finally { + stmt.finalize(); + } + + // Update the title + stmt = DBConn().createStatement( + "UPDATE moz_places_view SET title = :title WHERE url = :url" + ); + stmt.params.title = aTitle; + stmt.params.url = aURI.spec; + try { + stmt.execute(); + } + finally { + stmt.finalize(); + } +} + + +/** + * Clears history invoking callback when done. + * + * @param aCallback + * Callback function to be called once clear history has finished. + */ +function waitForClearHistory(aCallback) { + let observer = { + observe: function(aSubject, aTopic, aData) { + Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED); + aCallback(); + } + }; + Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); + + PlacesUtils.bhistory.removeAllPages(); +} + + +/** + * Simulates a Places shutdown. + */ +function shutdownPlaces() +{ + let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsIObserver); + hs.observe(null, TOPIC_SHUTDOWN, null); + + let sync = Cc["@mozilla.org/places/sync;1"]. + getService(Ci.nsIObserver); + sync.observe(null, TOPIC_SHUTDOWN, null); + + let expire = Cc["@mozilla.org/places/expiration;1"]. + getService(Ci.nsIObserver); + expire.observe(null, TOPIC_SHUTDOWN, null); +} + + +/** + * Creates a bookmarks.html file in the profile folder from a given source file. + * + * @param aFilename + * Name of the file to copy to the profile folder. This file must + * exist in the directory that contains the test files. + * + * @return nsIFile object for the file. + */ +function create_bookmarks_html(aFilename) { + if (!aFilename) + do_throw("you must pass a filename to create_bookmarks_html function"); + remove_bookmarks_html(); + let bookmarksHTMLFile = gTestDir.clone(); + bookmarksHTMLFile.append(aFilename); + do_check_true(bookmarksHTMLFile.exists()); + bookmarksHTMLFile.copyTo(gProfD, FILENAME_BOOKMARKS_HTML); + let profileBookmarksHTMLFile = gProfD.clone(); + profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); + do_check_true(profileBookmarksHTMLFile.exists()); + return profileBookmarksHTMLFile; +} + + +/** + * Remove bookmarks.html file from the profile folder. + */ +function remove_bookmarks_html() { + let profileBookmarksHTMLFile = gProfD.clone(); + profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); + if (profileBookmarksHTMLFile.exists()) { + profileBookmarksHTMLFile.remove(false); + do_check_false(profileBookmarksHTMLFile.exists()); + } +} + + +/** + * Check bookmarks.html file exists in the profile folder. + * + * @return nsIFile object for the file. + */ +function check_bookmarks_html() { + let profileBookmarksHTMLFile = gProfD.clone(); + profileBookmarksHTMLFile.append(FILENAME_BOOKMARKS_HTML); + do_check_true(profileBookmarksHTMLFile.exists()); + return profileBookmarksHTMLFile; +} + + +/** + * Creates a JSON backup in the profile folder folder from a given source file. + * + * @param aFilename + * Name of the file to copy to the profile folder. This file must + * exist in the directory that contains the test files. + * + * @return nsIFile object for the file. + */ +function create_JSON_backup(aFilename) { + if (!aFilename) + do_throw("you must pass a filename to create_JSON_backup function"); + remove_all_JSON_backups(); + let bookmarksBackupDir = gProfD.clone(); + bookmarksBackupDir.append("bookmarkbackups"); + if (!bookmarksBackupDir.exists()) { + bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); + do_check_true(bookmarksBackupDir.exists()); + } + let bookmarksJSONFile = gTestDir.clone(); + bookmarksJSONFile.append(aFilename); + do_check_true(bookmarksJSONFile.exists()); + bookmarksJSONFile.copyTo(bookmarksBackupDir, FILENAME_BOOKMARKS_JSON); + let profileBookmarksJSONFile = bookmarksBackupDir.clone(); + profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); + do_check_true(profileBookmarksJSONFile.exists()); + return profileBookmarksJSONFile; +} + + +/** + * Remove bookmarksbackup dir and all backups from the profile folder. + */ +function remove_all_JSON_backups() { + let bookmarksBackupDir = gProfD.clone(); + bookmarksBackupDir.append("bookmarkbackups"); + if (bookmarksBackupDir.exists()) { + bookmarksBackupDir.remove(true); + do_check_false(bookmarksBackupDir.exists()); + } +} + + +/** + * Check a JSON backup file for today exists in the profile folder. + * + * @return nsIFile object for the file. + */ +function check_JSON_backup() { + let profileBookmarksJSONFile = gProfD.clone(); + profileBookmarksJSONFile.append("bookmarkbackups"); + profileBookmarksJSONFile.append(FILENAME_BOOKMARKS_JSON); + do_check_true(profileBookmarksJSONFile.exists()); + return profileBookmarksJSONFile; +} + + +// These tests are known to randomly fail due to bug 507790 when database +// flushes are active, so we turn off syncing for them. +let (randomFailingSyncTests = [ + "test_multi_word_tags.js", + "test_removeVisitsByTimeframe.js", + "test_utils_getURLsForContainerNode.js", + "test_exclude_livemarks.js", + "test_402799.js", + "test_results-as-visit.js", + "test_sorting.js", + "test_redirectsMode.js", + "test_384228.js", + "test_395593.js", + "test_containersQueries_sorting.js", + "test_browserGlue_smartBookmarks.js", + "test_browserGlue_distribution.js", +]) { + let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; + if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { + print("Test " + currentTestFilename + + " is known random due to bug 507790, disabling PlacesDBFlush."); + let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); + sync.observe(null, "places-debug-stop-sync", null); + } +} diff --git a/toolkit/components/places/tests/network/head_network.js b/toolkit/components/places/tests/network/head_network.js index f6bda7eb5fd2..8832f3f521a7 100644 --- a/toolkit/components/places/tests/network/head_network.js +++ b/toolkit/components/places/tests/network/head_network.js @@ -37,292 +37,16 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - -// This will also define Cc, Ci. +// This will also define Cc, Ci, Cr, Cu. do_load_httpd_js(); -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -do_get_profile(); +// Put any other stuff relative to this test folder below. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("ProfD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -/* - * Reads the data from the specified nsIFile, and returns an array of bytes. - */ -function readFileData(aFile) { - var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - // init the stream as RD_ONLY, -1 == default permissions. - inputStream.init(aFile, 0x01, -1, null); - var size = inputStream.available(); - - // use a binary input stream to grab the bytes. - var bis = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(inputStream); - - var bytes = bis.readByteArray(size); - - if (size != bytes.length) - throw "Didn't read expected number of bytes"; - - return bytes; -} - -/* - * Compares two arrays, and returns true if they are equal. - */ -function compareArrays(aArray1, aArray2) { - if (aArray1.length != aArray2.length) { - print("compareArrays: array lengths differ\n"); - return false; - } - - for (var i = 0; i < aArray1.length; i++) { - if (aArray1[i] != aArray2[i]) { - print("compareArrays: arrays differ at index " + i + ": " + - "(" + aArray1[i] + ") != (" + aArray2[i] +")\n"); - return false; - } - } - - return true; -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Sets title synchronously for a page in moz_places synchronously. - * History.SetPageTitle uses LAZY_ADD so we can't rely on it. - * - * @param aURI - * An nsIURI to set the title for. - * @param aTitle - * The title to set the page to. - * @throws if the page is not found in the database. - * - * @note this function only exists because we have no API to do this. It should - * be added in bug 421897. - */ -function setPageTitle(aURI, aTitle) { - let dbConn = DBConn(); - // Check that the page exists. - let stmt = dbConn.createStatement( - "SELECT id FROM moz_places_view WHERE url = :url"); - stmt.params.url = aURI.spec; - try { - if (!stmt.executeStep()) { - do_throw("Unable to find page " + aURIString); - return; - } - } - finally { - stmt.finalize(); - } - - // Update the title - stmt = dbConn.createStatement( - "UPDATE moz_places_view SET title = :title WHERE url = :url"); - stmt.params.title = aTitle; - stmt.params.url = aURI.spec; - try { - stmt.execute(); - } - finally { - stmt.finalize(); - } -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let observer = { - observe: function(aSubject, aTopic, aData) { - os.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } - }; - os.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages(); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} diff --git a/toolkit/components/places/tests/network/test_history_redirects.js b/toolkit/components/places/tests/network/test_history_redirects.js index 2bead1dd08b1..224d5aa356aa 100644 --- a/toolkit/components/places/tests/network/test_history_redirects.js +++ b/toolkit/components/places/tests/network/test_history_redirects.js @@ -44,9 +44,6 @@ let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. let bh = hs.QueryInterface(Ci.nsIBrowserHistory); let ghist3 = hs.QueryInterface(Ci.nsIGlobalHistory3); -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/NetUtil.jsm"); - const PERMA_REDIR_PATH = "/permaredir"; const TEMP_REDIR_PATH = "/tempredir"; const FOUND_PATH = "/found"; @@ -110,8 +107,7 @@ function run_test() { } function continue_test() { - let dbConn = DBConn(); - let stmt = dbConn.createStatement( + let stmt = DBConn().createStatement( "SELECT v.id, h.url, v.from_visit, v.visit_date, v.visit_type, v.session " + "FROM moz_historyvisits_view v " + "JOIN moz_places_view h on h.id = v.place_id " + diff --git a/toolkit/components/places/tests/queries/head_queries.js b/toolkit/components/places/tests/queries/head_queries.js index e6f42974df38..35754e733ac9 100644 --- a/toolkit/components/places/tests/queries/head_queries.js +++ b/toolkit/components/places/tests/queries/head_queries.js @@ -35,12 +35,22 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + // Some Useful Date constants - PRTime uses microseconds, so convert const DAY_MICROSEC = 86400000000; @@ -52,100 +62,6 @@ const tomorrow = today + DAY_MICROSEC; const old = today - (DAY_MICROSEC * 3); const futureday = today + (DAY_MICROSEC * 3); -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - print(aMsg); -} - -// If there's no location registered for the profile directory, register one now. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var profileDir = do_get_profile(); - -var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = profileDir.clone(); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -// Get our interfaces -try { - var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); -} catch(ex) { - do_throw("Could not get history service\n"); -} - -try { - var bhistsvc = histsvc.QueryInterface(Ci.nsIBrowserHistory); -} catch(ex) { - do_throw("Could not get browser history service\n"); -} - -try { - var annosvc = Cc["@mozilla.org/browser/annotation-service;1"]. - getService(Ci.nsIAnnotationService); -} catch(ex) { - do_throw("Could not get annotation service\n"); -} - -try { - var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); -} catch (ex) { - do_throw("Could not get bookmark service\n"); -} - -try { - var tagssvc = Cc["@mozilla.org/browser/tagging-service;1"]. - getService(Ci.nsITaggingService); -} catch(ex) { - do_throw("Could not get tagging service\n"); -} - -try { - var faviconsvc = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); -} catch(ex) { - do_throw("Could not get favicon service\n"); -} - -try { - var lmsvc = Cc["@mozilla.org/browser/livemark-service;2"]. - getService(Ci.nsILivemarkService); -} catch(ex) { - do_throw("Could not get livemark service\n"); -} /** * Generalized function to pull in an array of objects of data and push it into @@ -154,6 +70,7 @@ try { */ function populateDB(aArray) { aArray.forEach(function(data) { + dump_table("moz_bookmarks"); try { // make the data object into a query data object in order to create proper // default values for anything left unspecified @@ -161,23 +78,21 @@ function populateDB(aArray) { if (qdata.isVisit) { // Then we should add a visit for this node var referrer = qdata.referrer ? uri(qdata.referrer) : null; - var visitId = histsvc.addVisit(uri(qdata.uri), qdata.lastVisit, - referrer, qdata.transType, - qdata.isRedirect, qdata.sessionID); + var visitId = PlacesUtils.history.addVisit(uri(qdata.uri), qdata.lastVisit, + referrer, qdata.transType, + qdata.isRedirect, qdata.sessionID); do_check_true(visitId > 0); if (qdata.title && !qdata.isDetails) { // Set the page title synchronously, otherwise setPageTitle is LAZY. - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("UPDATE moz_places_view " + - "SET title = :title WHERE url = :url"); + let stmt = DBConn().createStatement( + "UPDATE moz_places_view SET title = :title WHERE url = :url" + ); stmt.params.title = qdata.title; stmt.params.url = qdata.uri; try { stmt.execute(); // Force a notification so results are updated. - histsvc.runInBatchMode({runBatched: function(){}}, null); + PlacesUtils.history.runInBatchMode({runBatched: function(){}}, null); } finally { stmt.finalize(); @@ -186,17 +101,14 @@ function populateDB(aArray) { if (qdata.visitCount && !qdata.isDetails) { // Set a fake visit_count, this is not a real count but can be used // to test sorting by visit_count. - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("UPDATE moz_places_view " + - "SET visit_count = :vc WHERE url = :url"); + let stmt = DBConn().createStatement( + "UPDATE moz_places_view SET visit_count = :vc WHERE url = :url"); stmt.params.vc = qdata.visitCount; stmt.params.url = qdata.uri; try { stmt.execute(); // Force a notification so results are updated. - histsvc.runInBatchMode({runBatched: function(){}}, null); + PlacesUtils.history.runInBatchMode({runBatched: function(){}}, null); } finally { stmt.finalize(); @@ -206,57 +118,71 @@ function populateDB(aArray) { if (qdata.isDetails) { // Then we add extraneous page details for testing - bhistsvc.addPageWithDetails(uri(qdata.uri), qdata.title, qdata.lastVisit); + PlacesUtils.history.addPageWithDetails(uri(qdata.uri), + qdata.title, qdata.lastVisit); } if (qdata.markPageAsTyped){ - bhistsvc.markPageAsTyped(uri(qdata.uri)); + PlacesUtils.bhistory.markPageAsTyped(uri(qdata.uri)); } if (qdata.hidePage){ - bhistsvc.hidePage(uri(qdata.uri)); + PlacesUtils.bhistory.hidePage(uri(qdata.uri)); } if (qdata.isPageAnnotation) { if (qdata.removeAnnotation) - annosvc.removePageAnnotation(uri(qdata.uri), qdata.annoName); + PlacesUtils.annotations.removePageAnnotation(uri(qdata.uri), + qdata.annoName); else { - annosvc.setPageAnnotation(uri(qdata.uri), - qdata.annoName, qdata.annoVal, - qdata.annoFlags, qdata.annoExpiration); + PlacesUtils.annotations.setPageAnnotation(uri(qdata.uri), + qdata.annoName, + qdata.annoVal, + qdata.annoFlags, + qdata.annoExpiration); } } if (qdata.isItemAnnotation) { if (qdata.removeAnnotation) - annosvc.removeItemAnnotation(qdata.itemId, qdata.annoName); + PlacesUtils.annotations.removeItemAnnotation(qdata.itemId, + qdata.annoName); else { - annosvc.setItemAnnotation(qdata.itemId, qdata.annoName, qdata.annoVal, - qdata.annoFlags, qdata.annoExpiration); + PlacesUtils.annotations.setItemAnnotation(qdata.itemId, + qdata.annoName, + qdata.annoVal, + qdata.annoFlags, + qdata.annoExpiration); } } if (qdata.isPageBinaryAnnotation) { if (qdata.removeAnnotation) - annosvc.removePageAnnotation(uri(qdata.uri), qdata.annoName); + PlacesUtils.annotations.removePageAnnotation(uri(qdata.uri), + qdata.annoName); else { - annosvc.setPageAnnotationBinary(uri(qdata.uri), qdata.annoName, - qdata.binarydata, - qdata.binaryDataLength, - qdata.annoMimeType, qdata.annoFlags, - qdata.annoExpiration); + PlacesUtils.annotations.setPageAnnotationBinary(uri(qdata.uri), + qdata.annoName, + qdata.binarydata, + qdata.binaryDataLength, + qdata.annoMimeType, + qdata.annoFlags, + qdata.annoExpiration); } } if (qdata.isItemBinaryAnnotation) { if (qdata.removeAnnotation) - annosvc.removeItemAnnotation(qdata.itemId, qdata.annoName); + PlacesUtils.annotations.removeItemAnnotation(qdata.itemId, + qdata.annoName); else { - annosvc.setItemAnnotationBinary(qdata.itemId, qdata.annoName, - qdata.binaryData, - qdata.binaryDataLength, - qdata.annoMimeType, qdata.annoFlags, - qdata.annoExpiration); + PlacesUtils.annotations.setItemAnnotationBinary(qdata.itemId, + qdata.annoName, + qdata.binaryData, + qdata.binaryDataLength, + qdata.annoMimeType, + qdata.annoFlags, + qdata.annoExpiration); } } @@ -264,42 +190,54 @@ function populateDB(aArray) { // Not planning on doing deep testing of favIcon service so these two // calls should be sufficient to get favicons into the database try { - faviconsvc.setFaviconData(uri(qdata.faviconURI), qdata.favicon, - qdata.faviconLen, qdata.faviconMimeType, - qdata.faviconExpiration); + PlacesUtils.favicons.setFaviconData(uri(qdata.faviconURI), + qdata.favicon, + qdata.faviconLen, + qdata.faviconMimeType, + qdata.faviconExpiration); } catch (ex) {} - faviconsvc.setFaviconUrlForPage(uri(qdata.uri), uri(qdata.faviconURI)); + PlacesUtils.favicons.setFaviconUrlForPage(uri(qdata.uri), + uri(qdata.faviconURI)); } if (qdata.isFolder) { - let folderId = bmsvc.createFolder(qdata.parentFolder, qdata.title, qdata.index); + let folderId = PlacesUtils.bookmarks.createFolder(qdata.parentFolder, + qdata.title, + qdata.index); if (qdata.readOnly) - bmsvc.setFolderReadonly(folderId, true); + PlacesUtils.bookmarks.setFolderReadonly(folderId, true); } if (qdata.isLivemark) { - lmsvc.createLivemark(qdata.parentFolder, qdata.title, uri(qdata.uri), - uri(qdata.feedURI), qdata.index); + PlacesUtils.livemarks.createLivemark(qdata.parentFolder, + qdata.title, + uri(qdata.uri), + uri(qdata.feedURI), + qdata.index); } if (qdata.isBookmark) { - let itemId = bmsvc.insertBookmark(qdata.parentFolder, uri(qdata.uri), - qdata.index, qdata.title); + let itemId = PlacesUtils.bookmarks.insertBookmark(qdata.parentFolder, + uri(qdata.uri), + qdata.index, + qdata.title); if (qdata.keyword) - bmsvc.setKeywordForBookmark(itemId, qdata.keyword); + PlacesUtils.bookmarks.setKeywordForBookmark(itemId, qdata.keyword); if (qdata.dateAdded) - bmsvc.setItemDateAdded(itemId, qdata.dateAdded); + PlacesUtils.bookmarks.setItemDateAdded(itemId, qdata.dateAdded); if (qdata.lastModified) - bmsvc.setItemLastModified(itemId, qdata.lastModified); + PlacesUtils.bookmarks.setItemLastModified(itemId, qdata.lastModified); } if (qdata.isTag) { - tagssvc.tagURI(uri(qdata.uri), qdata.tagArray); + PlacesUtils.tagging.tagURI(uri(qdata.uri), qdata.tagArray); } if (qdata.isDynContainer) { - bmsvc.createDynamicContainer(qdata.parentFolder, qdata.title, - qdata.contractId, qdata.index); + PlacesUtils.bookmarks.createDynamicContainer(qdata.parentFolder, + qdata.title, + qdata.contractId, + qdata.index); } } catch (ex) { // use the data object here in case instantiation of qdata failed @@ -309,6 +247,7 @@ function populateDB(aArray) { }); // End of function and array } + /** * The Query Data Object - this object encapsulates data for our queries and is * used to parameterize our calls to the Places APIs to put data into the @@ -326,7 +265,7 @@ function queryData(obj) { this.uri = obj.uri ? obj.uri : ""; this.lastVisit = obj.lastVisit ? obj.lastVisit : today; this.referrer = obj.referrer ? obj.referrer : null; - this.transType = obj.transType ? obj.transType : histsvc.TRANSITION_TYPED; + this.transType = obj.transType ? obj.transType : Ci.nsINavHistoryService.TRANSITION_TYPED; this.isRedirect = obj.isRedirect ? obj.isRedirect : false; this.sessionID = obj.sessionID ? obj.sessionID : 0; this.isDetails = obj.isDetails ? obj.isDetails : false; @@ -357,9 +296,10 @@ function queryData(obj) { this.faviconExpiration = obj.faviconExpiration ? obj.faviconExpiration : futureday; this.isLivemark = obj.isLivemark ? obj.isLivemark : false; - this.parentFolder = obj.parentFolder ? obj.parentFolder : bmsvc.placesRoot; + this.parentFolder = obj.parentFolder ? obj.parentFolder + : PlacesUtils.placesRootId; this.feedURI = obj.feedURI ? obj.feedURI : ""; - this.index = obj.index ? obj.index : bmsvc.DEFAULT_INDEX; + this.index = obj.index ? obj.index : PlacesUtils.bookmarks.DEFAULT_INDEX; this.isFolder = obj.isFolder ? obj.isFolder : false; this.contractId = obj.contractId ? obj.contractId : ""; this.lastModified = obj.lastModified ? obj.lastModified : today; @@ -376,6 +316,7 @@ function queryData(obj) { // All attributes are set in the constructor above queryData.prototype = { } + /** * Helper function to compare an array of query objects with a result set. * It assumes the array of query objects contains the SAME SORT as the result @@ -409,7 +350,7 @@ function compareArrayToResult(aArray, aRoot) { aArray[i].lastVisit != child.time) do_throw("Expected " + aArray[i].lastVisit + " found " + child.time); if (aArray[i].hasOwnProperty("index") && - aArray[i].index != bmsvc.DEFAULT_INDEX && + aArray[i].index != PlacesUtils.bookmarks.DEFAULT_INDEX && aArray[i].index != child.bookmarkIndex) do_throw("Expected " + aArray[i].index + " found " + child.bookmarkIndex); @@ -422,6 +363,7 @@ function compareArrayToResult(aArray, aRoot) { LOG("Comparing Array to Results passes"); } + /** * Helper function to check to see if one object either is or is not in the * result set. It can accept either a queryData object or an array of queryData @@ -454,6 +396,7 @@ function isInResult(aQueryData, aRoot) { return rv; } + /** * A nice helper function for debugging things. It LOGs the contents of a * result set. @@ -474,107 +417,3 @@ function displayResultSet(aRoot) { aRoot.getChild(i).title + " Visit Time: " + aRoot.getChild(i).time); } } - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - // Clear all bookmarks - bmsvc.removeFolderChildren(bmsvc.bookmarksMenuFolder); - bmsvc.removeFolderChildren(bmsvc.toolbarFolder); - bmsvc.removeFolderChildren(bmsvc.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder, bmsvc.bookmarksMenuFolder, bmsvc.unfiledBookmarksFolder], 3); - var options = histsvc.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = histsvc.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_results-as-visit.js", - "test_sorting.js", - "test_redirectsMode.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} diff --git a/toolkit/components/places/tests/queries/stub-test.js b/toolkit/components/places/tests/queries/stub-test.js index 0132006a8781..367c81426ffd 100644 --- a/toolkit/components/places/tests/queries/stub-test.js +++ b/toolkit/components/places/tests/queries/stub-test.js @@ -43,12 +43,15 @@ * Here is an example of using these to create some bookmark folders: */ // Create Folder1 from root - bmsvc.createFolder(bmsvc.placesRoot, "Folder 1", bmsvc.DEFAULT_INDEX); - var folder1Id = bmsvc.getChildFolder(bmsvc.placesRoot, "Folder 1"); + PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId, "Folder 1", + PlacesUtils.bookmarks.DEFAULT_INDEX); + var folder1Id = PlacesUtils.bookmarks.getChildFolder(PlacesUtils.placesRootId, + "Folder 1"); // Make Folder 1a a child of Folder 1 - bmsvc.createFolder(folder1Id, "Folder 1a", bmsvc.DEFAULT_INDEX); - var folder1aId = bmsvc.getChildFolder(folder1Id, "Folder 1a"); + PlacesUtils.bookmarks.createFolder(folder1Id, "Folder 1a", + PlacesUtils.bookmarks.DEFAULT_INDEX); + var folder1aId = PlacesUtils.bookmarks.getChildFolder(folder1Id, "Folder 1a"); /** * The next thing we do is create a test database for us. Each test runs with @@ -90,15 +93,15 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // Set query attributes here... // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); // Set queryOptions attributes here // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -130,7 +133,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); // Close the container when finished root.containerOpen = false; diff --git a/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js b/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js index f926cdef9334..3ea3dc14d531 100644 --- a/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js +++ b/toolkit/components/places/tests/queries/test_abstime-annotation-domain.js @@ -92,7 +92,7 @@ var testData = [ // Test subdomain included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "moz", isRedirect: true, uri: "http://mail.foo.com/redirect", lastVisit: jan11_800, - transType: histsvc.TRANSITION_LINK}, + transType: PlacesUtils.history.TRANSITION_LINK}, // Test subdomain inclued at the leading time edge {isInQuery: true, isVisit: true, isDetails: true, @@ -158,11 +158,11 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.beginTime = beginTime; query.endTime = endTime; - query.beginTimeReference = histsvc.TIME_RELATIVE_EPOCH; - query.endTimeReference = histsvc.TIME_RELATIVE_EPOCH; + query.beginTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; + query.endTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; query.searchTerms = "moz"; query.domain = "foo.com"; query.domainIsHost = false; @@ -170,7 +170,7 @@ function run_test() { query.annotationIsNot = true; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_URI_ASCENDING; options.resultType = options.RESULTS_AS_URI; // The next two options should be ignored @@ -178,7 +178,7 @@ function run_test() { // options.excludeItems = true; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -246,7 +246,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); LOG("LiveUpdate by updating title in batch mode"); do_check_eq(isInResult({uri: "http://foo.com/changeme2"}, root), true); diff --git a/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js b/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js index abe066152aa5..afe0b382986e 100644 --- a/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js +++ b/toolkit/components/places/tests/queries/test_abstime-annotation-uri.js @@ -96,7 +96,7 @@ var testData = [ // Test uri included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "moz", isRedirect: true, uri: "http://foo.com/redirect", lastVisit: jan11_800, - transType: histsvc.TRANSITION_LINK}, + transType: PlacesUtils.history.TRANSITION_LINK}, // Test leading time edge with tag string is included {isInQuery: true, isVisit: true, isDetails: true, title: "taggariffic", @@ -156,11 +156,11 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.beginTime = beginTime; query.endTime = endTime; - query.beginTimeReference = histsvc.TIME_RELATIVE_EPOCH; - query.endTimeReference = histsvc.TIME_RELATIVE_EPOCH; + query.beginTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; + query.endTimeReference = PlacesUtils.history.TIME_RELATIVE_EPOCH; query.searchTerms = "moz"; query.uri = uri("http://foo.com"); query.uriIsPrefix = true; @@ -168,7 +168,7 @@ function run_test() { query.annotationIsNot = true; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_URI_ASCENDING; options.resultType = options.RESULTS_AS_URI; // The next two options should be ignored @@ -176,7 +176,7 @@ function run_test() { // options.excludeItems = true; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -243,7 +243,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); LOG("LiveUpdate by updating title in batch mode"); do_check_eq(isInResult({uri: "http://foo.com/changeme2"}, root), true); diff --git a/toolkit/components/places/tests/queries/test_containersQueries_sorting.js b/toolkit/components/places/tests/queries/test_containersQueries_sorting.js index 3f4c6897ccb0..61da4f446ee3 100644 --- a/toolkit/components/places/tests/queries/test_containersQueries_sorting.js +++ b/toolkit/components/places/tests/queries/test_containersQueries_sorting.js @@ -199,13 +199,13 @@ function test_query_callback(aSequence) { } // Create a new query with required options. - var query = histsvc.getNewQuery(); - var options = histsvc.getNewQueryOptions(); + var query = PlacesUtils.history.getNewQuery(); + var options = PlacesUtils.history.getNewQueryOptions(); options.resultType = resultType.value; options.sortingMode = sortingMode.value; // Compare resultset with expectedData. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; diff --git a/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js b/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js index 61a7a9070467..f6baba717c24 100644 --- a/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js +++ b/toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js @@ -1,74 +1,74 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Places Test Code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Clint Talbert - * Marco Bonardo - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -// The test data for our database, note that the ordering of the results that -// will be returned by the query (the isInQuery: true objects) is IMPORTANT. -// see compareArrayToResult in head_queries.js for more info. -var testData = [ - // Normal folder - { isInQuery: true, isFolder: true, title: "Folder 1", - parentFolder: bmsvc.toolbarFolder }, - - // Read only folder - { isInQuery: false, isFolder: true, title: "Folder 2 RO", - parentFolder: bmsvc.toolbarFolder, readOnly: true } -]; - -function run_test() { - populateDB(testData); - - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); - - // Options - var options = histsvc.getNewQueryOptions(); - options.excludeQueries = true; - options.excludeReadOnlyFolders = true; - - // Results - var result = histsvc.executeQuery(query, options); - var root = result.root; - displayResultSet(root); - // The readonly folder should not be in our result set. - do_check_eq(1, root.childCount); - do_check_eq("Folder 1", root.getChild(0).title); - - root.containerOpen = false; -} +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Places Test Code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Clint Talbert + * Marco Bonardo + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +// The test data for our database, note that the ordering of the results that +// will be returned by the query (the isInQuery: true objects) is IMPORTANT. +// see compareArrayToResult in head_queries.js for more info. +var testData = [ + // Normal folder + { isInQuery: true, isFolder: true, title: "Folder 1", + parentFolder: PlacesUtils.toolbarFolderId }, + + // Read only folder + { isInQuery: false, isFolder: true, title: "Folder 2 RO", + parentFolder: PlacesUtils.toolbarFolderId, readOnly: true } +]; + +function run_test() { + populateDB(testData); + + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.toolbarFolderId], 1); + + // Options + var options = PlacesUtils.history.getNewQueryOptions(); + options.excludeQueries = true; + options.excludeReadOnlyFolders = true; + + // Results + var result = PlacesUtils.history.executeQuery(query, options); + var root = result.root; + displayResultSet(root); + // The readonly folder should not be in our result set. + do_check_eq(1, root.childCount); + do_check_eq("Folder 1", root.getChild(0).title); + + root.containerOpen = false; +} diff --git a/toolkit/components/places/tests/queries/test_onlyBookmarked.js b/toolkit/components/places/tests/queries/test_onlyBookmarked.js index b120fbfc0928..0369c421de70 100644 --- a/toolkit/components/places/tests/queries/test_onlyBookmarked.js +++ b/toolkit/components/places/tests/queries/test_onlyBookmarked.js @@ -52,16 +52,16 @@ var testData = [ // Add a bookmark that should be in the results { isBookmark: true, uri: "http://bookmarked.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.toolbarFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: true }, // Add a bookmark that should not be in the results { isBookmark: true, uri: "http://bookmarked-elsewhere.com/", - parentFolder: bmsvc.bookmarksMenuFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarksMenuFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: false }, @@ -83,16 +83,16 @@ function run_test() { populateDB(testData); // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.toolbarFolderId], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.queryType = options.QUERY_TYPE_HISTORY; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -111,16 +111,16 @@ function run_test() { //Add a bookmark that should show up { isBookmark: true, uri: "http://bookmarked2.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.toolbarFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: true }, //Add a bookmark that should not show up { isBookmark: true, uri: "http://bookmarked-elsewhere2.com/", - parentFolder: bmsvc.bookmarksMenuFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarksMenuFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "", isInQuery: false } ]; @@ -150,7 +150,7 @@ function run_test() { } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); // re-query and test LOG("begin batched test"); diff --git a/toolkit/components/places/tests/queries/test_querySerialization.js b/toolkit/components/places/tests/queries/test_querySerialization.js index 0ab4d514b582..779afb1931b6 100644 --- a/toolkit/components/places/tests/queries/test_querySerialization.js +++ b/toolkit/components/places/tests/queries/test_querySerialization.js @@ -286,10 +286,10 @@ const querySwitches = [ aQuery.setFolders([], 0); }, function (aQuery, aQueryOptions) { - aQuery.setFolders([bmsvc.placesRoot], 1); + aQuery.setFolders([PlacesUtils.placesRootId], 1); }, function (aQuery, aQueryOptions) { - aQuery.setFolders([bmsvc.placesRoot, bmsvc.tagsFolder], 2); + aQuery.setFolders([PlacesUtils.placesRootId, PlacesUtils.tagsFolderId], 2); } ] }, @@ -754,8 +754,8 @@ function runQuerySequences(aHowManyLo, aHowManyHi) // ] cartProd(runs, function (runSet) { // Create a new query, apply the switches in runSet, and test it. - var query = histsvc.getNewQuery(); - var opts = histsvc.getNewQueryOptions(); + var query = PlacesUtils.history.getNewQuery(); + var opts = PlacesUtils.history.getNewQueryOptions(); for (let i = 0; i < runSet.length; i++) { runSet[i](query, opts); } @@ -793,13 +793,13 @@ function runQuerySequences(aHowManyLo, aHowManyHi) */ function serializeDeserialize(aQueryArr, aQueryOptions) { - var queryStr = histsvc.queriesToQueryString(aQueryArr, - aQueryArr.length, - aQueryOptions); + var queryStr = PlacesUtils.history.queriesToQueryString(aQueryArr, + aQueryArr.length, + aQueryOptions); print(" " + queryStr); var queryArr2 = {}; var opts2 = {}; - histsvc.queryStringToQueries(queryStr, queryArr2, {}, opts2); + PlacesUtils.history.queryStringToQueries(queryStr, queryArr2, {}, opts2); queryArr2 = queryArr2.value; opts2 = opts2.value; diff --git a/toolkit/components/places/tests/queries/test_redirectsMode.js b/toolkit/components/places/tests/queries/test_redirectsMode.js index 45063e6351ca..5a5ab41dc076 100644 --- a/toolkit/components/places/tests/queries/test_redirectsMode.js +++ b/toolkit/components/places/tests/queries/test_redirectsMode.js @@ -109,8 +109,8 @@ function check_results_callback(aSequence) { } // Create a new query with required options. - let query = histsvc.getNewQuery(); - let options = histsvc.getNewQueryOptions(); + let query = PlacesUtils.history.getNewQuery(); + let options = PlacesUtils.history.getNewQueryOptions(); options.includeHidden = includeHidden; options.redirectsMode = redirectsMode; options.sortingMode = sortingMode; @@ -118,7 +118,7 @@ function check_results_callback(aSequence) { options.maxResults = maxResults; // Compare resultset with expectedData. - let result = histsvc.executeQuery(query, options); + let result = PlacesUtils.history.executeQuery(query, options); let root = result.root; root.containerOpen = true; compareArrayToResult(expectedData, root); @@ -212,7 +212,7 @@ function cartProd(aSequences, aCallback) */ function add_visits_to_database() { // Clean up the database. - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); // We don't really bother on this, but we need a time to add visits. @@ -271,8 +271,8 @@ function add_visits_to_database() { // Add an unvisited bookmark in the database, it should never appear. visits.push({ isBookmark: true, uri: "http://unvisited.bookmark.com/", - parentFolder: bmsvc.bookmarksMenuFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarksMenuFolderId, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "Unvisited Bookmark", isInQuery: false }); @@ -302,6 +302,6 @@ function run_test() { check_results_callback); // Clean up so we can't pollute next tests. - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); } diff --git a/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js b/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js index 939806d618e2..e50b09f75658 100644 --- a/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js +++ b/toolkit/components/places/tests/queries/test_results-as-tag-contents-query.js @@ -72,10 +72,10 @@ var testData = [ function getIdForTag(aTagName) { var id = -1; - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.tagsFolder], 1); - var options = histsvc.getNewQueryOptions(); - var root = histsvc.executeQuery(query, options).root; + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.tagsFolderId], 1); + var options = PlacesUtils.history.getNewQueryOptions(); + var root = PlacesUtils.history.executeQuery(query, options).root; root.containerOpen = true; var cc = root.childCount; do_check_eq(root.childCount, 2); @@ -100,12 +100,12 @@ function run_test() { let tagId = getIdForTag("bugzilla"); do_check_true(tagId > 0); - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.resultType = options.RESULTS_AS_TAG_CONTENTS; - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.setFolders([tagId], 1); - var root = histsvc.executeQuery(query, options).root; + var root = PlacesUtils.history.executeQuery(query, options).root; root.containerOpen = true; displayResultSet(root); @@ -148,13 +148,13 @@ function run_test() { populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_false(isInResult({uri: "http://fooz.com/"}, root)); do_check_true(isInResult({uri: "http://foo.com/changeme2.html"}, root)); // Test removing a tag updates us. LOG("Delete item outside of batch"); - tagssvc.untagURI(uri("http://foo.com/changeme2.html"), ["bugzilla"]); + PlacesUtils.tagging.untagURI(uri("http://foo.com/changeme2.html"), ["bugzilla"]); do_check_false(isInResult({uri: "http://foo.com/changeme2.html"}, root)); root.containerOpen = false; diff --git a/toolkit/components/places/tests/queries/test_results-as-visit.js b/toolkit/components/places/tests/queries/test_results-as-visit.js index 80df4049847d..ab61ebfbf2ca 100644 --- a/toolkit/components/places/tests/queries/test_results-as-visit.js +++ b/toolkit/components/places/tests/queries/test_results-as-visit.js @@ -66,17 +66,17 @@ function createTestData() { function run_test() { createTestData(); populateDB(testData); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.searchTerms = "moz"; query.minVisits = 2; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_VISITCOUNT_ASCENDING; options.resultType = options.RESULTS_AS_VISIT; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -127,7 +127,7 @@ function createTestData() { populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_false(isInResult({uri: "http://foo.mail.com/changeme1.html"}, root)); do_check_true(isInResult({uri: "http://foo.mail.com/changeme3.html"}, root)); diff --git a/toolkit/components/places/tests/queries/test_searchterms-domain.js b/toolkit/components/places/tests/queries/test_searchterms-domain.js index ed6fe5f45f07..413d6a67d48d 100644 --- a/toolkit/components/places/tests/queries/test_searchterms-domain.js +++ b/toolkit/components/places/tests/queries/test_searchterms-domain.js @@ -53,7 +53,7 @@ // Test subdomain included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "amozzie", isRedirect: true, uri: "http://mail.foo.com/redirect", lastVisit: old, - referrer: "http://myreferrer.com", transType: histsvc.TRANSITION_LINK}, + referrer: "http://myreferrer.com", transType: PlacesUtils.history.TRANSITION_LINK}, // Test subdomain inclued, search term at end {isInQuery: true, isVisit: true, isDetails: true, @@ -89,18 +89,18 @@ */ function run_test() { populateDB(testData); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.searchTerms = "moz"; query.domain = "foo.com"; query.domainIsHost = false; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_DATE_ASCENDING; options.resultType = options.RESULTS_AS_URI; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -116,7 +116,7 @@ function run_test() { // Add to the query set LOG("Adding item to query") var change1 = [{isVisit: true, isDetails: true, uri: "http://foo.com/added.htm", - title: "moz", transType: histsvc.TRANSITION_LINK}]; + title: "moz", transType: PlacesUtils.history.TRANSITION_LINK}]; populateDB(change1); do_check_true(isInResult(change1, root)); @@ -140,7 +140,7 @@ function run_test() { populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_true(isInResult({uri: "http://foo.com/changeme2.htm"}, root)); do_check_true(isInResult({uri: "http://mail.foo.com/yiihah"}, root)); do_check_false(isInResult({uri: "ftp://foo.com/ftp"}, root)); diff --git a/toolkit/components/places/tests/queries/test_searchterms-uri.js b/toolkit/components/places/tests/queries/test_searchterms-uri.js index 5481f560e2dc..90368a379e82 100644 --- a/toolkit/components/places/tests/queries/test_searchterms-uri.js +++ b/toolkit/components/places/tests/queries/test_searchterms-uri.js @@ -48,7 +48,7 @@ // Test subdomain included with isRedirect=true, different transtype {isInQuery: true, isVisit: true, isDetails: true, title: "amozzie", isRedirect: true, uri: "http://foo.com/redirect", lastVisit: old, - referrer: "http://myreferrer.com", transType: histsvc.TRANSITION_LINK}, + referrer: "http://myreferrer.com", transType: PlacesUtils.history.TRANSITION_LINK}, // Test www. style URI is included, with a tag {isInQuery: true, isVisit: true, isDetails: true, isTag: true, @@ -85,18 +85,18 @@ */ function run_test() { populateDB(testData); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.searchTerms = "moz"; query.uri = uri("http://foo.com"); query.uriIsPrefix = true; // Options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = options.SORT_BY_DATE_ASCENDING; options.resultType = options.RESULTS_AS_URI; // Results - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; @@ -112,7 +112,7 @@ // Add to the query set LOG("Adding item to query") var change1 = [{isVisit: true, isDetails: true, uri: "http://foo.com/added.htm", - title: "moz", transType: histsvc.TRANSITION_LINK}]; + title: "moz", transType: PlacesUtils.history.TRANSITION_LINK}]; populateDB(change1); do_check_true(isInResult(change1, root)); @@ -137,7 +137,7 @@ populateDB(batchchange); } }; - histsvc.runInBatchMode(updateBatch, null); + PlacesUtils.history.runInBatchMode(updateBatch, null); do_check_true(isInResult({uri: "http://foo.com/changeme2.htm"}, root)); do_check_true(isInResult({uri: "http://foo.com/yiihah"}, root)); do_check_false(isInResult({uri: "http://foo.com/redirect"}, root)); diff --git a/toolkit/components/places/tests/queries/test_sorting.js b/toolkit/components/places/tests/queries/test_sorting.js index cc9e251da8a1..f06db6760dcf 100644 --- a/toolkit/components/places/tests/queries/test_sorting.js +++ b/toolkit/components/places/tests/queries/test_sorting.js @@ -50,24 +50,24 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y", keyword: "b", isInQuery: true }, { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "z", keyword: "a", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "x", keyword: "c", isInQuery: true }, @@ -81,16 +81,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -113,30 +113,30 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y", isInQuery: true }, { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "z", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "x", isInQuery: true }, // if titles are equal, should fall back to URI { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y", isInQuery: true }, ]; @@ -154,16 +154,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -190,7 +190,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, uri: "http://example.com/c1", lastVisit: timeInMicroseconds - 2, @@ -200,7 +200,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, uri: "http://example.com/a", lastVisit: timeInMicroseconds - 1, @@ -210,7 +210,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, uri: "http://example.com/b", lastVisit: timeInMicroseconds - 3, @@ -221,7 +221,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, uri: "http://example.com/c2", lastVisit: timeInMicroseconds - 2, @@ -232,7 +232,7 @@ tests.push({ { isVisit: true, isDetails: true, isBookmark: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, uri: "http://example.com/c2", lastVisit: timeInMicroseconds - 2, @@ -254,16 +254,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -291,21 +291,21 @@ tests.push({ isDetails: true, lastVisit: timeInMicroseconds, uri: "http://example.com/b", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, title: "y", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, title: "x", isInQuery: true }, { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, title: "z", isInQuery: true }, @@ -315,14 +315,14 @@ tests.push({ isDetails: true, lastVisit: timeInMicroseconds + 1, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, title: "x", isInQuery: true }, // if no URI (e.g., node is a folder), should fall back to title { isFolder: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, title: "a", isInQuery: true }, @@ -332,14 +332,14 @@ tests.push({ isDetails: true, lastVisit: timeInMicroseconds + 1, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 5, title: "x", isInQuery: true }, // if no URI and titles are equal, should fall back to bookmark index { isFolder: true, - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 6, title: "a", isInQuery: true }, @@ -361,15 +361,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -397,7 +397,7 @@ tests.push({ uri: "http://example.com/a", lastVisit: timeInMicroseconds, title: "z", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, isInQuery: true }, @@ -405,7 +405,7 @@ tests.push({ uri: "http://example.com/c", lastVisit: timeInMicroseconds, title: "x", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, isInQuery: true }, @@ -413,7 +413,7 @@ tests.push({ uri: "http://example.com/b1", lastVisit: timeInMicroseconds, title: "y1", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, isInQuery: true }, @@ -422,7 +422,7 @@ tests.push({ uri: "http://example.com/b2", lastVisit: timeInMicroseconds + 1, title: "y2a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, isInQuery: true }, @@ -431,7 +431,7 @@ tests.push({ uri: "http://example.com/b2", lastVisit: timeInMicroseconds + 1, title: "y2b", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, isInQuery: true }, ]; @@ -447,36 +447,36 @@ tests.push({ // This function in head_queries.js creates our database with the above data populateDB(this._unsortedData); // add visits to increase visit count - histsvc.addVisit(uri("http://example.com/a"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); - histsvc.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, - histsvc.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/a"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b1"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/b2"), timeInMicroseconds + 1, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); + PlacesUtils.history.addVisit(uri("http://example.com/c"), timeInMicroseconds, null, + PlacesUtils.history.TRANSITION_TYPED, false, 0); }, check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -501,24 +501,24 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "z", keyword: "a", isInQuery: true }, { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "x", keyword: "c", isInQuery: true }, { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y9", keyword: "b", isInQuery: true }, @@ -526,8 +526,8 @@ tests.push({ // without a keyword, should fall back to title { isBookmark: true, uri: "http://example.com/null2", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "null8", keyword: null, isInQuery: true }, @@ -535,8 +535,8 @@ tests.push({ // without a keyword, should fall back to title { isBookmark: true, uri: "http://example.com/null1", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "null9", keyword: null, isInQuery: true }, @@ -544,8 +544,8 @@ tests.push({ // if keywords are equal, should fall back to title { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "y8", keyword: "b", isInQuery: true }, @@ -566,16 +566,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -601,7 +601,7 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, title: "y1", dateAdded: timeInMicroseconds -1, @@ -609,7 +609,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, title: "z", dateAdded: timeInMicroseconds - 2, @@ -617,7 +617,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, title: "x", dateAdded: timeInMicroseconds, @@ -626,7 +626,7 @@ tests.push({ // if dateAddeds are equal, should fall back to title { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, title: "y2", dateAdded: timeInMicroseconds - 1, @@ -635,7 +635,7 @@ tests.push({ // if dateAddeds and titles are equal, should fall back to bookmark index { isBookmark: true, uri: "http://example.com/b3", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, title: "y3", dateAdded: timeInMicroseconds - 1, @@ -656,16 +656,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -691,7 +691,7 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://example.com/b1", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 0, title: "y1", lastModified: timeInMicroseconds -1, @@ -699,7 +699,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/a", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 1, title: "z", lastModified: timeInMicroseconds - 2, @@ -707,7 +707,7 @@ tests.push({ { isBookmark: true, uri: "http://example.com/c", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 2, title: "x", lastModified: timeInMicroseconds, @@ -716,7 +716,7 @@ tests.push({ // if lastModifieds are equal, should fall back to title { isBookmark: true, uri: "http://example.com/b2", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 3, title: "y2", lastModified: timeInMicroseconds - 1, @@ -726,7 +726,7 @@ tests.push({ // index { isBookmark: true, uri: "http://example.com/b3", - parentFolder: bmsvc.toolbarFolder, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, index: 4, title: "y3", lastModified: timeInMicroseconds - 1, @@ -747,16 +747,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -781,8 +781,8 @@ tests.push({ this._unsortedData = [ { isBookmark: true, uri: "http://url2.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title x", isTag: true, tagArray: ["x", "y", "z"], @@ -790,8 +790,8 @@ tests.push({ { isBookmark: true, uri: "http://url1a.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title y1", isTag: true, tagArray: ["a", "b"], @@ -799,15 +799,15 @@ tests.push({ { isBookmark: true, uri: "http://url3a.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title w1", isInQuery: true }, { isBookmark: true, uri: "http://url0.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title z", isTag: true, tagArray: ["a", "y", "z"], @@ -816,8 +816,8 @@ tests.push({ // if tags are equal, should fall back to title { isBookmark: true, uri: "http://url1b.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title y2", isTag: true, tagArray: ["b", "a"], @@ -826,8 +826,8 @@ tests.push({ // if tags are equal, should fall back to title { isBookmark: true, uri: "http://url3b.com/", - parentFolder: bmsvc.toolbarFolder, - index: bmsvc.DEFAULT_INDEX, + parentFolder: PlacesUtils.bookmarks.toolbarFolder, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, title: "title w2", isInQuery: true }, ]; @@ -847,16 +847,16 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); - query.setFolders([bmsvc.toolbarFolder], 1); + var query = PlacesUtils.history.getNewQuery(); + query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); query.onlyBookmarked = true; // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -944,15 +944,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1026,15 +1026,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1108,15 +1108,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1190,15 +1190,15 @@ tests.push({ check: function() { // Query - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); // query options - var options = histsvc.getNewQueryOptions(); + var options = PlacesUtils.history.getNewQueryOptions(); options.sortingAnnotation = "sorting"; options.sortingMode = this._sortingMode; // Results - this gets the result set and opens it for reading and modification. - var result = histsvc.executeQuery(query, options); + var result = PlacesUtils.history.executeQuery(query, options); var root = result.root; root.containerOpen = true; compareArrayToResult(this._sortedData, root); @@ -1216,7 +1216,7 @@ tests.push({ function prepare_for_next_test() { // Execute cleanup tasks - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); } diff --git a/toolkit/components/places/tests/queries/test_tags.js b/toolkit/components/places/tests/queries/test_tags.js index 774e0702571b..f16614f824f6 100644 --- a/toolkit/components/places/tests/queries/test_tags.js +++ b/toolkit/components/places/tests/queries/test_tags.js @@ -71,14 +71,14 @@ var gTests = [ desc: "Invalid calls to tags setter should fail", run: function () { try { - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.tags = null; do_throw(" Passing null to SetTags should fail"); } catch (exc) {} try { - query = histsvc.getNewQuery(); + query = PlacesUtils.history.getNewQuery(); query.tags = "this should not work"; do_throw(" Passing a string to SetTags should fail"); } @@ -126,7 +126,7 @@ var gTests = [ var str = Cc["@mozilla.org/supports-string;1"]. createInstance(Ci.nsISupportsString); str.data = "foo"; - query = histsvc.getNewQuery(); + query = PlacesUtils.history.getNewQuery(); query.tags = str; do_throw(" Passing nsISupportsString to SetTags should fail"); } @@ -377,32 +377,32 @@ var gTests = [ let nsiuri = uri(pURI); addVisit(nsiuri); if (tags) - tagssvc.tagURI(nsiuri, tags); + PlacesUtils.tagging.tagURI(nsiuri, tags); } print(' Querying for "foo" should match only /2 and /3'); var [query, opts] = makeQuery(["foo"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bar" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bar"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bogus" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bogus"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "baz" should match only /3'); [query, opts] = makeQuery(["foo", "baz"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/3"]); print(' Querying for "bogus" should match all'); [query, opts] = makeQuery(["bogus"], true); - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/1", "http://example.com/2", "http://example.com/3"]); @@ -411,7 +411,7 @@ var gTests = [ for (let [pURI, tags] in Iterator(urisAndTags)) { let nsiuri = uri(pURI); if (tags) - tagssvc.untagURI(nsiuri, tags); + PlacesUtils.tagging.untagURI(nsiuri, tags); } cleanDatabase(); } @@ -431,37 +431,37 @@ var gTests = [ let nsiuri = uri(pURI); addBookmark(nsiuri); if (tags) - tagssvc.tagURI(nsiuri, tags); + PlacesUtils.tagging.tagURI(nsiuri, tags); } print(' Querying for "foo" should match only /2 and /3'); var [query, opts] = makeQuery(["foo"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bar" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bar"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "bogus" should match only /2 and /3'); [query, opts] = makeQuery(["foo", "bogus"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/2", "http://example.com/3"]); print(' Querying for "foo" and "baz" should match only /3'); [query, opts] = makeQuery(["foo", "baz"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/3"]); print(' Querying for "bogus" should match all'); [query, opts] = makeQuery(["bogus"], true); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, ["http://example.com/1", "http://example.com/2", "http://example.com/3"]); @@ -470,7 +470,7 @@ var gTests = [ for (let [pURI, tags] in Iterator(urisAndTags)) { let nsiuri = uri(pURI); if (tags) - tagssvc.untagURI(nsiuri, tags); + PlacesUtils.tagging.untagURI(nsiuri, tags); } cleanDatabase(); } @@ -484,26 +484,26 @@ var gTests = [ print(" Add bookmark and tag it normally"); addBookmark(TEST_URI); - tagssvc.tagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.tagURI(TEST_URI, [tagName]); print(" Manually create tag folder with same name as tag and insert " + "bookmark"); - var dupTagId = bmsvc.createFolder(bmsvc.tagsFolder, - tagName, - bmsvc.DEFAULT_INDEX); + var dupTagId = PlacesUtils.bookmarks.createFolder(PlacesUtils.tagsFolderId, + tagName, + Ci.nsINavBookmarksService.DEFAULT_INDEX); do_check_true(dupTagId > 0); - var bmId = bmsvc.insertBookmark(dupTagId, - TEST_URI, - bmsvc.DEFAULT_INDEX, - "title"); + var bmId = PlacesUtils.bookmarks.insertBookmark(dupTagId, + TEST_URI, + Ci.nsINavBookmarksService.DEFAULT_INDEX, + "title"); do_check_true(bmId > 0); print(" Querying for tag should match URI"); var [query, opts] = makeQuery([tagName]); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, [TEST_URI.spec]); + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, [TEST_URI.spec]); - tagssvc.untagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.untagURI(TEST_URI, [tagName]); cleanDatabase(); } }, @@ -516,20 +516,20 @@ var gTests = [ print(" Add bookmark and tag it"); addBookmark(TEST_URI); - tagssvc.tagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.tagURI(TEST_URI, [tagName]); print(" Create folder with same name as tag"); - var folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder, - tagName, - bmsvc.DEFAULT_INDEX); + var folderId = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, + tagName, + Ci.nsINavBookmarksService.DEFAULT_INDEX); do_check_true(folderId > 0); print(" Querying for tag should match URI"); var [query, opts] = makeQuery([tagName]); opts.queryType = opts.QUERY_TYPE_BOOKMARKS; - queryResultsAre(histsvc.executeQuery(query, opts).root, [TEST_URI.spec]); + queryResultsAre(PlacesUtils.history.executeQuery(query, opts).root, [TEST_URI.spec]); - tagssvc.untagURI(TEST_URI, [tagName]); + PlacesUtils.tagging.untagURI(TEST_URI, [tagName]); cleanDatabase(); } }, @@ -554,53 +554,53 @@ var gTests = [ let nsiuri = uri(pURI); addVisit(nsiuri); if (tags) - tagssvc.tagURI(nsiuri, tags); + PlacesUtils.tagging.tagURI(nsiuri, tags); } print(" Query for /1 OR query for /2 should match both /1 and /2"); var [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); var [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"]); - var root = histsvc.executeQueries([query1, query2], 2, opts).root; + var root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); print(" Query for /1 OR query on bogus tag should match only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(["bogus"]); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); print(" Query for /1 OR query for /1 should match only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(urisAndTags["http://example.com/1"]); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); print(" Query for /1 with tagsAreNot OR query for /2 with tagsAreNot " + "should match both /1 and /2"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"], true); [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"], true); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); print(" Query for /1 OR query for /2 with tagsAreNot should match " + "only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"], true); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); print(" Query for /1 OR query for /1 with tagsAreNot should match " + "both URIs"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); [query2, dummy] = makeQuery(urisAndTags["http://example.com/1"], true); - root = histsvc.executeQueries([query1, query2], 2, opts).root; + root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); // Clean up. for (let [pURI, tags] in Iterator(urisAndTags)) { let nsiuri = uri(pURI); if (tags) - tagssvc.untagURI(nsiuri, tags); + PlacesUtils.tagging.untagURI(nsiuri, tags); } cleanDatabase(); } @@ -623,10 +623,10 @@ const TEST_URI = uri("http://example.com/"); * URI of the page (an nsIURI) */ function addBookmark(aURI) { - var bmId = bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder, - aURI, - bmsvc.DEFAULT_INDEX, - aURI.spec); + var bmId = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + aURI, + Ci.nsINavBookmarksService.DEFAULT_INDEX, + aURI.spec); print(" Sanity check: insertBookmark should not fail"); do_check_true(bmId > 0); } @@ -638,12 +638,12 @@ function addBookmark(aURI) { * URI of the page (an nsIURI) */ function addVisit(aURI) { - var visitId = histsvc.addVisit(aURI, - Date.now() * 1000, - null, - histsvc.TRANSITION_LINK, - false, - 0); + var visitId = PlacesUtils.history.addVisit(aURI, + Date.now() * 1000, + null, + Ci.nsINavHistoryService.TRANSITION_LINK, + false, + 0); print(" Sanity check: addVisit should not fail"); do_check_true(visitId > 0); } @@ -652,7 +652,7 @@ function addVisit(aURI) { * Removes all pages from history and bookmarks. */ function cleanDatabase() { - bhistsvc.removeAllPages(); + PlacesUtils.bhistory.removeAllPages(); remove_all_bookmarks(); } @@ -688,9 +688,9 @@ function checkQueryURI(aTags, aTagsAreNot) { */ function doWithBookmark(aTags, aCallback) { addBookmark(TEST_URI); - tagssvc.tagURI(TEST_URI, aTags); + PlacesUtils.tagging.tagURI(TEST_URI, aTags); aCallback(TEST_URI); - tagssvc.untagURI(TEST_URI, aTags); + PlacesUtils.tagging.untagURI(TEST_URI, aTags); cleanDatabase(); } @@ -706,9 +706,9 @@ function doWithBookmark(aTags, aCallback) { */ function doWithVisit(aTags, aCallback) { addVisit(TEST_URI); - tagssvc.tagURI(TEST_URI, aTags); + PlacesUtils.tagging.tagURI(TEST_URI, aTags); aCallback(TEST_URI); - tagssvc.untagURI(TEST_URI, aTags); + PlacesUtils.tagging.untagURI(TEST_URI, aTags); cleanDatabase(); } @@ -740,7 +740,7 @@ function encodeTag(aTag) { * Array of URIs (as strings) that aResultRoot should contain */ function executeAndCheckQueryResults(aQuery, aQueryOpts, aExpectedURIs) { - var root = histsvc.executeQuery(aQuery, aQueryOpts).root; + var root = PlacesUtils.history.executeQuery(aQuery, aQueryOpts).root; root.containerOpen = true; queryResultsAre(root, aExpectedURIs); root.containerOpen = false; @@ -765,7 +765,7 @@ function makeQuery(aTags, aTagsAreNot) { "without calling setTags() at all") + " and with tagsAreNot=" + aTagsAreNot); - var query = histsvc.getNewQuery(); + var query = PlacesUtils.history.getNewQuery(); query.tagsAreNot = aTagsAreNot; if (aTags) { query.tags = aTags; @@ -784,7 +784,7 @@ function makeQuery(aTags, aTagsAreNot) { do_check_eq(query.tags.length, expCount); do_check_eq(query.tagsAreNot, aTagsAreNot); - return [query, histsvc.getNewQueryOptions()]; + return [query, PlacesUtils.history.getNewQueryOptions()]; } /** @@ -818,7 +818,7 @@ function queryResultsAre(aResultRoot, aExpectedURIs) { * @return The query's URI */ function queryURI(aQuery, aQueryOpts) { - return histsvc.queriesToQueryString([aQuery], 1, aQueryOpts); + return PlacesUtils.history.queriesToQueryString([aQuery], 1, aQueryOpts); } /** diff --git a/toolkit/components/places/tests/sync/head_sync.js b/toolkit/components/places/tests/sync/head_sync.js index 771a1435f38b..ceeb6211163a 100644 --- a/toolkit/components/places/tests/sync/head_sync.js +++ b/toolkit/components/places/tests/sync/head_sync.js @@ -39,120 +39,21 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -// If there's no location registered for the profile direcotry, register one now. -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var profileDir = null; -try { - profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile); -} catch (e) {} -if (!profileDir) { - // Register our own provider for the profile directory. - // It will simply return the current directory. - var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_USER_PROFILE_50_DIR) { - return dirSvc.get("CurProcD", Ci.nsIFile); - } - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("CurProcD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } - }; - dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); -} +// Put any other stuff relative to this test folder below. -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = DBConn() - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} /** * Function tests to see if the place associated with the bookmark with id @@ -170,8 +71,7 @@ function dump_table(aName) */ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFinish) { - let db = DBConn(); - let stmt = db.createStatement( + let stmt = DBConn().createStatement( "SELECT moz_places.url " + "FROM moz_bookmarks INNER JOIN moz_places " + "ON moz_bookmarks.fk = moz_places.id " + @@ -194,6 +94,7 @@ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFini do_test_finished(); } + /** * Function tests to see if the place associated with the visit with id aVisitId * has the uri aExpectedURI. The event will call do_test_finished() if aFinish is @@ -210,8 +111,7 @@ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFini */ function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) { - let db = DBConn(); - let stmt = db.createStatement( + let stmt = DBConn().createStatement( "SELECT moz_places.url " + "FROM moz_historyvisits INNER JOIN moz_places " + "ON moz_historyvisits.place_id = moz_places.id " + @@ -234,50 +134,3 @@ function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) do_test_finished(); } -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -// Simulates a Places shutdown. -function shutdownPlaces() -{ - const TOPIC_XPCOM_SHUTDOWN = "xpcom-shutdown"; - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsIObserver); - hs.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, TOPIC_XPCOM_SHUTDOWN, null); - let expire = Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsIObserver); - expire.observe(null, TOPIC_XPCOM_SHUTDOWN, null); -} diff --git a/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js b/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js index d0cc6934fcfb..e805817fdb49 100644 --- a/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js +++ b/toolkit/components/places/tests/sync/test_database_sync_after_shutdown_with_removeAllPages.js @@ -110,13 +110,13 @@ function check_results() { do_test_finished(); } - if (hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection.connectionReady) { + if (PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) + .DBConnection.connectionReady) { do_timeout(POLLING_TIMEOUT_MS, check_results); return; } let dbConn = DBConn(); - do_check_neq(dbConn, null); do_check_true(dbConn.connectionReady); // Check that frecency for not cleared items (bookmarks) has been @@ -127,14 +127,14 @@ function check_results() { do_check_false(stmt.executeStep()); stmt.finalize(); - stmt = DBConn().createStatement( + stmt = dbConn.createStatement( "SELECT h.id FROM moz_places h WHERE h.frecency = -2 " + "AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1"); do_check_true(stmt.executeStep()); stmt.finalize(); // Check that all visit_counts have been brought to 0 - stmt = DBConn().createStatement( + stmt = dbConn.createStatement( "SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1"); do_check_false(stmt.executeStep()); stmt.finalize(); diff --git a/toolkit/components/places/tests/unit/head_bookmarks.js b/toolkit/components/places/tests/unit/head_bookmarks.js index b1b444f90923..2228f7347197 100644 --- a/toolkit/components/places/tests/unit/head_bookmarks.js +++ b/toolkit/components/places/tests/unit/head_bookmarks.js @@ -12,16 +12,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Places. + * The Original Code is Places Unit Tests. * - * The Initial Developer of the Original Code is - * Google Inc. - * Portions created by the Initial Developer are Copyright (C) 2005 + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Brian Ryner - * Dietrich Ayala + * Marco Bonardo * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,298 +35,17 @@ * * ***** END LICENSE BLOCK ***** */ -const NS_APP_USER_PROFILE_50_DIR = "ProfD"; -const NS_APP_HISTORY_50_FILE = "UHist"; - const Ci = Components.interfaces; const Cc = Components.classes; const Cr = Components.results; +const Cu = Components.utils; -function LOG(aMsg) { - aMsg = ("*** PLACES TESTS: " + aMsg); - Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). - logStringMessage(aMsg); - print(aMsg); +Cu.import("resource://gre/modules/Services.jsm"); + +// Import common head. +let (commonFile = do_get_file("../head_common.js", false)) { + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); } -do_get_profile(); - -var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); -var provider = { - getFile: function(prop, persistent) { - persistent.value = true; - if (prop == NS_APP_HISTORY_50_FILE) { - var histFile = dirSvc.get("ProfD", Ci.nsIFile); - histFile.append("history.dat"); - return histFile; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: function(iid) { - if (iid.equals(Ci.nsIDirectoryServiceProvider) || - iid.equals(Ci.nsISupports)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - } -}; -dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); - -var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - -function uri(spec) { - return iosvc.newURI(spec, null, null); -} - -/* - * Reads the data from the specified nsIFile, and returns an array of bytes. - */ -function readFileData(aFile) { - var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - // init the stream as RD_ONLY, -1 == default permissions. - inputStream.init(aFile, 0x01, -1, null); - var size = inputStream.available(); - - // use a binary input stream to grab the bytes. - var bis = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(inputStream); - - var bytes = bis.readByteArray(size); - - if (size != bytes.length) - throw "Didn't read expected number of bytes"; - - return bytes; -} - -/* - * Compares two arrays, and returns true if they are equal. - */ -function compareArrays(aArray1, aArray2) { - if (aArray1.length != aArray2.length) { - print("compareArrays: array lengths differ\n"); - return false; - } - - for (var i = 0; i < aArray1.length; i++) { - if (aArray1[i] != aArray2[i]) { - print("compareArrays: arrays differ at index " + i + ": " + - "(" + aArray1[i] + ") != (" + aArray2[i] +")\n"); - return false; - } - } - - return true; -} - -// Delete a previously created sqlite file -function clearDB() { - try { - var file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - if (file.exists()) - file.remove(false); - } catch(ex) { dump("Exception: " + ex); } -} -clearDB(); - -/** - * Dumps the rows of a table out to the console. - * - * @param aName - * The name of the table or view to output. - */ -function dump_table(aName) -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - let stmt = db.createStatement("SELECT * FROM " + aName); - - dump("\n*** Printing data from " + aName + ":\n"); - let count = 0; - while (stmt.executeStep()) { - let columns = stmt.numEntries; - - if (count == 0) { - // print the column names - for (let i = 0; i < columns; i++) - dump(stmt.getColumnName(i) + "\t"); - dump("\n"); - } - - // print the row - for (let i = 0; i < columns; i++) { - switch (stmt.getTypeOfIndex(i)) { - case Ci.mozIStorageValueArray.VALUE_TYPE_NULL: - dump("NULL\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER: - dump(stmt.getInt64(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT: - dump(stmt.getDouble(i) + "\t"); - break; - case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT: - dump(stmt.getString(i) + "\t"); - break; - } - } - dump("\n"); - - count++; - } - dump("*** There were a total of " + count + " rows of data.\n\n"); - - stmt.reset(); - stmt.finalize(); - stmt = null; -} - -/* - * Removes all bookmarks and checks for correct cleanup - */ -function remove_all_bookmarks() { - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - // Clear all bookmarks - bs.removeFolderChildren(bs.bookmarksMenuFolder); - bs.removeFolderChildren(bs.toolbarFolder); - bs.removeFolderChildren(bs.unfiledBookmarksFolder); - // Check for correct cleanup - check_no_bookmarks() -} - -/* - * Checks that we don't have any bookmark - */ -function check_no_bookmarks() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); - var query = hs.getNewQuery(); - query.setFolders([bs.toolbarFolder, bs.bookmarksMenuFolder, bs.unfiledBookmarksFolder], 3); - var options = hs.getNewQueryOptions(); - options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; - var result = hs.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - do_check_eq(root.childCount, 0); - root.containerOpen = false; -} - -/** - * Function gets current database connection, if the connection has been closed - * it will try to reconnect to the places.sqlite database. - */ -function DBConn() -{ - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; - if (db.connectionReady) - return db; - - // open a new connection if needed - let file = dirSvc.get('ProfD', Ci.nsIFile); - file.append("places.sqlite"); - let storageService = Cc["@mozilla.org/storage/service;1"]. - getService(Ci.mozIStorageService); - try { - var dbConn = storageService.openDatabase(file); - } catch (ex) { - return null; - } - return dbConn; -} - -/** - * Sets title synchronously for a page in moz_places synchronously. - * History.SetPageTitle uses LAZY_ADD so we can't rely on it. - * - * @param aURI - * An nsIURI to set the title for. - * @param aTitle - * The title to set the page to. - * @throws if the page is not found in the database. - * - * @note this function only exists because we have no API to do this. It should - * be added in bug 421897. - */ -function setPageTitle(aURI, aTitle) { - let dbConn = DBConn(); - // Check that the page exists. - let stmt = dbConn.createStatement( - "SELECT id FROM moz_places_view WHERE url = :url"); - stmt.params.url = aURI.spec; - try { - if (!stmt.executeStep()) { - do_throw("Unable to find page " + aURIString); - return; - } - } - finally { - stmt.finalize(); - } - - // Update the title - stmt = dbConn.createStatement( - "UPDATE moz_places_view SET title = :title WHERE url = :url"); - stmt.params.title = aTitle; - stmt.params.url = aURI.spec; - try { - stmt.execute(); - } - finally { - stmt.finalize(); - } -} - -/** - * Flushes any events in the event loop of the main thread. - */ -function flush_main_thread_events() -{ - let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); - while (tm.mainThread.hasPendingEvents()) - tm.mainThread.processNextEvent(false); -} - -/** - * Clears history invoking callback when done. - */ -function waitForClearHistory(aCallback) { - const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished"; - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let observer = { - observe: function(aSubject, aTopic, aData) { - os.removeObserver(this, TOPIC_EXPIRATION_FINISHED); - aCallback(); - } - }; - os.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false); - - let hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); - hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages(); -} - -// These tests are known to randomly fail due to bug 507790 when database -// flushes are active, so we turn off syncing for them. -let randomFailingSyncTests = [ - "test_multi_word_tags.js", - "test_removeVisitsByTimeframe.js", - "test_utils_getURLsForContainerNode.js", - "test_exclude_livemarks.js", - "test_402799.js", -]; -let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName; -if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) { - print("Test " + currentTestFilename + " is known random due to bug 507790, disabling PlacesDBFlush component."); - let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver); - sync.observe(null, "places-debug-stop-sync", null); -} +// Put any other stuff relative to this test folder below. diff --git a/toolkit/components/places/tests/unit/test_412132.js b/toolkit/components/places/tests/unit/test_412132.js index ae303a348c75..8a73511e5be5 100644 --- a/toolkit/components/places/tests/unit/test_412132.js +++ b/toolkit/components/places/tests/unit/test_412132.js @@ -303,14 +303,15 @@ function getFrecency(url) return frecency; } -function prepTest(testIndex, testName, callback) +function prepTest(testName, callback) { - print("Test " + testIndex + ": " + testName); + print("Test: " + testName); waitForClearHistory(function() { dbConn.executeSimpleSQL("DELETE FROM moz_places_view"); dbConn.executeSimpleSQL("DELETE FROM moz_bookmarks WHERE id > " + defaultBookmarksMaxId); callback(); + runNextTest(); }); } @@ -328,6 +329,7 @@ function visit(uri) function run_test() { + do_test_pending(); var stmt; dbConn = @@ -341,8 +343,16 @@ function run_test() stmt.finalize(); do_check_true(defaultBookmarksMaxId > 0); - for (let i= 0; i < tests.length; i++) - { - prepTest(i, tests[i].desc, tests[i].run); + runNextTest(); +} + +let currentTest; +function runNextTest() { + if (tests.length) { + currentTest = tests.shift(); + prepTest(currentTest.desc, currentTest.run); + } + else { + do_test_finished(); } } diff --git a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js index 5160cf0f60bf..127c80108bff 100644 --- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js +++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js @@ -64,7 +64,7 @@ function checkAddSucceeded(pageURI, mimetype, data) { var favicons = [ { - uri: iosvc.newFileURI(do_get_file("favicon-normal32.png")), + uri: uri(do_get_file("favicon-normal32.png")), data: readFileData(do_get_file("favicon-normal32.png")), mimetype: "image/png" } diff --git a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js index 9f2866c81879..460afec82113 100644 --- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js +++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js @@ -59,13 +59,13 @@ XPCOMUtils.defineLazyServiceGetter(this, "prefs", let favicons = [ { - uri: iosvc.newFileURI(do_get_file("favicon-normal16.png")), + uri: uri(do_get_file("favicon-normal16.png")), data: readFileData(do_get_file("favicon-normal16.png")), mimetype: "image/png", size: 286 }, { - uri: iosvc.newFileURI(do_get_file("favicon-normal32.png")), + uri: uri(do_get_file("favicon-normal32.png")), data: readFileData(do_get_file("favicon-normal32.png")), mimetype: "image/png", size: 344 @@ -154,7 +154,7 @@ let historyObserver = { do_check_true(pageURI.equals(uri("http://test4.bar/"))); // Ensure there is only one entry in favicons table. - let stmt = DBConn().createStatement( + let stmt = PlacesServices.DBConn.createStatement( "SELECT url FROM moz_favicons" ); let c = 0; diff --git a/toolkit/components/places/tests/unit/test_history.js b/toolkit/components/places/tests/unit/test_history.js index f6603fe17bff..04c387a7cc89 100644 --- a/toolkit/components/places/tests/unit/test_history.js +++ b/toolkit/components/places/tests/unit/test_history.js @@ -226,7 +226,7 @@ function run_test() { // test to ensure history.dat gets deleted if all history is being cleared var file = do_get_file("history.dat"); - var histFile = dirSvc.get("ProfD", Ci.nsIFile); + var histFile = Services.dirsvc.get("ProfD", Ci.nsIFile); file.copyTo(histFile, "history.dat"); histFile.append("history.dat"); do_check_true(histFile.exists()); From f203c2ec0f47ba5ab96f752110198acb91fb778d Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 1 Apr 2010 22:09:05 -0400 Subject: [PATCH 50/69] Bug 509569. Avoid assertion by not storing structs with unused inherit logical box props in them, even though it would be ok to do so. r=dbaron --- layout/style/crashtests/509569-1.html | 2 ++ layout/style/crashtests/crashtests.list | 1 + layout/style/nsRuleNode.cpp | 6 ++++++ 3 files changed, 9 insertions(+) create mode 100644 layout/style/crashtests/509569-1.html diff --git a/layout/style/crashtests/509569-1.html b/layout/style/crashtests/509569-1.html new file mode 100644 index 000000000000..023c710401ee --- /dev/null +++ b/layout/style/crashtests/509569-1.html @@ -0,0 +1,2 @@ + + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index 8d22e2346141..474d070cb1af 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -48,6 +48,7 @@ load 495269-2.html load 498036-1.html load 509155-1.html load 509156-1.html +load 509569-1.html load 524252-1.html load font-face-truncated-src.html load 536789-1.html diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index a4f79a9bc355..cb9ce6b9ec59 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -2326,6 +2326,12 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext, if (RTLlogical) aValueRect.*(nsCSSRect::sides[aSide]) = aRTLLogicalValue; } + } else if (aLTRLogicalValue.GetUnit() == eCSSUnit_Inherit || + aRTLLogicalValue.GetUnit() == eCSSUnit_Inherit) { + // It actually is valid to store this in the ruletree, since + // LTRlogical and RTLlogical are both false, but doing that will + // trigger asserts. Silence those. + aCanStoreInRuleTree = PR_FALSE; } } From dd2e9869ca969bc5bf68822427e47d2a2441d8c7 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 1 Apr 2010 22:09:05 -0400 Subject: [PATCH 51/69] Bug 538082. These asserts are asserting things that happen to not always be true. r=dbaron --- layout/base/crashtests/538082-1.xul | 34 ++++++++++++++++++++++++++ layout/base/crashtests/crashtests.list | 1 + layout/base/nsCSSFrameConstructor.cpp | 16 ++++++------ 3 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 layout/base/crashtests/538082-1.xul diff --git a/layout/base/crashtests/538082-1.xul b/layout/base/crashtests/538082-1.xul new file mode 100644 index 000000000000..10335617eab9 --- /dev/null +++ b/layout/base/crashtests/538082-1.xul @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 77e3ab246518..c2a06f40f862 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -280,5 +280,6 @@ load 536623-1.xhtml load 537059-1.xhtml load 537141-1.xhtml load 537562-1.xhtml +load 538082-1.xul load 541869-1.xhtml load 541869-2.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 634e176484f7..63e4319bca5d 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -11141,6 +11141,10 @@ nsCSSFrameConstructor::ProcessPendingRestyleTable( count = aRestyles.Count(); } + // Set mInStyleRefresh to false now, since the EndUpdate call might + // add more restyles. + mInStyleRefresh = PR_FALSE; + EndUpdate(); #ifdef DEBUG @@ -11163,8 +11167,9 @@ nsCSSFrameConstructor::ProcessPendingRestyles() ProcessPendingRestyleTable(mPendingRestyles); - NS_POSTCONDITION(mPendingRestyles.Count() == 0, - "We should have processed mPendingRestyles to completion"); +#ifdef DEBUG + PRUint32 oldPendingRestyleCount = mPendingRestyles.Count(); +#endif // ...and then process animation restyles. This needs to happen // second because we need to start animations that resulted from the @@ -11179,12 +11184,7 @@ nsCSSFrameConstructor::ProcessPendingRestyles() presContext->SetProcessingAnimationStyleChange(PR_FALSE); presContext->SetProcessingRestyles(PR_FALSE); - mInStyleRefresh = PR_FALSE; - - NS_POSTCONDITION(mPendingAnimationRestyles.Count() == 0, - "We should have processed mPendingAnimationRestyles to " - "completion"); - NS_POSTCONDITION(mPendingRestyles.Count() == 0, + NS_POSTCONDITION(mPendingRestyles.Count() == oldPendingRestyleCount, "We should not have posted new non-animation restyles while " "processing animation restyles"); From e31631ba457c82039ce94743896b217dda6175ef Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 1 Apr 2010 22:09:05 -0400 Subject: [PATCH 52/69] Bug 551699. Use the content insertion frame of our containing block when looking for our static position. r=dbaron --- layout/generic/nsHTMLReflowState.cpp | 45 +++++++++++++------------- layout/reftests/bugs/551699-1-ref.html | 13 ++++++++ layout/reftests/bugs/551699-1.html | 13 ++++++++ layout/reftests/bugs/reftest.list | 1 + 4 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 layout/reftests/bugs/551699-1-ref.html create mode 100644 layout/reftests/bugs/551699-1.html diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 469f1def77ad..b367a5eefd7c 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -710,16 +710,22 @@ nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs, } } +static nsIFrame* +GetNearestContainingBlock(nsIFrame *aFrame) +{ + nsIFrame *cb = aFrame; + do { + cb = cb->GetParent(); + } while (!cb->IsContainingBlock()); + return cb; +} + nsIFrame* nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame, nscoord& aCBLeftEdge, nscoord& aCBWidth) { - do { - aFrame = aFrame->GetParent(); - NS_ASSERTION(aFrame, "Must find containing block somewhere"); - } while (!aFrame->IsContainingBlock()); - + aFrame = GetNearestContainingBlock(aFrame); NS_ASSERTION(aFrame != frame, "How did that happen?"); /* Now aFrame is the containing block we want */ @@ -753,16 +759,6 @@ nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame, return aFrame; } -static nsIFrame* -GetNearestContainingBlock(nsIFrame *aFrame) -{ - nsIFrame *cb = aFrame; - do { - cb = cb->GetParent(); - } while (!cb->IsContainingBlock()); - return cb; -} - // When determining the hypothetical box that would have been if the element // had been in the flow we may not be able to exactly determine both the left // and right edges. For example, if the element is a non-replaced inline-level @@ -966,14 +962,19 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext, const nsStyleVisibility* blockVis = aContainingBlock->GetStyleVisibility(); // Get the placeholder x-offset and y-offset in the coordinate - // space of the block frame that contains it + // space of its containing block // XXXbz the placeholder is not fully reflowed yet if our containing block is // relatively positioned... nsPoint placeholderOffset = aPlaceholderFrame->GetOffsetTo(aContainingBlock); - // First, determine the hypothetical box's mTop - nsBlockFrame* blockFrame = nsLayoutUtils::GetAsBlock(aContainingBlock); + // First, determine the hypothetical box's mTop. We want to check the + // content insertion frame of aContainingBlock for block-ness, but make + // sure to compute all coordinates in the coordinate system of + // aContainingBlock. + nsBlockFrame* blockFrame = + nsLayoutUtils::GetAsBlock(aContainingBlock->GetContentInsertionFrame()); if (blockFrame) { + nscoord blockYOffset = blockFrame->GetOffsetTo(aContainingBlock).y; PRBool isValid; nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid); NS_ASSERTION(isValid, "Can't find placeholder!"); @@ -985,7 +986,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext, if (NS_STYLE_DISPLAY_INLINE == mStyleDisplay->mOriginalDisplay) { // Use the top of the inline box which the placeholder lives in as the // hypothetical box's top. - aHypotheticalBox.mTop = lineBox->mBounds.y; + aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset; } else { // The element would have been block-level which means it would be below // the line containing the placeholder frame, unless all the frames @@ -1010,14 +1011,14 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext, // The top of the hypothetical box is the top of the line containing // the placeholder, since there is nothing in the line before our // placeholder except empty frames. - aHypotheticalBox.mTop = lineBox->mBounds.y; + aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset; } else { // The top of the hypothetical box is just below the line containing // the placeholder. - aHypotheticalBox.mTop = lineBox->mBounds.YMost(); + aHypotheticalBox.mTop = lineBox->mBounds.YMost() + blockYOffset; } } else { - // Just use the placeholder's y-offset + // Just use the placeholder's y-offset wrt the containing block aHypotheticalBox.mTop = placeholderOffset.y; } } diff --git a/layout/reftests/bugs/551699-1-ref.html b/layout/reftests/bugs/551699-1-ref.html new file mode 100644 index 000000000000..1f81b34f38c4 --- /dev/null +++ b/layout/reftests/bugs/551699-1-ref.html @@ -0,0 +1,13 @@ + + + + + + + +
+
Text
+
+
+ + diff --git a/layout/reftests/bugs/551699-1.html b/layout/reftests/bugs/551699-1.html new file mode 100644 index 000000000000..a97921c4fdcf --- /dev/null +++ b/layout/reftests/bugs/551699-1.html @@ -0,0 +1,13 @@ + + + + + + + +
+
Text
+
+
+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 15ecf7395c5c..c60c349d142b 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1417,3 +1417,4 @@ random-if(!haveTestPlugin) == 546071-1.html 546071-1-ref.html == 549184-1.html 549184-1-ref.html == 550716-1.html 550716-1-ref.html == 551463-1.html 551463-1-ref.html +== 551699-1.html 551699-1-ref.html From eb59274fec0457939fd4b70b6e21a4f49415ad83 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 1 Apr 2010 22:09:05 -0400 Subject: [PATCH 53/69] Bug 552439. Make sure to gtk_widget_realize() the GtkEntry before trying to get information out of it; otherwise it doesn't pick up the right styles before being interrogated. r=karlt --- widget/src/gtk2/nsLookAndFeel.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/widget/src/gtk2/nsLookAndFeel.cpp b/widget/src/gtk2/nsLookAndFeel.cpp index ddd32deefb6d..35e2dd262f85 100644 --- a/widget/src/gtk2/nsLookAndFeel.cpp +++ b/widget/src/gtk2/nsLookAndFeel.cpp @@ -747,6 +747,7 @@ nsLookAndFeel::InitLookAndFeel() GtkWidget *treeView = gtk_tree_view_new(); GtkWidget *linkButton = gtk_link_button_new("http://example.com/"); GtkWidget *menuBar = gtk_menu_bar_new(); + GtkWidget *entry = gtk_entry_new(); gtk_container_add(GTK_CONTAINER(button), label); gtk_container_add(GTK_CONTAINER(combobox), comboboxLabel); @@ -756,6 +757,7 @@ nsLookAndFeel::InitLookAndFeel() gtk_container_add(GTK_CONTAINER(parent), combobox); gtk_container_add(GTK_CONTAINER(parent), menuBar); gtk_container_add(GTK_CONTAINER(window), parent); + gtk_container_add(GTK_CONTAINER(parent), entry); gtk_widget_set_style(button, NULL); gtk_widget_set_style(label, NULL); @@ -764,6 +766,7 @@ nsLookAndFeel::InitLookAndFeel() gtk_widget_set_style(combobox, NULL); gtk_widget_set_style(comboboxLabel, NULL); gtk_widget_set_style(menuBar, NULL); + gtk_widget_set_style(entry, NULL); gtk_widget_realize(button); gtk_widget_realize(label); @@ -772,6 +775,7 @@ nsLookAndFeel::InitLookAndFeel() gtk_widget_realize(combobox); gtk_widget_realize(comboboxLabel); gtk_widget_realize(menuBar); + gtk_widget_realize(entry); style = gtk_widget_get_style(label); if (style) { @@ -840,11 +844,7 @@ nsLookAndFeel::InitLookAndFeel() sNativeHyperLinkText = NS_RGB(0x00,0x00,0xEE); } - gtk_widget_destroy(window); - // invisible character styles - GtkWidget *entry = gtk_entry_new(); - g_object_ref_sink(entry); guint value; g_object_get (entry, "invisible-char", &value, NULL); sInvisibleCharacter = PRUnichar(value); @@ -854,8 +854,7 @@ nsLookAndFeel::InitLookAndFeel() "cursor-aspect-ratio", &sCaretRatio, NULL); - gtk_widget_destroy(entry); - g_object_unref(entry); + gtk_widget_destroy(window); } // virtual From e2c52c0a304030aded03789a5046fcfdfd6478db Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Thu, 1 Apr 2010 22:09:05 -0400 Subject: [PATCH 54/69] Bug 554707. Throw the right exception when document.open/close/write/writeln happen on an XHTML document. r=bzbarsky --- content/html/document/src/nsHTMLDocument.cpp | 6 +++--- content/html/document/test/test_bug332848.xhtml | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 29b288ee64ff..5a78fd11259d 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1849,7 +1849,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) if (!IsHTML() || mDisableDocWrite) { // No calling document.open() on XHTML - return NS_ERROR_DOM_INVALID_ACCESS_ERR; + return NS_ERROR_DOM_INVALID_STATE_ERR; } PRBool loadAsHtml5 = nsHtml5Module::sEnabled; @@ -2099,7 +2099,7 @@ nsHTMLDocument::Close() if (!IsHTML()) { // No calling document.close() on XHTML! - return NS_ERROR_DOM_INVALID_ACCESS_ERR; + return NS_ERROR_DOM_INVALID_STATE_ERR; } nsresult rv = NS_OK; @@ -2164,7 +2164,7 @@ nsHTMLDocument::WriteCommon(const nsAString& aText, if (!IsHTML() || mDisableDocWrite) { // No calling document.write*() on XHTML! - return NS_ERROR_DOM_INVALID_ACCESS_ERR; + return NS_ERROR_DOM_INVALID_STATE_ERR; } nsresult rv = NS_OK; diff --git a/content/html/document/test/test_bug332848.xhtml b/content/html/document/test/test_bug332848.xhtml index f8f824d60cf7..0cbdf327b1ed 100644 --- a/content/html/document/test/test_bug332848.xhtml +++ b/content/html/document/test/test_bug332848.xhtml @@ -28,7 +28,7 @@ function test() { document.open(); is(0, 1, "document.open succeeded"); } catch (e) { - is (e.code, DOMException.INVALID_ACCESS_ERR, + is (e.code, DOMException.INVALID_STATE_ERR, "Wrong exception from document.open"); } @@ -36,7 +36,15 @@ function test() { document.write("aaa"); is(0, 1, "document.write succeeded"); } catch (e) { - is (e.code, DOMException.INVALID_ACCESS_ERR, + is (e.code, DOMException.INVALID_STATE_ERR, + "Wrong exception from document.write"); + } + + try { + document.writeln("aaa"); + is(0, 1, "document.write succeeded"); + } catch (e) { + is (e.code, DOMException.INVALID_STATE_ERR, "Wrong exception from document.write"); } @@ -44,7 +52,7 @@ function test() { document.close(); is(0, 1, "document.close succeeded"); } catch (e) { - is (e.code, DOMException.INVALID_ACCESS_ERR, + is (e.code, DOMException.INVALID_STATE_ERR, "Wrong exception from document.close"); } } From 2b60b98a59da3c57bc55f0bf9f73cfc4afd94411 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 1 Apr 2010 22:09:05 -0400 Subject: [PATCH 55/69] Bug 552334. Deal with z-indices whose difference overflows a 32-bit signed int. r=roc --- layout/base/nsDisplayList.cpp | 11 ++++++----- layout/reftests/bugs/552334-1-ref.html | 15 +++++++++++++++ layout/reftests/bugs/552334-1.html | 26 ++++++++++++++++++++++++++ layout/reftests/bugs/reftest.list | 1 + 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 layout/reftests/bugs/552334-1-ref.html create mode 100644 layout/reftests/bugs/552334-1.html diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e7a6e43a4b48..48e588935e08 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -974,12 +974,13 @@ static PRBool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, static PRBool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, void* aClosure) { // These GetUnderlyingFrame calls return non-null because we're only used - // in sorting - PRInt32 diff = nsLayoutUtils::GetZIndex(aItem1->GetUnderlyingFrame()) - - nsLayoutUtils::GetZIndex(aItem2->GetUnderlyingFrame()); - if (diff == 0) + // in sorting. Note that we can't just take the difference of the two + // z-indices here, because that might overflow a 32-bit int. + PRInt32 index1 = nsLayoutUtils::GetZIndex(aItem1->GetUnderlyingFrame()); + PRInt32 index2 = nsLayoutUtils::GetZIndex(aItem2->GetUnderlyingFrame()); + if (index1 == index2) return IsContentLEQ(aItem1, aItem2, aClosure); - return diff < 0; + return index1 < index2; } void nsDisplayList::ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder) { diff --git a/layout/reftests/bugs/552334-1-ref.html b/layout/reftests/bugs/552334-1-ref.html new file mode 100644 index 000000000000..a139827f2c40 --- /dev/null +++ b/layout/reftests/bugs/552334-1-ref.html @@ -0,0 +1,15 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/bugs/552334-1.html b/layout/reftests/bugs/552334-1.html new file mode 100644 index 000000000000..66f426e09b7c --- /dev/null +++ b/layout/reftests/bugs/552334-1.html @@ -0,0 +1,26 @@ + + + + + + + +
+
+ +
+
+ +
+
+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index c60c349d142b..77bd01f7e830 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1417,4 +1417,5 @@ random-if(!haveTestPlugin) == 546071-1.html 546071-1-ref.html == 549184-1.html 549184-1-ref.html == 550716-1.html 550716-1-ref.html == 551463-1.html 551463-1-ref.html +== 552334-1.html 552334-1-ref.html == 551699-1.html 551699-1-ref.html From 6aba9a22d0057afca0aaece02a39c77b77b3cc72 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Fri, 2 Apr 2010 11:11:59 +0900 Subject: [PATCH 56/69] Bug 556458 Cannot select an item of google suggest by mouse click during composition of MS-IME r=roc --- content/events/src/nsContentEventHandler.cpp | 5 ++- .../window_composition_text_querycontent.xul | 35 +++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/content/events/src/nsContentEventHandler.cpp b/content/events/src/nsContentEventHandler.cpp index 0f545985d9af..bfb031e32935 100644 --- a/content/events/src/nsContentEventHandler.cpp +++ b/content/events/src/nsContentEventHandler.cpp @@ -788,7 +788,10 @@ nsContentEventHandler::OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent) nsLayoutUtils::GetEventCoordinatesRelativeTo(&eventOnRoot, rootFrame); nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot); - if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame) { + if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame || + !targetFrame->GetContent() || + !nsContentUtils::ContentIsDescendantOf(targetFrame->GetContent(), + mRootContent)) { // there is no character at the point. aEvent->mReply.mOffset = nsQueryContentEvent::NOT_FOUND; aEvent->mSucceeded = PR_TRUE; diff --git a/widget/tests/window_composition_text_querycontent.xul b/widget/tests/window_composition_text_querycontent.xul index 20378fcb042c..f909ffa142db 100644 --- a/widget/tests/window_composition_text_querycontent.xul +++ b/widget/tests/window_composition_text_querycontent.xul @@ -26,7 +26,8 @@

- +

Here is a text frame.
+

@@ -78,7 +79,7 @@ const nsIDOMWindowUtils = Components.interfaces.nsIDOMWindowUtils; const kIsWin = (navigator.platform.indexOf("Win") == 0); const kIsMac = (navigator.platform.indexOf("Mac") == 0); -function checkQueryContentResult(aResult, aMessage, aID) +function checkQueryContentResult(aResult, aMessage) { ok(aResult, aMessage + ": the result is null"); if (!aResult) { @@ -741,7 +742,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) for (var i = 0; i < kTestingOffset.length; i++) { var textRect = synthesizeQueryTextRect(kTestingOffset[i], 1); if (!checkQueryContentResult(textRect, - "runCharAtPointTest (" + aTargetName + "): textRect", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): textRect: i=" + i)) { continue; } @@ -753,7 +754,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt1 = synthesizeCharAtPoint(textRect.left + 1, textRect.top + 1); if (checkQueryContentResult(charAtPt1, - "runCharAtPointTest (" + aTargetName + "): charAtPt1", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt1: i=" + i)) { ok(!charAtPt1.notFound, "runCharAtPointTest (" + aTargetName + "): charAtPt1 isn't found: i=" + i); if (!charAtPt1.notFound) { @@ -768,7 +769,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt2 = synthesizeCharAtPoint(textRect.left + textRect.width - 2, textRect.top + textRect.height - 2); if (checkQueryContentResult(charAtPt2, - "runCharAtPointTest (" + aTargetName + "): charAtPt2", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt2: i=" + i)) { ok(!charAtPt2.notFound, "runCharAtPointTest (" + aTargetName + "): charAtPt2 isn't found: i=" + i); if (!charAtPt2.notFound) { @@ -783,7 +784,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt3 = synthesizeCharAtPoint(textRect.left - 2, textRect.top + 1); if (checkQueryContentResult(charAtPt3, - "runCharAtPointTest (" + aTargetName + "): charAtPt3", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt3: i=" + i)) { is(charAtPt3.notFound, kLeftSideOffset[i] == kNone, kLeftSideOffset[i] == kNone ? "runCharAtPointTest (" + aTargetName + "): charAtPt3 is found: i=" + i : @@ -798,7 +799,7 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) var charAtPt4 = synthesizeCharAtPoint(textRect.left + textRect.width + 1, textRect.top + textRect.height - 2); if (checkQueryContentResult(charAtPt4, - "runCharAtPointTest (" + aTargetName + "): charAtPt4", "i=" + i)) { + "runCharAtPointTest (" + aTargetName + "): charAtPt4: i=" + i)) { is(charAtPt4.notFound, kRightSideOffset[i] == kNone, kRightSideOffset[i] == kNone ? "runCharAtPointTest (" + aTargetName + "): charAtPt4 is found: i=" + i : @@ -811,6 +812,25 @@ function runCharAtPointTest(aFocusedEditor, aTargetName) } } +function runCharAtPointAtOutsideTest() +{ + textarea.focus(); + textarea.value = "some text"; + var editorRect = synthesizeQueryEditorRect(); + if (!checkQueryContentResult(editorRect, + "runCharAtPointAtOutsideTest: editorRect")) { + return; + } + // Check on a text node which is at the outside of editor. + var charAtPt = synthesizeCharAtPoint(editorRect.left + 20, + editorRect.top - 10); + if (checkQueryContentResult(charAtPt, + "runCharAtPointAtOutsideTest: charAtPt")) { + ok(charAtPt.notFound, + "runCharAtPointAtOutsideTest: charAtPt is found on outside of editor"); + } +} + function runTestOnAnotherContext(aPanelOrFrame, aFocusedEditor, aTestName) { aFocusedEditor.value = ""; @@ -976,6 +996,7 @@ function runTest() { runCompositionTest(); runCharAtPointTest(textarea, "textarea in the document"); + runCharAtPointAtOutsideTest(); runFrameTest(); runPanelTest(); } From 7cdccaed47869e786f88e81fbe9ea05479d8d3e9 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Thu, 1 Apr 2010 19:54:03 -0700 Subject: [PATCH 57/69] Bug 556424 - mozilla::MonitorAutoEnter::NotifyAll() should notify all. r=cjones --- xpcom/glue/Monitor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpcom/glue/Monitor.h b/xpcom/glue/Monitor.h index cd2d8d8aac00..6d6b3851cbaf 100644 --- a/xpcom/glue/Monitor.h +++ b/xpcom/glue/Monitor.h @@ -233,7 +233,7 @@ public: nsresult NotifyAll() { - return mMonitor->Notify(); + return mMonitor->NotifyAll(); } private: From afd172b8070b6ffad50be4128ebb8131ab9128e5 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Thu, 1 Apr 2010 20:03:07 -0700 Subject: [PATCH 58/69] Bug 531340 - New Ogg video decoder. r=doublec sr=roc --- .../html/content/public/nsHTMLAudioElement.h | 5 + .../html/content/public/nsHTMLMediaElement.h | 5 + .../html/content/public/nsHTMLVideoElement.h | 5 + .../html/content/src/nsHTMLMediaElement.cpp | 3 +- content/media/nsAudioStream.cpp | 42 +- content/media/nsAudioStream.h | 17 +- content/media/ogg/Makefile.in | 4 + content/media/ogg/nsOggCodecState.cpp | 509 ++++ content/media/ogg/nsOggCodecState.h | 206 ++ content/media/ogg/nsOggDecoder.cpp | 2143 +---------------- content/media/ogg/nsOggDecoder.h | 223 +- content/media/ogg/nsOggHacks.h | 109 + content/media/ogg/nsOggPlayStateMachine.cpp | 1394 +++++++++++ content/media/ogg/nsOggPlayStateMachine.h | 419 ++++ content/media/ogg/nsOggReader.cpp | 1540 ++++++++++++ content/media/ogg/nsOggReader.h | 531 ++++ content/media/test/Makefile.in | 12 +- content/media/test/audio-overhang.ogg | Bin 0 -> 45463 bytes content/media/test/bug495794.ogg | Bin 0 -> 4837 bytes content/media/test/manifest.js | 28 +- content/media/test/test_duration1.html | 2 +- content/media/test/test_info_leak.html | 2 +- content/media/test/test_playback.html | 11 +- content/media/test/test_timeupdate1.html | 6 +- content/media/test/video-overhang.ogg | Bin 0 -> 301831 bytes content/media/wave/nsWaveDecoder.cpp | 2 +- 26 files changed, 5041 insertions(+), 2177 deletions(-) create mode 100644 content/media/ogg/nsOggCodecState.cpp create mode 100644 content/media/ogg/nsOggCodecState.h create mode 100644 content/media/ogg/nsOggHacks.h create mode 100644 content/media/ogg/nsOggPlayStateMachine.cpp create mode 100644 content/media/ogg/nsOggPlayStateMachine.h create mode 100644 content/media/ogg/nsOggReader.cpp create mode 100644 content/media/ogg/nsOggReader.h create mode 100644 content/media/test/audio-overhang.ogg create mode 100644 content/media/test/bug495794.ogg create mode 100644 content/media/test/video-overhang.ogg diff --git a/content/html/content/public/nsHTMLAudioElement.h b/content/html/content/public/nsHTMLAudioElement.h index 59ef12943b43..baf65833079e 100644 --- a/content/html/content/public/nsHTMLAudioElement.h +++ b/content/html/content/public/nsHTMLAudioElement.h @@ -35,6 +35,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#if !defined(nsHTMLAudioElement_h__) +#define nsHTMLAudioElement_h__ + #include "nsIDOMHTMLAudioElement.h" #include "nsIJSNativeInitializer.h" #include "nsHTMLMediaElement.h" @@ -74,3 +77,5 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; }; + +#endif diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 7be197a982ec..b78e7bac2f86 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -35,6 +35,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#if !defined(nsHTMLMediaElement_h__) +#define nsHTMLMediaElement_h__ + #include "nsIDOMHTMLMediaElement.h" #include "nsGenericHTMLElement.h" #include "nsMediaDecoder.h" @@ -538,3 +541,5 @@ protected: nsRefPtr mPrintSurface; }; + +#endif diff --git a/content/html/content/public/nsHTMLVideoElement.h b/content/html/content/public/nsHTMLVideoElement.h index b6d6ad7e3cd3..c32861569b36 100644 --- a/content/html/content/public/nsHTMLVideoElement.h +++ b/content/html/content/public/nsHTMLVideoElement.h @@ -35,6 +35,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#if !defined(nsHTMLVideoElement_h__) +#define nsHTMLVideoElement_h__ + #include "nsIDOMHTMLVideoElement.h" #include "nsHTMLMediaElement.h" @@ -76,3 +79,5 @@ public: // If there is no video frame, returns the given default size. nsIntSize GetVideoSize(nsIntSize defaultSize); }; + +#endif diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 4777a95d213c..97165ac43a6a 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -84,6 +84,7 @@ #include "nsLayoutUtils.h" #include "nsVideoFrame.h" #include "BasicLayers.h" +#include #ifdef MOZ_OGG #include "nsOggDecoder.h" @@ -819,7 +820,7 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCurrentTime(float aCurrentTime) /* readonly attribute float duration; */ NS_IMETHODIMP nsHTMLMediaElement::GetDuration(float *aDuration) { - *aDuration = mDecoder ? mDecoder->GetDuration() : 0.0; + *aDuration = mDecoder ? mDecoder->GetDuration() : std::numeric_limits::quiet_NaN(); return NS_OK; } diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 0d237c4c0e41..12452f7d51ec 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -45,6 +45,9 @@ extern "C" { #include "sydneyaudio/sydney_audio.h" } +#include "mozilla/TimeStamp.h" + +using mozilla::TimeStamp; #ifdef PR_LOGGING PRLogModuleInfo* gAudioStreamLog = nsnull; @@ -68,7 +71,8 @@ nsAudioStream::nsAudioStream() : mAudioHandle(0), mRate(0), mChannels(0), - mFormat(FORMAT_S16_LE) + mFormat(FORMAT_S16_LE), + mPaused(PR_FALSE) { } @@ -110,13 +114,14 @@ void nsAudioStream::Shutdown() mAudioHandle = nsnull; } -void nsAudioStream::Write(const void* aBuf, PRUint32 aCount) +void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) { NS_ABORT_IF_FALSE(aCount % mChannels == 0, "Buffer size must be divisible by channel count"); + NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block"); PRUint32 offset = mBufferOverflow.Length(); - PRInt32 count = aCount + offset; + PRUint32 count = aCount + offset; if (!mAudioHandle) return; @@ -168,21 +173,28 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount) } } - PRInt32 available = Available(); - if (available < count) { - mBufferOverflow.AppendElements(s_data.get() + available, (count - available)); - count = available; + if (!aBlocking) { + // We're running in non-blocking mode, crop the data to the amount + // which is available in the audio buffer, and save the rest for + // subsequent calls. + PRUint32 available = Available(); + if (available < count) { + mBufferOverflow.AppendElements(s_data.get() + available, (count - available)); + count = available; + } } if (sa_stream_write(static_cast(mAudioHandle), - s_data.get(), count * sizeof(short)) != SA_SUCCESS) { + s_data.get(), + count * sizeof(short)) != SA_SUCCESS) + { PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStream: sa_stream_write error")); Shutdown(); } } } -PRInt32 nsAudioStream::Available() +PRUint32 nsAudioStream::Available() { // If the audio backend failed to open, lie and say we'll accept some // data. @@ -225,7 +237,7 @@ void nsAudioStream::Pause() { if (!mAudioHandle) return; - + mPaused = PR_TRUE; sa_stream_pause(static_cast(mAudioHandle)); } @@ -233,14 +245,14 @@ void nsAudioStream::Resume() { if (!mAudioHandle) return; - + mPaused = PR_FALSE; sa_stream_resume(static_cast(mAudioHandle)); } -float nsAudioStream::GetPosition() +PRInt64 nsAudioStream::GetPosition() { if (!mAudioHandle) - return -1.0; + return -1; sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE; #if defined(XP_WIN) @@ -249,9 +261,9 @@ float nsAudioStream::GetPosition() PRInt64 position = 0; if (sa_stream_get_position(static_cast(mAudioHandle), positionType, &position) == SA_SUCCESS) { - return (position / float(mRate) / mChannels / sizeof(short)); + return ((1000 * position) / mRate / mChannels / sizeof(short)); } - return -1.0; + return -1; } diff --git a/content/media/nsAudioStream.h b/content/media/nsAudioStream.h index 5ba06b31419d..a054e67f7af4 100644 --- a/content/media/nsAudioStream.h +++ b/content/media/nsAudioStream.h @@ -76,11 +76,14 @@ class nsAudioStream // Write sound data to the audio hardware. aBuf is an array of samples in // the format specified by mFormat of length aCount. aCount should be // evenly divisible by the number of channels in this audio stream. - void Write(const void* aBuf, PRUint32 aCount); + // When aBlocking is PR_TRUE, we'll block until the write has completed, + // otherwise we'll buffer any data we can't write immediately, and write + // it in a later call. + void Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking); // Return the number of sound samples that can be written to the audio device // without blocking. - PRInt32 Available(); + PRUint32 Available(); // Set the current volume of the audio playback. This is a value from // 0 (meaning muted) to 1 (meaning full volume). @@ -95,9 +98,12 @@ class nsAudioStream // Resume audio playback void Resume(); - // Return the position in seconds of the sample being played by the + // Return the position in milliseconds of the sample being played by the // audio hardware. - float GetPosition(); + PRInt64 GetPosition(); + + // Returns PR_TRUE when the audio stream is paused. + PRBool IsPaused() { return mPaused; } private: double mVolume; @@ -112,5 +118,8 @@ class nsAudioStream // backend, the remaining samples are stored in this variable. They // will be written on the next Write() request. nsTArray mBufferOverflow; + + // PR_TRUE if this audio stream is paused. + PRPackedBool mPaused; }; #endif diff --git a/content/media/ogg/Makefile.in b/content/media/ogg/Makefile.in index 6ce9b92c4793..d8eff6105e47 100644 --- a/content/media/ogg/Makefile.in +++ b/content/media/ogg/Makefile.in @@ -49,11 +49,15 @@ LIBXUL_LIBRARY = 1 EXPORTS += \ nsChannelReader.h \ nsOggDecoder.h \ + nsOggCodecState.h \ $(NULL) CPPSRCS = \ nsChannelReader.cpp \ nsOggDecoder.cpp \ + nsOggCodecState.cpp \ + nsOggReader.cpp \ + nsOggPlayStateMachine.cpp \ $(NULL) FORCE_STATIC_LIB = 1 diff --git a/content/media/ogg/nsOggCodecState.cpp b/content/media/ogg/nsOggCodecState.cpp new file mode 100644 index 000000000000..982b60cd2fed --- /dev/null +++ b/content/media/ogg/nsOggCodecState.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "nsDebug.h" +#include "nsOggCodecState.h" +#include "nsOggDecoder.h" +#include +#include "nsTraceRefcnt.h" +#include "nsOggHacks.h" + +/* + The maximum height and width of the video. Used for + sanitizing the memory allocation of the RGB buffer. + The maximum resolution we anticipate encountering in the + wild is 2160p - 3840x2160 pixels. +*/ +#define MAX_VIDEO_WIDTH 4000 +#define MAX_VIDEO_HEIGHT 3000 + +// Adds two 64bit numbers, retuns PR_TRUE if addition succeeded, or PR_FALSE +// if addition would result in an overflow. +static PRBool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult); + +// 64 bit integer multiplication with overflow checking. Returns PR_TRUE +// if the multiplication was successful, or PR_FALSE if the operation resulted +// in an integer overflow. +static PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult); + +// Defined in nsOggReader.cpp. +extern PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult); + + +nsOggCodecState* +nsOggCodecState::Create(ogg_page* aPage) +{ + nsAutoPtr codecState; + if (aPage->body_len > 6 && memcmp(aPage->body+1, "theora", 6) == 0) { + codecState = new nsTheoraState(aPage); + } else if (aPage->body_len > 6 && memcmp(aPage->body+1, "vorbis", 6) == 0) { + codecState = new nsVorbisState(aPage); + } else if (aPage->body_len > 8 && memcmp(aPage->body, "fishead\0", 8) == 0) { + codecState = new nsSkeletonState(aPage); + } else { + codecState = new nsOggCodecState(aPage); + } + return codecState->nsOggCodecState::Init() ? codecState.forget() : nsnull; +} + +nsOggCodecState::nsOggCodecState(ogg_page* aBosPage) : + mPacketCount(0), + mSerial(ogg_page_serialno(aBosPage)), + mActive(PR_FALSE), + mDoneReadingHeaders(PR_FALSE) +{ + MOZ_COUNT_CTOR(nsOggCodecState); + memset(&mState, 0, sizeof(ogg_stream_state)); +} + +nsOggCodecState::~nsOggCodecState() { + MOZ_COUNT_DTOR(nsOggCodecState); + int ret = ogg_stream_clear(&mState); + NS_ASSERTION(ret == 0, "ogg_stream_clear failed"); +} + +nsresult nsOggCodecState::Reset() { + if (ogg_stream_reset(&mState) != 0) { + return NS_ERROR_FAILURE; + } + mBuffer.Erase(); + return NS_OK; +} + +PRBool nsOggCodecState::Init() { + int ret = ogg_stream_init(&mState, mSerial); + return ret == 0; +} + +void nsPageQueue::Append(ogg_page* aPage) { + ogg_page* p = new ogg_page(); + p->header_len = aPage->header_len; + p->body_len = aPage->body_len; + p->header = new unsigned char[p->header_len + p->body_len]; + p->body = p->header + p->header_len; + memcpy(p->header, aPage->header, p->header_len); + memcpy(p->body, aPage->body, p->body_len); + nsDeque::Push(p); +} + +PRBool nsOggCodecState::PageInFromBuffer() { + if (mBuffer.IsEmpty()) + return PR_FALSE; + ogg_page *p = mBuffer.PeekFront(); + int ret = ogg_stream_pagein(&mState, p); + NS_ENSURE_TRUE(ret == 0, PR_FALSE); + mBuffer.PopFront(); + delete p->header; + delete p; + return PR_TRUE; +} + +nsTheoraState::nsTheoraState(ogg_page* aBosPage) : + nsOggCodecState(aBosPage), + mSetup(0), + mCtx(0), + mFrameDuration(0), + mFrameRate(0), + mAspectRatio(0) +{ + MOZ_COUNT_CTOR(nsTheoraState); + th_info_init(&mInfo); + th_comment_init(&mComment); +} + +nsTheoraState::~nsTheoraState() { + MOZ_COUNT_DTOR(nsTheoraState); + th_setup_free(mSetup); + th_decode_free(mCtx); + th_comment_clear(&mComment); + th_info_clear(&mInfo); +} + +PRBool nsTheoraState::Init() { + if (!mActive) + return PR_FALSE; + mCtx = th_decode_alloc(&mInfo, mSetup); + if (mCtx == NULL) { + return mActive = PR_FALSE; + } + + PRUint32 n = mInfo.fps_numerator; + PRUint32 d = mInfo.fps_denominator; + + mFrameRate = (n == 0 || d == 0) ? + 0.0 : static_cast(n) / static_cast(d); + + PRUint32 c; + if (!MulOverflow32(1000, d, c)) { + return mActive = PR_FALSE; + } + mFrameDuration = c / n; + + n = mInfo.aspect_numerator; + d = mInfo.aspect_denominator; + mAspectRatio = (n == 0 || d == 0) ? + 1.0 : static_cast(n) / static_cast(d); + + // Ensure the frame isn't larger than our prescribed maximum. + PRUint32 pixels; + if (!MulOverflow32(mInfo.pic_width, mInfo.pic_height, pixels) || + pixels > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT || + pixels == 0) + { + return mActive = PR_FALSE; + } + + return PR_TRUE; +} + +PRBool +nsTheoraState::DecodeHeader(ogg_packet* aPacket) +{ + mPacketCount++; + int ret = th_decode_headerin(&mInfo, + &mComment, + &mSetup, + aPacket); + + // We must determine when we've read the last header packet. + // th_decode_headerin() does not tell us when it's read the last header, so + // we must keep track of the headers externally. + // + // There are 3 header packets, the Identification, Comment, and Setup + // headers, which must be in that order. If they're out of order, the file + // is invalid. If we've successfully read a header, and it's the setup + // header, then we're done reading headers. The first byte of each packet + // determines it's type as follows: + // 0x80 -> Identification header + // 0x81 -> Comment header + // 0x82 -> Setup header + // See http://www.theora.org/doc/Theora.pdf Chapter 6, "Bitstream Headers", + // for more details of the Ogg/Theora containment scheme. + PRBool isSetupHeader = aPacket->bytes > 0 && aPacket->packet[0] == 0x82; + if (ret < 0 || mPacketCount > 3) { + // We've received an error, or the first three packets weren't valid + // header packets, assume bad input, and don't activate the bitstream. + mDoneReadingHeaders = PR_TRUE; + } else if (ret > 0 && isSetupHeader && mPacketCount == 3) { + // Successfully read the three header packets. + mDoneReadingHeaders = PR_TRUE; + mActive = PR_TRUE; + } + return mDoneReadingHeaders; +} + +PRInt64 +nsTheoraState::Time(PRInt64 granulepos) { + if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) { + return -1; + } + PRInt64 t = 0; + PRInt64 frameno = th_granule_frame(mCtx, granulepos); + if (!AddOverflow(frameno, 1, t)) + return -1; + if (!MulOverflow(t, 1000, t)) + return -1; + if (!MulOverflow(t, mInfo.fps_denominator, t)) + return -1; + return t / mInfo.fps_numerator; +} + +PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) { + if (granulepos < 0 || !mActive || mInfo.fps_numerator == 0) { + return -1; + } + PRInt64 t = 0; + PRInt64 frameno = th_granule_frame(mCtx, granulepos); + if (!MulOverflow(frameno, 1000, t)) + return -1; + if (!MulOverflow(t, mInfo.fps_denominator, t)) + return -1; + return t / mInfo.fps_numerator; +} + +PRInt64 +nsTheoraState::MaxKeyframeOffset() +{ + // Determine the maximum time in milliseconds by which a key frame could + // offset for the theora bitstream. Theora granulepos encode time as: + // ((key_frame_number << granule_shift) + frame_offset). + // Therefore the maximum possible time by which any frame could be offset + // from a keyframe is the duration of (1 << granule_shift) - 1) frames. + PRInt64 frameDuration; + PRInt64 keyframeDiff; + + PRInt64 shift = mInfo.keyframe_granule_shift; + + // Max number of frames keyframe could possibly be offset. + keyframeDiff = (1 << shift) - 1; + + // Length of frame in ms. + PRInt64 d = 0; // d will be 0 if multiplication overflows. + MulOverflow(1000, mInfo.fps_denominator, d); + frameDuration = d / mInfo.fps_numerator; + + // Total time in ms keyframe can be offset from any given frame. + return frameDuration * keyframeDiff; +} + +nsresult nsVorbisState::Reset() +{ + nsresult res = NS_OK; + if (mActive && vorbis_synthesis_restart(&mDsp) != 0) { + res = NS_ERROR_FAILURE; + } + if (NS_FAILED(nsOggCodecState::Reset())) { + return NS_ERROR_FAILURE; + } + return res; +} + +nsVorbisState::nsVorbisState(ogg_page* aBosPage) : + nsOggCodecState(aBosPage) +{ + MOZ_COUNT_CTOR(nsVorbisState); + vorbis_info_init(&mInfo); + vorbis_comment_init(&mComment); + memset(&mDsp, 0, sizeof(vorbis_dsp_state)); + memset(&mBlock, 0, sizeof(vorbis_block)); +} + +nsVorbisState::~nsVorbisState() { + MOZ_COUNT_DTOR(nsVorbisState); + vorbis_block_clear(&mBlock); + vorbis_dsp_clear(&mDsp); + vorbis_info_clear(&mInfo); + vorbis_comment_clear(&mComment); +} + +PRBool nsVorbisState::DecodeHeader(ogg_packet* aPacket) { + mPacketCount++; + int ret = vorbis_synthesis_headerin(&mInfo, + &mComment, + aPacket); + // We must determine when we've read the last header packet. + // vorbis_synthesis_headerin() does not tell us when it's read the last + // header, so we must keep track of the headers externally. + // + // There are 3 header packets, the Identification, Comment, and Setup + // headers, which must be in that order. If they're out of order, the file + // is invalid. If we've successfully read a header, and it's the setup + // header, then we're done reading headers. The first byte of each packet + // determines it's type as follows: + // 0x1 -> Identification header + // 0x3 -> Comment header + // 0x5 -> Setup header + // For more details of the Vorbis/Ogg containment scheme, see the Vorbis I + // Specification, Chapter 4, Codec Setup and Packet Decode: + // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-580004 + + PRBool isSetupHeader = aPacket->bytes > 0 && aPacket->packet[0] == 0x5; + + if (ret < 0 || mPacketCount > 3) { + // We've received an error, or the first three packets weren't valid + // header packets, assume bad input, and don't activate the bitstream. + mDoneReadingHeaders = PR_TRUE; + } else if (ret == 0 && isSetupHeader && mPacketCount == 3) { + // Successfully read the three header packets, activate the bitstream. + mDoneReadingHeaders = PR_TRUE; + mActive = PR_TRUE; + } + return mDoneReadingHeaders; +} + +PRBool nsVorbisState::Init() +{ + if (!mActive) + return PR_FALSE; + + int ret = vorbis_synthesis_init(&mDsp, &mInfo); + if (ret != 0) { + NS_WARNING("vorbis_synthesis_init() failed initializing vorbis bitstream"); + return mActive = PR_FALSE; + } + ret = vorbis_block_init(&mDsp, &mBlock); + if (ret != 0) { + NS_WARNING("vorbis_block_init() failed initializing vorbis bitstream"); + if (mActive) { + vorbis_dsp_clear(&mDsp); + } + return mActive = PR_FALSE; + } + return PR_TRUE; +} + +PRInt64 nsVorbisState::Time(PRInt64 granulepos) { + if (granulepos == -1 || !mActive || mDsp.vi->rate == 0) { + return -1; + } + PRInt64 t = 0; + MulOverflow(1000, granulepos, t); + return t / mDsp.vi->rate; +} + +nsSkeletonState::nsSkeletonState(ogg_page* aBosPage) + : nsOggCodecState(aBosPage) +{ + MOZ_COUNT_CTOR(nsSkeletonState); +} + +nsSkeletonState::~nsSkeletonState() +{ + MOZ_COUNT_DTOR(nsSkeletonState); +} + +PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket) +{ + if (aPacket->e_o_s) { + mActive = PR_TRUE; + mDoneReadingHeaders = PR_TRUE; + } + return mDoneReadingHeaders; +} + +// Adds two 64bit numbers, retuns PR_TRUE if addition succeeded, or PR_FALSE +// if addition would result in an overflow. +static PRBool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) { + if (b < 1) { + if (PR_INT64_MIN - b <= a) { + aResult = a + b; + return PR_TRUE; + } + } else if (PR_INT64_MAX - b >= a) { + aResult = a + b; + return PR_TRUE; + } + return PR_FALSE; +} + +// 64 bit integer multiplication with overflow checking. Returns PR_TRUE +// if the multiplication was successful, or PR_FALSE if the operation resulted +// in an integer overflow. +static PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) { + // We break a multiplication a * b into of sign_a * sign_b * abs(a) * abs(b) + // + // This is equivalent to: + // + // (sign_a * sign_b) * ((a_hi * 2^32) + a_lo) * ((b_hi * 2^32) + b_lo) + // + // Which is equivalent to: + // + // (sign_a * sign_b) * + // ((a_hi * b_hi << 64) + + // (a_hi * b_lo << 32) + (a_lo * b_hi << 32) + + // a_lo * b_lo) + // + // So to check if a*b overflows, we must check each sub part of the above + // sum. + // + // Note: -1 * PR_INT64_MIN == PR_INT64_MIN ; we can't negate PR_INT64_MIN! + // Note: Shift of negative numbers is undefined. + // + // Figure out the sign after multiplication. Then we can just work with + // unsigned numbers. + PRInt64 sign = (!(a < 0) == !(b < 0)) ? 1 : -1; + + PRInt64 abs_a = (a < 0) ? -a : a; + PRInt64 abs_b = (b < 0) ? -b : b; + + if (abs_a < 0) { + NS_ASSERTION(a == PR_INT64_MIN, "How else can this happen?"); + if (b == 0 || b == 1) { + aResult = a * b; + return PR_TRUE; + } else { + return PR_FALSE; + } + } + + if (abs_b < 0) { + NS_ASSERTION(b == PR_INT64_MIN, "How else can this happen?"); + if (a == 0 || a == 1) { + aResult = a * b; + return PR_TRUE; + } else { + return PR_FALSE; + } + } + + NS_ASSERTION(abs_a >= 0 && abs_b >= 0, "abs values must be non-negative"); + + PRInt64 a_hi = abs_a >> 32; + PRInt64 a_lo = abs_a & 0xFFFFFFFF; + PRInt64 b_hi = abs_b >> 32; + PRInt64 b_lo = abs_b & 0xFFFFFFFF; + + NS_ASSERTION((a_hi<<32) + a_lo == abs_a, "Partition must be correct"); + NS_ASSERTION((b_hi<<32) + b_lo == abs_b, "Partition must be correct"); + + // In the sub-equation (a_hi * b_hi << 64), if a_hi or b_hi + // are non-zero, this will overflow as it's shifted by 64. + // Abort if this overflows. + if (a_hi != 0 && b_hi != 0) { + return PR_FALSE; + } + + // We can now assume that either a_hi or b_hi is 0. + NS_ASSERTION(a_hi == 0 || b_hi == 0, "One of these must be 0"); + + // Next we calculate: + // (a_hi * b_lo << 32) + (a_lo * b_hi << 32) + // We can factor this as: + // (a_hi * b_lo + a_lo * b_hi) << 32 + PRInt64 q = a_hi * b_lo + a_lo * b_hi; + if (q > PR_INT32_MAX) { + // q will overflow when we shift by 32; abort. + return PR_FALSE; + } + q <<= 32; + + // Both a_lo and b_lo are less than INT32_MAX, so can't overflow. + PRUint64 lo = a_lo * b_lo; + if (lo > PR_INT64_MAX) { + return PR_FALSE; + } + + // Add the final result. We must check for overflow during addition. + if (!AddOverflow(q, static_cast(lo), aResult)) { + return PR_FALSE; + } + + aResult *= sign; + NS_ASSERTION(a * b == aResult, "We didn't overflow, but result is wrong!"); + return PR_TRUE; +} diff --git a/content/media/ogg/nsOggCodecState.h b/content/media/ogg/nsOggCodecState.h new file mode 100644 index 000000000000..2b87584e7746 --- /dev/null +++ b/content/media/ogg/nsOggCodecState.h @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#if !defined(nsOggCodecState_h_) +#define nsOggCodecState_h_ + +#include +#include +#include +#include + +class OggPageDeallocator : public nsDequeFunctor { + virtual void* operator() (void* aPage) { + ogg_page* p = static_cast(aPage); + delete p->header; + delete p; + return nsnull; + } +}; + +// A queue of ogg_pages. When we read a page, and it's not from the bitstream +// which we're looking for a page for, we buffer the page in the nsOggCodecState, +// rather than pushing it immediately into the ogg_stream_state object. This +// is because if we're skipping up to the next keyframe in very large frame +// sized videos, there may be several megabytes of data between keyframes, +// and the ogg_stream_state would end up resizing its buffer every time we +// added a new 4K page to the bitstream, which kills performance on Windows. +class nsPageQueue : private nsDeque { +public: + nsPageQueue() : nsDeque(new OggPageDeallocator()) {} + ~nsPageQueue() { Erase(); } + PRBool IsEmpty() { return nsDeque::GetSize() == 0; } + void Append(ogg_page* aPage); + ogg_page* PopFront() { return static_cast(nsDeque::PopFront()); } + ogg_page* PeekFront() { return static_cast(nsDeque::PeekFront()); } + void Erase() { nsDeque::Erase(); } +}; + +// Encapsulates the data required for decoding an ogg bitstream and for +// converting granulepos to timestamps. +class nsOggCodecState { + public: + // Ogg types we know about + enum CodecType { + TYPE_VORBIS=0, + TYPE_THEORA=1, + TYPE_SKELETON=2, + TYPE_UNKNOWN=3 + }; + + public: + nsOggCodecState(ogg_page* aBosPage); + virtual ~nsOggCodecState(); + + // Factory for creating nsCodecStates. + static nsOggCodecState* Create(ogg_page* aPage); + + virtual CodecType GetType() { return TYPE_UNKNOWN; } + + // Reads a header packet. Returns PR_TRUE when last header has been read. + virtual PRBool DecodeHeader(ogg_packet* aPacket) { + return (mDoneReadingHeaders = PR_TRUE); + } + + // Returns the end time that a granulepos represents. + virtual PRInt64 Time(PRInt64 granulepos) { return -1; } + + // Returns the start time that a granulepos represents. + virtual PRInt64 StartTime(PRInt64 granulepos) { return -1; } + + // Initializes the codec state. + virtual PRBool Init(); + + // Returns PR_TRUE when this bitstream has finished reading all its + // header packets. + PRBool DoneReadingHeaders() { return mDoneReadingHeaders; } + + // Deactivates the bitstream. Only the primary video and audio bitstreams + // should be active. + void Deactivate() { mActive = PR_FALSE; } + + // Resets decoding state. + virtual nsresult Reset(); + + // Clones a page and adds it to our buffer of pages which we'll insert to + // the bitstream at a later time (using PageInFromBuffer()). Memory stored in + // cloned pages is freed when Reset() or PageInFromBuffer() are called. + inline void AddToBuffer(ogg_page* aPage) { mBuffer.Append(aPage); } + + // Returns PR_TRUE if we had a buffered page and we successfully inserted it + // into the bitstream. + PRBool PageInFromBuffer(); + +public: + + // Number of packets read. + PRUint64 mPacketCount; + + // Serial number of the bitstream. + PRUint32 mSerial; + + // Ogg specific state. + ogg_stream_state mState; + + // Buffer of pages which we've not yet inserted into the ogg_stream_state. + nsPageQueue mBuffer; + + // Is the bitstream active; whether we're decoding and playing this bitstream. + PRPackedBool mActive; + + // PR_TRUE when all headers packets have been read. + PRPackedBool mDoneReadingHeaders; +}; + +class nsVorbisState : public nsOggCodecState { +public: + nsVorbisState(ogg_page* aBosPage); + virtual ~nsVorbisState(); + + virtual CodecType GetType() { return TYPE_VORBIS; } + virtual PRBool DecodeHeader(ogg_packet* aPacket); + virtual PRInt64 Time(PRInt64 granulepos); + virtual PRBool Init(); + virtual nsresult Reset(); + + vorbis_info mInfo; + vorbis_comment mComment; + vorbis_dsp_state mDsp; + vorbis_block mBlock; +}; + +class nsTheoraState : public nsOggCodecState { +public: + nsTheoraState(ogg_page* aBosPage); + virtual ~nsTheoraState(); + + virtual CodecType GetType() { return TYPE_THEORA; } + virtual PRBool DecodeHeader(ogg_packet* aPacket); + virtual PRInt64 Time(PRInt64 granulepos); + virtual PRInt64 StartTime(PRInt64 granulepos); + virtual PRBool Init(); + + // Returns the maximum number of milliseconds which a keyframe can be offset + // from any given interframe. + PRInt64 MaxKeyframeOffset(); + + th_info mInfo; + th_comment mComment; + th_setup_info *mSetup; + th_dec_ctx* mCtx; + + // Frame duration in ms. + PRUint32 mFrameDuration; + + // Number of frames per second. + float mFrameRate; + + float mAspectRatio; +}; + +class nsSkeletonState : public nsOggCodecState { +public: + nsSkeletonState(ogg_page* aBosPage); + virtual ~nsSkeletonState(); + virtual CodecType GetType() { return TYPE_SKELETON; } + virtual PRBool DecodeHeader(ogg_packet* aPacket); + virtual PRInt64 Time(PRInt64 granulepos) { return -1; } + virtual PRBool Init() { return PR_TRUE; } +}; + +#endif diff --git a/content/media/ogg/nsOggDecoder.cpp b/content/media/ogg/nsOggDecoder.cpp index 37bcaf58e7aa..b4ba4dcc7b62 100644 --- a/content/media/ogg/nsOggDecoder.cpp +++ b/content/media/ogg/nsOggDecoder.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Chris Double + * Chris Pearce * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,1945 +37,31 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsOggDecoder.h" - +#include "nsOggPlayStateMachine.h" #include -#include "prmem.h" -#include "nsIFrame.h" -#include "nsIDocument.h" -#include "nsThreadUtils.h" -#include "nsIDOMHTMLMediaElement.h" #include "nsNetUtil.h" #include "nsAudioStream.h" -#include "nsChannelReader.h" #include "nsHTMLVideoElement.h" #include "nsIObserver.h" #include "nsIObserverService.h" -#include "nsAutoLock.h" #include "nsTArray.h" -#include "nsNetUtil.h" - -using mozilla::TimeDuration; -using mozilla::TimeStamp; -using namespace mozilla::layers; +#include "nsOggCodecState.h" +#include "nsOggDecoder.h" +#include "nsOggReader.h" #ifdef PR_LOGGING -static PRLogModuleInfo* gOggDecoderLog; +PRLogModuleInfo* gOggDecoderLog; #define LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) #else #define LOG(type, msg) #endif -/* - The maximum height and width of the video. Used for - sanitizing the memory allocation of the RGB buffer. - The maximum resolution we anticipate encountering in the - wild is 2160p - 3840x2160 pixels. -*/ -#define MAX_VIDEO_WIDTH 4000 -#define MAX_VIDEO_HEIGHT 3000 - -// The number of entries in oggplay buffer list. This value is totally -// arbitrary. Note that the actual number of video/audio frames buffered is -// twice this, because the current implementation releases OggPlay's buffer -// entries and stores references or copies of the underlying data in the -// FrameQueue. -#define OGGPLAY_BUFFER_SIZE 5 - -// The number of frames to read before audio callback is called. -// This value is the one used by the oggplay examples. -#define OGGPLAY_FRAMES_PER_CALLBACK 2048 - -// Offset into Ogg buffer containing audio information. This value -// is the one used by the oggplay examples. -#define OGGPLAY_AUDIO_OFFSET 250L - -// Wait this number of seconds when buffering, then leave and play -// as best as we can if the required amount of data hasn't been -// retrieved. -#define BUFFERING_WAIT 15 - -// The amount of data to retrieve during buffering is computed based -// on the download rate. BUFFERING_MIN_RATE is the minimum download -// rate to be used in that calculation to help avoid constant buffering -// attempts at a time when the average download rate has not stabilised. -#define BUFFERING_MIN_RATE 50000 -#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x)) - -// The number of seconds of buffer data before buffering happens -// based on current playback rate. -#define BUFFERING_SECONDS_LOW_WATER_MARK 1 - -// The minimum size buffered byte range inside which we'll consider -// trying a bounded-seek. When we seek, we first try to seek inside all -// buffered ranges larger than this, and if they all fail we fall back to -// an unbounded seek over the whole media. 64K is approximately 16 pages. -#define MIN_BOUNDED_SEEK_SIZE (64 * 1024) - -class nsOggStepDecodeEvent; - -/* - All reading (including seeks) from the nsMediaStream are done on the - decoding thread. The decoder thread is informed before closing that - the stream is about to close via the Shutdown - event. oggplay_prepare_for_close is called before sending the - shutdown event to tell liboggplay to shutdown. - - This call results in oggplay internally not calling any - read/write/seek/tell methods, and returns a value that results in - stopping the decoder thread. - - oggplay_close is called in the destructor which results in the media - stream being closed. This is how the nsMediaStream contract that no - read/seeking must occur during or after Close is called is enforced. - - This object keeps pointers to the nsOggDecoder and nsChannelReader - objects. Since the lifetime of nsOggDecodeStateMachine is - controlled by nsOggDecoder it will never have a stale reference to - these objects. The reader is destroyed by the call to oggplay_close - which is done in the destructor so again this will never be a stale - reference. - - All internal state is synchronised via the decoder monitor. NotifyAll - on the monitor is called when the state of the state machine is changed - by the main thread. The following changes to state cause a notify: - - mState and data related to that state changed (mSeekTime, etc) - Ogg Metadata Loaded - First Frame Loaded - Frame decoded - - See nsOggDecoder.h for more details. -*/ -class nsOggDecodeStateMachine : public nsRunnable -{ - friend class nsOggStepDecodeEvent; -public: - // Object to hold the decoded data from a frame - class FrameData { - public: - FrameData() : - mVideoHeader(nsnull), - mVideoWidth(0), - mVideoHeight(0), - mUVWidth(0), - mUVHeight(0), - mDecodedFrameTime(0.0), - mTime(0.0) - { - MOZ_COUNT_CTOR(FrameData); - } - - ~FrameData() - { - MOZ_COUNT_DTOR(FrameData); - ClearVideoHeader(); - } - - void ClearVideoHeader() { - if (mVideoHeader) { - oggplay_callback_info_unlock_item(mVideoHeader); - mVideoHeader = nsnull; - } - } - - // Write the audio data from the frame to the Audio stream. - void Write(nsAudioStream* aStream) - { - aStream->Write(mAudioData.Elements(), mAudioData.Length()); - mAudioData.Clear(); - } - - void SetVideoHeader(OggPlayDataHeader* aVideoHeader) - { - NS_ABORT_IF_FALSE(!mVideoHeader, "Frame already owns a video header"); - mVideoHeader = aVideoHeader; - oggplay_callback_info_lock_item(mVideoHeader); - } - - // The position in the stream where this frame ended, in bytes - PRInt64 mEndStreamPosition; - OggPlayDataHeader* mVideoHeader; - nsTArray mAudioData; - int mVideoWidth; - int mVideoHeight; - int mUVWidth; - int mUVHeight; - float mDecodedFrameTime; - float mTime; - OggPlayStreamInfo mState; - }; - - // A queue of decoded video frames. - class FrameQueue - { - public: - FrameQueue() : - mHead(0), - mTail(0), - mCount(0) - { - } - - void Push(FrameData* frame) - { - NS_ASSERTION(!IsFull(), "FrameQueue is full"); - mQueue[mTail] = frame; - mTail = (mTail+1) % OGGPLAY_BUFFER_SIZE; - ++mCount; - } - - FrameData* Peek() const - { - NS_ASSERTION(mCount > 0, "FrameQueue is empty"); - - return mQueue[mHead]; - } - - FrameData* Pop() - { - NS_ASSERTION(mCount, "FrameQueue is empty"); - - FrameData* result = mQueue[mHead]; - mHead = (mHead + 1) % OGGPLAY_BUFFER_SIZE; - --mCount; - return result; - } - - PRBool IsEmpty() const - { - return mCount == 0; - } - - PRUint32 GetCount() const - { - return mCount; - } - - PRBool IsFull() const - { - return mCount == OGGPLAY_BUFFER_SIZE; - } - - PRUint32 ResetTimes(float aPeriod) - { - PRUint32 frames = 0; - if (mCount > 0) { - PRUint32 current = mHead; - do { - mQueue[current]->mTime = frames * aPeriod; - frames += 1; - current = (current + 1) % OGGPLAY_BUFFER_SIZE; - } while (current != mTail); - } - return frames; - } - - private: - FrameData* mQueue[OGGPLAY_BUFFER_SIZE]; - PRUint32 mHead; - PRUint32 mTail; - // This isn't redundant with mHead/mTail, since when mHead == mTail - // it's ambiguous whether the queue is full or empty - PRUint32 mCount; - }; - - // Enumeration for the valid states - enum State { - DECODER_STATE_DECODING_METADATA, - DECODER_STATE_DECODING, - DECODER_STATE_SEEKING, - DECODER_STATE_BUFFERING, - DECODER_STATE_COMPLETED, - DECODER_STATE_SHUTDOWN - }; - - nsOggDecodeStateMachine(nsOggDecoder* aDecoder); - ~nsOggDecodeStateMachine(); - - // Cause state transitions. These methods obtain the decoder monitor - // to synchronise the change of state, and to notify other threads - // that the state has changed. - void Shutdown(); - void Decode(); - void Seek(float aTime); - void StopStepDecodeThread(nsAutoMonitor* aMonitor); - - NS_IMETHOD Run(); - - PRBool HasAudio() - { - NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA, "HasAudio() called during invalid state"); - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mAudioTrack != -1; - } - - // Decode one frame of data, returning the OggPlay error code. Must - // be called only when the current state > DECODING_METADATA. The decode - // monitor MUST NOT be locked during this call since it can take a long - // time. liboggplay internally handles locking. - // Any return value apart from those below is mean decoding cannot continue. - // E_OGGPLAY_CONTINUE = One frame decoded and put in buffer list - // E_OGGPLAY_USER_INTERRUPT = One frame decoded, buffer list is now full - // E_OGGPLAY_TIMEOUT = No frames decoded, timed out - OggPlayErrorCode DecodeFrame(); - - // Handle any errors returned by liboggplay when decoding a frame. - // Since this function can change the decoding state it must be called - // with the decoder lock held. - void HandleDecodeErrors(OggPlayErrorCode r); - - // Returns the next decoded frame of data. The caller is responsible - // for freeing the memory returned. This function must be called - // only when the current state > DECODING_METADATA. The decode - // monitor lock does not need to be locked during this call since - // liboggplay internally handles locking. - FrameData* NextFrame(); - - // Play a frame of decoded video. The decode monitor is obtained - // internally by this method for synchronisation. - void PlayFrame(); - - // Play the video data from the given frame. The decode monitor - // must be locked when calling this method. - void PlayVideo(FrameData* aFrame); - - // Plays the audio for the frame, plus any outstanding audio data - // buffered by nsAudioStream and not yet written to the - // hardware. The audio data for the frame is cleared out so - // subsequent calls with the same frame do not re-write the data. - // The decode monitor must be locked when calling this method. - void PlayAudio(FrameData* aFrame); - - // Called from the main thread to get the current frame time. The decoder - // monitor must be obtained before calling this. - float GetCurrentTime(); - - // Called from the main thread to get the duration. The decoder monitor - // must be obtained before calling this. It is in units of milliseconds. - PRInt64 GetDuration(); - - // Called from the main thread to set the duration of the media resource - // if it is able to be obtained via HTTP headers. The decoder monitor - // must be obtained before calling this. - void SetDuration(PRInt64 aDuration); - - // Called from the main thread to set whether the media resource can - // be seeked. The decoder monitor must be obtained before calling this. - void SetSeekable(PRBool aSeekable); - - // Set the audio volume. The decoder monitor must be obtained before - // calling this. - void SetVolume(float aVolume); - - // Clear the flag indicating that a playback position change event - // is currently queued. This is called from the main thread and must - // be called with the decode monitor held. - void ClearPositionChangeFlag(); - - // Called by decoder and main thread. - nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus(); - - // Must be called with the decode monitor held. Can be called by main - // thread. - PRBool HaveNextFrameData() const { - return !mDecodedFrames.IsEmpty() && - (mDecodedFrames.Peek()->mDecodedFrameTime > mCurrentFrameTime || - mDecodedFrames.GetCount() > 1); - } - - // Must be called with the decode monitor held. Can be called by main - // thread. - PRBool IsBuffering() const { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mState == nsOggDecodeStateMachine::DECODER_STATE_BUFFERING; - } - - // Must be called with the decode monitor held. Can be called by main - // thread. - PRBool IsSeeking() const { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mState == nsOggDecodeStateMachine::DECODER_STATE_SEEKING; - } - -protected: - - // Decodes from the current position until encountering a frame with time - // greater or equal to aSeekTime. - PRBool DecodeToFrame(nsAutoMonitor& aMonitor, - float aSeekTime); - - // Convert the OggPlay frame information into a format used by Gecko - // (RGB for video, float for sound, etc).The decoder monitor must be - // acquired in the scope of calls to these functions. They must be - // called only when the current state > DECODING_METADATA. - void HandleVideoData(FrameData* aFrame, int aTrackNum, OggPlayDataHeader* aVideoHeader); - void HandleAudioData(FrameData* aFrame, OggPlayAudioData* aAudioData, int aSize); - - void UpdateReadyState() { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - - nsCOMPtr event; - switch (GetNextFrameStatus()) { - case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING: - event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailableBuffering); - break; - case nsHTMLMediaElement::NEXT_FRAME_AVAILABLE: - event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameAvailable); - break; - case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE: - event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailable); - break; - default: - PR_NOT_REACHED("unhandled frame state"); - } - - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); - } - - // These methods can only be called on the decoding thread. - void LoadOggHeaders(nsChannelReader* aReader); - - // Initializes and opens the audio stream. Called from the decode - // thread only. Must be called with the decode monitor held. - void OpenAudioStream(); - - // Closes and releases resources used by the audio stream. Called - // from the decode thread only. Must be called with the decode - // monitor held. - void CloseAudioStream(); - - // Start playback of audio, either by opening or resuming the audio - // stream. Must be called with the decode monitor held. - void StartAudio(); - - // Stop playback of audio, either by closing or pausing the audio - // stream. Must be called with the decode monitor held. - void StopAudio(); - - // Start playback of media. Must be called with the decode monitor held. - // This opens or re-opens the audio stream for playback to start. - void StartPlayback(); - - // Stop playback of media. Must be called with the decode monitor held. - // This actually closes the audio stream and releases any OS resources. - void StopPlayback(); - - // Pause playback of media. Must be called with the decode monitor held. - // This does not close the OS based audio stream - it suspends it to be - // resumed later. - void PausePlayback(); - - // Resume playback of media. Must be called with the decode monitor held. - // This resumes a paused audio stream. - void ResumePlayback(); - - // Update the playback position. This can result in a timeupdate event - // and an invalidate of the frame being dispatched asynchronously if - // there is no such event currently queued. - // Only called on the decoder thread. Must be called with - // the decode monitor held. - void UpdatePlaybackPosition(float aTime); - - // Takes decoded frames from liboggplay's internal buffer and - // places them in our frame queue. Must be called with the decode - // monitor held. - void QueueDecodedFrames(); - - // Seeks the OggPlay to aTime, inside buffered byte ranges in aReader's - // media stream. - nsresult Seek(float aTime, nsChannelReader* aReader); - - // Sets the current video and audio track to active in liboggplay. - // Called from the decoder thread only. - void SetTracksActive(); - -private: - // ***** - // The follow fields are only accessed by the decoder thread - // ***** - - // The decoder object that created this state machine. The decoder - // always outlives us since it controls our lifetime. - nsOggDecoder* mDecoder; - - // The OggPlay handle. Synchronisation of calls to oggplay functions - // are handled by liboggplay. We control the lifetime of this - // object, destroying it in our destructor. - OggPlay* mPlayer; - - // Frame data containing decoded video/audio for the frame the - // current frame and the previous frame. Always accessed with monitor - // held. Written only via the decoder thread, but can be tested on - // main thread via HaveNextFrameData. - FrameQueue mDecodedFrames; - - // The time that playback started from the system clock. This is used - // for synchronising frames. It is reset after a seek as the mTime member - // of FrameData is reset to start at 0 from the first frame after a seek. - // Accessed only via the decoder thread. - TimeStamp mPlayStartTime; - - // The time that playback was most recently paused, either via - // buffering or pause. This is used to compute mPauseDuration for - // a/v sync adjustments. Accessed only via the decoder thread. - TimeStamp mPauseStartTime; - - // The total time that has been spent in completed pauses (via - // 'pause' or buffering). This is used to adjust for these - // pauses when computing a/v synchronisation. Accessed only via the - // decoder thread. - TimeDuration mPauseDuration; - - // PR_TRUE if the media is playing and the decoder has started - // the sound and adjusted the sync time for pauses. PR_FALSE - // if the media is paused and the decoder has stopped the sound - // and adjusted the sync time for pauses. Accessed only via the - // decoder thread. - PRPackedBool mPlaying; - - // Number of seconds of data video/audio data held in a frame. - // Accessed only via the decoder thread. - double mCallbackPeriod; - - // Video data. These are initially set when the metadata is loaded. - // They are only accessed from the decoder thread. - PRInt32 mVideoTrack; - float mFramerate; - float mAspectRatio; - - // Audio data. These are initially set when the metadata is loaded. - // They are only accessed from the decoder thread. - PRInt32 mAudioRate; - PRInt32 mAudioChannels; - PRInt32 mAudioTrack; - - // Time that buffering started. Used for buffering timeout and only - // accessed in the decoder thread. - TimeStamp mBufferingStart; - - // Download position where we should stop buffering. Only - // accessed in the decoder thread. - PRInt64 mBufferingEndOffset; - - // The last decoded video frame. Used for computing the sleep period - // between frames for a/v sync. Read/Write from the decode thread only. - PRUint64 mLastFrame; - - // The decoder position of the end of the last decoded video frame. - // Read/Write from the decode thread only. - PRInt64 mLastFramePosition; - - // Thread that steps through decoding each frame using liboggplay. Only accessed - // via the decode thread. - nsCOMPtr mStepDecodeThread; - - // ***** - // The follow fields are accessed by the decoder thread or - // the main thread. - // ***** - - // The decoder monitor must be obtained before modifying this state. - // NotifyAll on the monitor must be called when the state is changed by - // the main thread so the decoder thread can wake up. - State mState; - - // Position to seek to when the seek state transition occurs. The - // decoder monitor lock must be obtained before reading or writing - // this value. - float mSeekTime; - - // The audio stream resource. Used on the decode thread and the - // main thread (Via the SetVolume call). Synchronisation via - // mDecoder monitor. - nsAutoPtr mAudioStream; - - // The time of the current frame in seconds. This is referenced from - // 0.0 which is the initial start of the stream. Set by the decode - // thread, and read-only from the main thread to get the current - // time value. Synchronised via decoder monitor. - float mCurrentFrameTime; - - // The presentation times of the first frame that was decoded. This is - // the start time of the frame. This is subtracted from each frames' - // timestamp, so that playback appears to start at time 0 and end at - // time mDuration. Read/Written from the decode thread, read from the - // main thread. Synchronised via decoder monitor. - float mPlaybackStartTime; - - // Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written - // from the decode and main threads. Synchronised via decoder - // monitor. - float mVolume; - - // Duration of the media resource. It is accessed from the decoder and main - // threads. Synchronised via decoder monitor. It is in units of - // milliseconds. - PRInt64 mDuration; - - // PR_TRUE if the media resource can be seeked. Accessed from the decoder - // and main threads. Synchronised via decoder monitor. - PRPackedBool mSeekable; - - // PR_TRUE if an event to notify about a change in the playback - // position has been queued, but not yet run. It is set to PR_FALSE when - // the event is run. This allows coalescing of these events as they can be - // produced many times per second. Synchronised via decoder monitor. - PRPackedBool mPositionChangeQueued; - - // PR_TRUE if the step decode loop thread has finished decoding. It is - // written by the step decode thread and read and written by the state - // machine thread (but only written by the state machine thread while - // the step decode thread is not running). - // Synchronised via decoder monitor. - PRPackedBool mDecodingCompleted; - - // PR_TRUE if the step decode loop thread should exit now. It is - // written by the state machine thread and read by the step decode thread. - // Synchronised via decoder monitor. - PRPackedBool mExitStepDecodeThread; - - // PR_TRUE if the step decode loop has indicated that we need to buffer. - // Accessed by the step decode thread and the decode state machine thread. - // Synchronised via the decoder monitor. - PRPackedBool mBufferExhausted; - - // PR_TRUE if mDuration has a value obtained from an HTTP header. - // Read/Written from the decode and main threads. Synchronised via the - // decoder monitor. - PRPackedBool mGotDurationFromHeader; -}; - -// Event that gets posted to the thread that is responsible for decoding -// Ogg frames. Decodes each frame of an Ogg file. Locking of liboggplay -// is managed by liboggplay. The thread is created when the frames first -// need to be decoded and is shutdown when decoding is not needed (either -// completed, or seeking). -class nsOggStepDecodeEvent : public nsRunnable { -private: - // Since the lifetime of this event loop is controlled by the - // decode state machine object, it is safe to keep an - // unreferenced counted pointer to it, so we can inform - // it when we've finished decoding. - nsOggDecodeStateMachine* mDecodeStateMachine; - - // The lifetime of this player is managed by the decode state - // machine thread. This event is created and destroyed before - // the mPlayer object itself is deleted. - OggPlay* mPlayer; - -public: - nsOggStepDecodeEvent(nsOggDecodeStateMachine* machine, OggPlay* player) : - mDecodeStateMachine(machine), mPlayer(player) {} - - // Return true if we are in a state where the decoder should not be running. - PRBool InStopDecodingState() { - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecodeStateMachine->mDecoder->GetMonitor()); - return - mDecodeStateMachine->mState != nsOggDecodeStateMachine::DECODER_STATE_DECODING && - mDecodeStateMachine->mState != nsOggDecodeStateMachine::DECODER_STATE_BUFFERING; - } - - // This method will block on oggplay_step_decoding when oggplay's - // internal buffers are full. It is unblocked by the decode - // state machine thread via a call to oggplay_prepare_for_close - // during the shutdown protocol. It is unblocked during seeking - // by release frames from liboggplay's frame queue. - NS_IMETHOD Run() { - OggPlayErrorCode r = E_OGGPLAY_TIMEOUT; - nsAutoMonitor mon(mDecodeStateMachine->mDecoder->GetMonitor()); - nsOggDecoder* decoder = mDecodeStateMachine->mDecoder; - NS_ASSERTION(!mDecodeStateMachine->mDecodingCompleted, - "State machine should have cleared this flag"); - - while (!mDecodeStateMachine->mExitStepDecodeThread && - !InStopDecodingState() && - (r == E_OGGPLAY_TIMEOUT || - r == E_OGGPLAY_USER_INTERRUPT || - r == E_OGGPLAY_CONTINUE)) { - if (mDecodeStateMachine->mBufferExhausted) { - mon.Wait(); - } else { - // decoder and decoder->mReader are never null here because - // they are non-null through the lifetime of the state machine - // thread, which includes the lifetime of this thread. - PRInt64 initialDownloadPosition = - decoder->mReader->Stream()->GetCachedDataEnd(decoder->mDecoderPosition); - - mon.Exit(); - r = oggplay_step_decoding(mPlayer); - mon.Enter(); - - mDecodeStateMachine->HandleDecodeErrors(r); - - // Check whether decoding the last frame required us to read data - // that wasn't available at the start of the frame. That means - // we should probably start buffering. - if (decoder->mDecoderPosition > initialDownloadPosition) { - mDecodeStateMachine->mBufferExhausted = PR_TRUE; - } - - // If PlayFrame is waiting, wake it up so we can run the - // decoder loop and move frames from the oggplay queue to our - // queue. Also needed to wake up the decoder loop that waits - // for a frame to be ready to display. - mon.NotifyAll(); - } - } - - mDecodeStateMachine->mDecodingCompleted = PR_TRUE; - return NS_OK; - } -}; - -nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder) : - mDecoder(aDecoder), - mPlayer(0), - mPlayStartTime(), - mPauseStartTime(), - mPauseDuration(0), - mPlaying(PR_FALSE), - mCallbackPeriod(1.0), - mVideoTrack(-1), - mFramerate(0.0), - mAspectRatio(1.0), - mAudioRate(0), - mAudioChannels(0), - mAudioTrack(-1), - mBufferingStart(), - mBufferingEndOffset(0), - mLastFrame(0), - mLastFramePosition(-1), - mState(DECODER_STATE_DECODING_METADATA), - mSeekTime(0.0), - mCurrentFrameTime(0.0), - mPlaybackStartTime(0.0), - mVolume(1.0), - mDuration(-1), - mSeekable(PR_TRUE), - mPositionChangeQueued(PR_FALSE), - mDecodingCompleted(PR_FALSE), - mExitStepDecodeThread(PR_FALSE), - mBufferExhausted(PR_FALSE), - mGotDurationFromHeader(PR_FALSE) -{ -} - -nsOggDecodeStateMachine::~nsOggDecodeStateMachine() -{ - while (!mDecodedFrames.IsEmpty()) { - delete mDecodedFrames.Pop(); - } - oggplay_close(mPlayer); -} - -OggPlayErrorCode nsOggDecodeStateMachine::DecodeFrame() -{ - OggPlayErrorCode r = oggplay_step_decoding(mPlayer); - return r; -} - -void nsOggDecodeStateMachine::HandleDecodeErrors(OggPlayErrorCode aErrorCode) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - - if (aErrorCode != E_OGGPLAY_TIMEOUT && - aErrorCode != E_OGGPLAY_OK && - aErrorCode != E_OGGPLAY_USER_INTERRUPT && - aErrorCode != E_OGGPLAY_CONTINUE) { - mState = DECODER_STATE_SHUTDOWN; - nsCOMPtr event = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, DecodeError); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); - } -} - -nsOggDecodeStateMachine::FrameData* nsOggDecodeStateMachine::NextFrame() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - OggPlayCallbackInfo** info = oggplay_buffer_retrieve_next(mPlayer); - if (!info) - return nsnull; - - FrameData* frame = new FrameData(); - if (!frame) { - return nsnull; - } - - frame->mTime = mCallbackPeriod * mLastFrame; - frame->mEndStreamPosition = mDecoder->mDecoderPosition; - mLastFrame += 1; - - if (mLastFramePosition >= 0) { - NS_ASSERTION(frame->mEndStreamPosition >= mLastFramePosition, - "Playback positions must not decrease without an intervening reset"); - TimeStamp base = mPlayStartTime; - if (base.IsNull()) { - // It doesn't really matter what 'base' is, so just use 'now' if - // we haven't started playback. - base = TimeStamp::Now(); - } - mDecoder->mPlaybackStatistics.Start( - base + TimeDuration::FromMilliseconds(NS_round(frame->mTime*1000))); - mDecoder->mPlaybackStatistics.AddBytes(frame->mEndStreamPosition - mLastFramePosition); - mDecoder->mPlaybackStatistics.Stop( - base + TimeDuration::FromMilliseconds(NS_round(mCallbackPeriod*mLastFrame*1000))); - mDecoder->UpdatePlaybackRate(); - } - mLastFramePosition = frame->mEndStreamPosition; - - int num_tracks = oggplay_get_num_tracks(mPlayer); - float audioTime = -1.0; - float videoTime = -1.0; - - if (mVideoTrack != -1 && - num_tracks > mVideoTrack && - oggplay_callback_info_get_type(info[mVideoTrack]) == OGGPLAY_YUV_VIDEO) { - OggPlayDataHeader** headers = oggplay_callback_info_get_headers(info[mVideoTrack]); - if (headers[0]) { - videoTime = ((float)oggplay_callback_info_get_presentation_time(headers[0]))/1000.0; - HandleVideoData(frame, mVideoTrack, headers[0]); - } - } - - // If the audio stream has finished, but there's still video frames to - // be rendered, we need to send blank audio data to the audio hardware, - // so that the audio clock, which maintains the presentation time, keeps - // incrementing. - PRBool needSilence = PR_FALSE; - - if (mAudioTrack != -1 && num_tracks > mAudioTrack) { - OggPlayDataType type = oggplay_callback_info_get_type(info[mAudioTrack]); - needSilence = (type == OGGPLAY_INACTIVE); - if (type == OGGPLAY_FLOATS_AUDIO) { - OggPlayDataHeader** headers = oggplay_callback_info_get_headers(info[mAudioTrack]); - if (headers[0]) { - audioTime = ((float)oggplay_callback_info_get_presentation_time(headers[0]))/1000.0; - int required = oggplay_callback_info_get_required(info[mAudioTrack]); - for (int j = 0; j < required; ++j) { - int size = oggplay_callback_info_get_record_size(headers[j]); - OggPlayAudioData* audio_data = oggplay_callback_info_get_audio_data(headers[j]); - HandleAudioData(frame, audio_data, size); - } - } - } - } - - if (needSilence) { - // Write silence to keep audio clock moving for av sync - size_t count = mAudioChannels * mAudioRate * mCallbackPeriod; - // count must be evenly divisble by number of channels. - count = mAudioChannels * PRInt32(NS_ceil(mAudioRate*mCallbackPeriod)); - float* data = frame->mAudioData.AppendElements(count); - if (data) { - memset(data, 0, sizeof(float)*count); - } - } - - // Pick one stream to act as the reference track to indicate if the - // stream has ended, seeked, etc. - if (videoTime >= 0) { - frame->mState = oggplay_callback_info_get_stream_info(info[mVideoTrack]); - frame->mDecodedFrameTime = videoTime; - } else if (audioTime >= 0) { - frame->mState = oggplay_callback_info_get_stream_info(info[mAudioTrack]); - frame->mDecodedFrameTime = audioTime; - } else { - NS_WARNING("Encountered frame with no audio or video data"); - frame->mState = OGGPLAY_STREAM_UNINITIALISED; - frame->mDecodedFrameTime = 0.0; - } - - oggplay_buffer_release(mPlayer, info); - return frame; -} - -void nsOggDecodeStateMachine::HandleVideoData(FrameData* aFrame, int aTrackNum, OggPlayDataHeader* aVideoHeader) { - if (!aVideoHeader) - return; - - int y_width = 0; - int y_height = 0; - oggplay_get_video_y_size(mPlayer, aTrackNum, &y_width, &y_height); - int uv_width = 0; - int uv_height = 0; - oggplay_get_video_uv_size(mPlayer, aTrackNum, &uv_width, &uv_height); - - if (y_width >= MAX_VIDEO_WIDTH || y_height >= MAX_VIDEO_HEIGHT) { - return; - } - - aFrame->mVideoWidth = y_width; - aFrame->mVideoHeight = y_height; - aFrame->mUVWidth = uv_width; - aFrame->mUVHeight = uv_height; - aFrame->SetVideoHeader(aVideoHeader); -} - -void nsOggDecodeStateMachine::HandleAudioData(FrameData* aFrame, OggPlayAudioData* aAudioData, int aSize) { - // 'aSize' is number of samples. Multiply by number of channels to - // get the actual number of floats being sent. - int size = aSize * mAudioChannels; - - aFrame->mAudioData.AppendElements(reinterpret_cast(aAudioData), size); -} - -void nsOggDecodeStateMachine::PlayFrame() { - // Play a frame of video and/or audio data. - // If we are playing we open the audio stream if needed - // If there are decoded frames in the queue a single frame - // is popped off and played if it is time for that frame - // to display. - // If it is not time yet to display the frame, we either - // continue decoding frames, or wait until it is time for - // the frame to display if the queue is full. - // - // If the decode state is not PLAYING then we just exit - // so we can continue decoding frames. If the queue is - // full we wait for a state change. - nsAutoMonitor mon(mDecoder->GetMonitor()); - - if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { - if (!mPlaying) { - ResumePlayback(); - } - - if (!mDecodedFrames.IsEmpty()) { - FrameData* frame = mDecodedFrames.Peek(); - if (frame->mState == OGGPLAY_STREAM_JUST_SEEKED) { - // After returning from a seek all mTime members of - // FrameData start again from a time position of 0. - // Reset the play start time. - mPlayStartTime = TimeStamp::Now(); - mPauseDuration = TimeDuration(0); - frame->mState = OGGPLAY_STREAM_INITIALISED; - } - - double time; - PRUint32 hasAudio = frame->mAudioData.Length(); - for (;;) { - // Even if the frame has had its audio data written we call - // PlayAudio to ensure that any data we have buffered in the - // nsAudioStream is written to the hardware. - PlayAudio(frame); - double hwtime = mAudioStream && hasAudio ? mAudioStream->GetPosition() : -1.0; - time = hwtime < 0.0 ? - (TimeStamp::Now() - mPlayStartTime - mPauseDuration).ToSeconds() : - hwtime; - // Resynchronize the system clock against the audio clock. - if (hwtime >= 0.0) { - mPlayStartTime = TimeStamp::Now(); - mPlayStartTime -= TimeDuration::FromMilliseconds(hwtime * 1000.0); - mPauseDuration = TimeDuration(0); - } - // Is it time for the next frame? Using an integer here avoids f.p. - // rounding errors that can cause multiple 0ms waits (Bug 495352) - PRInt64 wait = PRInt64((frame->mTime - time)*1000); - if (wait <= 0) - break; - mon.Wait(PR_MillisecondsToInterval(wait)); - if (mState == DECODER_STATE_SHUTDOWN) - return; - } - - mDecodedFrames.Pop(); - QueueDecodedFrames(); - - // Skip frames up to the one we should be showing. - while (!mDecodedFrames.IsEmpty() && time >= mDecodedFrames.Peek()->mTime) { - LOG(PR_LOG_DEBUG, ("%p Skipping frame time %f with audio at time %f", mDecoder, mDecodedFrames.Peek()->mTime, time)); - PlayAudio(frame); - delete frame; - frame = mDecodedFrames.Peek(); - mDecodedFrames.Pop(); - } - if (time < frame->mTime + mCallbackPeriod) { - PlayAudio(frame); - PlayVideo(frame); - mDecoder->mPlaybackPosition = frame->mEndStreamPosition; - UpdatePlaybackPosition(frame->mDecodedFrameTime); - delete frame; - } - else { - PlayAudio(frame); - delete frame; - frame = 0; - } - } - } - else { - if (mPlaying) { - PausePlayback(); - } - - if (mState == DECODER_STATE_DECODING) { - mon.Wait(); - if (mState == DECODER_STATE_SHUTDOWN) { - return; - } - } - } -} - -static void ToARGBHook(const PlanarYCbCrImage::Data& aData, PRUint8* aOutput) -{ - OggPlayYUVChannels yuv; - NS_ASSERTION(aData.mYStride == aData.mYSize.width, - "Stride not supported"); - NS_ASSERTION(aData.mCbCrStride == aData.mCbCrSize.width, - "Stride not supported"); - yuv.ptry = aData.mYChannel; - yuv.ptru = aData.mCbChannel; - yuv.ptrv = aData.mCrChannel; - yuv.uv_width = aData.mCbCrSize.width; - yuv.uv_height = aData.mCbCrSize.height; - yuv.y_width = aData.mYSize.width; - yuv.y_height = aData.mYSize.height; - - OggPlayRGBChannels rgb; - rgb.ptro = aOutput; - rgb.rgb_width = aData.mYSize.width; - rgb.rgb_height = aData.mYSize.height; - - oggplay_yuv2bgra(&yuv, &rgb); -} - -void nsOggDecodeStateMachine::PlayVideo(FrameData* aFrame) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (aFrame && aFrame->mVideoHeader) { - ImageContainer* container = mDecoder->GetImageContainer(); - // Currently our Ogg decoder only knows how to output to PLANAR_YCBCR - // format. - Image::Format format = Image::PLANAR_YCBCR; - nsRefPtr image; - if (container) { - image = container->CreateImage(&format, 1); - } - if (image) { - NS_ASSERTION(image->GetFormat() == Image::PLANAR_YCBCR, - "Wrong format?"); - PlanarYCbCrImage* videoImage = static_cast(image.get()); - - // XXX this is only temporary until we get YUV code in the layer - // system. - videoImage->SetRGBConverter(ToARGBHook); - - OggPlayVideoData* videoData = oggplay_callback_info_get_video_data(aFrame->mVideoHeader); - PlanarYCbCrImage::Data data; - data.mYChannel = videoData->y; - data.mYSize = gfxIntSize(aFrame->mVideoWidth, aFrame->mVideoHeight); - data.mYStride = data.mYSize.width; - data.mCbChannel = videoData->u; - data.mCrChannel = videoData->v; - data.mCbCrSize = gfxIntSize(aFrame->mUVWidth, aFrame->mUVHeight); - data.mCbCrStride = data.mCbCrSize.width; - videoImage->SetData(data); - - mDecoder->SetVideoData(data.mYSize, mAspectRatio, image); - } - - // Don't play the frame's video data more than once. - aFrame->ClearVideoHeader(); - } -} - -void nsOggDecodeStateMachine::PlayAudio(FrameData* aFrame) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (!mAudioStream) - return; - - aFrame->Write(mAudioStream); -} - -void nsOggDecodeStateMachine::OpenAudioStream() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mAudioStream = new nsAudioStream(); - if (!mAudioStream) { - LOG(PR_LOG_ERROR, ("%p Could not create audio stream", mDecoder)); - } - else { - mAudioStream->Init(mAudioChannels, mAudioRate, nsAudioStream::FORMAT_FLOAT32); - mAudioStream->SetVolume(mVolume); - } -} - -void nsOggDecodeStateMachine::CloseAudioStream() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (mAudioStream) { - mAudioStream->Shutdown(); - mAudioStream = nsnull; - } -} - -void nsOggDecodeStateMachine::StartAudio() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (HasAudio()) { - OpenAudioStream(); - } -} - -void nsOggDecodeStateMachine::StopAudio() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (HasAudio()) { - CloseAudioStream(); - } -} - -void nsOggDecodeStateMachine::StartPlayback() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - StartAudio(); - mPlaying = PR_TRUE; - - // If this is the very first play, then set the initial start time - if (mPlayStartTime.IsNull()) { - mPlayStartTime = TimeStamp::Now(); - } - - // If we have been paused previously, then compute duration spent paused - if (!mPauseStartTime.IsNull()) { - mPauseDuration += TimeStamp::Now() - mPauseStartTime; - // Null out mPauseStartTime - mPauseStartTime = TimeStamp(); - } -} - -void nsOggDecodeStateMachine::StopPlayback() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mLastFrame = mDecodedFrames.ResetTimes(mCallbackPeriod); - StopAudio(); - mPlaying = PR_FALSE; - mPauseStartTime = TimeStamp(); - mPauseDuration = 0; - mPlayStartTime = TimeStamp(); -} - -void nsOggDecodeStateMachine::PausePlayback() -{ - if (!mAudioStream) { - StopPlayback(); - return; - } - mAudioStream->Pause(); - mPlaying = PR_FALSE; - mPauseStartTime = TimeStamp::Now(); -} - -void nsOggDecodeStateMachine::ResumePlayback() -{ - if (!mAudioStream) { - StartPlayback(); - return; - } - - mAudioStream->Resume(); - mPlaying = PR_TRUE; - - // Compute duration spent paused - if (!mPauseStartTime.IsNull()) { - mPauseDuration += TimeStamp::Now() - mPauseStartTime; - // Null out mPauseStartTime - mPauseStartTime = TimeStamp(); - } -} - -void nsOggDecodeStateMachine::UpdatePlaybackPosition(float aTime) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mCurrentFrameTime = aTime - mPlaybackStartTime; - if (!mPositionChangeQueued) { - mPositionChangeQueued = PR_TRUE; - nsCOMPtr event = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackPositionChanged); - NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); - } -} - -void nsOggDecodeStateMachine::QueueDecodedFrames() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - FrameData* frame; - while (!mDecodedFrames.IsFull() && (frame = NextFrame())) { - PRUint32 oldFrameCount = mDecodedFrames.GetCount(); - mDecodedFrames.Push(frame); - if (oldFrameCount < 2) { - // Transitioning from 0 to 1 frames or from 1 to 2 frames could - // affect HaveNextFrameData and hence what UpdateReadyStateForData does. - // This could change us from HAVE_CURRENT_DATA to HAVE_FUTURE_DATA - // (or even HAVE_ENOUGH_DATA), so we'd better trigger an - // update to the ready state. - UpdateReadyState(); - } - } -} - -void nsOggDecodeStateMachine::ClearPositionChangeFlag() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mPositionChangeQueued = PR_FALSE; -} - -nsHTMLMediaElement::NextFrameStatus nsOggDecodeStateMachine::GetNextFrameStatus() -{ - nsAutoMonitor mon(mDecoder->GetMonitor()); - if (IsBuffering() || IsSeeking()) { - return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING; - } else if (HaveNextFrameData()) { - return nsHTMLMediaElement::NEXT_FRAME_AVAILABLE; - } - return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE; -} - -void nsOggDecodeStateMachine::SetVolume(float volume) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - if (mAudioStream) { - mAudioStream->SetVolume(volume); - } - - mVolume = volume; -} - -float nsOggDecodeStateMachine::GetCurrentTime() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mCurrentFrameTime; -} - -PRInt64 nsOggDecodeStateMachine::GetDuration() -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - return mDuration; -} - -void nsOggDecodeStateMachine::SetDuration(PRInt64 aDuration) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mDuration = aDuration; -} - -void nsOggDecodeStateMachine::SetSeekable(PRBool aSeekable) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - mSeekable = aSeekable; -} - -void nsOggDecodeStateMachine::Shutdown() -{ - // oggplay_prepare_for_close cannot be undone. Once called, the - // mPlayer object cannot decode any more frames. Once we've entered - // the shutdown state here there's no going back. - nsAutoMonitor mon(mDecoder->GetMonitor()); - - // Change state before issuing shutdown request to threads so those - // threads can start exiting cleanly during the Shutdown call. - LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN", mDecoder)); - mState = DECODER_STATE_SHUTDOWN; - mon.NotifyAll(); - - if (mPlayer) { - // This will unblock the step decode loop in the - // StepDecode thread. The thread can then be safely - // shutdown. - oggplay_prepare_for_close(mPlayer); - } -} - -void nsOggDecodeStateMachine::Decode() -{ - // When asked to decode, switch to decoding only if - // we are currently buffering. - nsAutoMonitor mon(mDecoder->GetMonitor()); - if (mState == DECODER_STATE_BUFFERING) { - LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); - mState = DECODER_STATE_DECODING; - mon.NotifyAll(); - } -} - -void nsOggDecodeStateMachine::Seek(float aTime) -{ - nsAutoMonitor mon(mDecoder->GetMonitor()); - // nsOggDecoder::mPlayState should be SEEKING while we seek, and - // in that case nsOggDecoder shouldn't be calling us. - NS_ASSERTION(mState != DECODER_STATE_SEEKING, - "We shouldn't already be seeking"); - mSeekTime = aTime + mPlaybackStartTime; - float duration = static_cast(mDuration) / 1000.0; - NS_ASSERTION(mSeekTime >= 0 && mSeekTime <= duration, - "Can only seek in range [0,duration]"); - LOG(PR_LOG_DEBUG, ("%p Changed state to SEEKING (to %f)", mDecoder, aTime)); - mState = DECODER_STATE_SEEKING; -} - -class ByteRange { -public: - ByteRange() : mStart(-1), mEnd(-1) {} - ByteRange(PRInt64 aStart, PRInt64 aEnd) : mStart(aStart), mEnd(aEnd) {} - PRInt64 mStart, mEnd; -}; - -static void GetBufferedBytes(nsMediaStream* aStream, nsTArray& aRanges) -{ - PRInt64 startOffset = 0; - while (PR_TRUE) { - PRInt64 endOffset = aStream->GetCachedDataEnd(startOffset); - if (endOffset == startOffset) { - // Uncached at startOffset. - endOffset = aStream->GetNextCachedData(startOffset); - if (endOffset == -1) { - // Uncached at startOffset until endOffset of stream, or we're at - // the end of stream. - break; - } - } else { - // Bytes [startOffset..endOffset] are cached. - PRInt64 cachedLength = endOffset - startOffset; - // Only bother trying to seek inside ranges greater than - // MIN_BOUNDED_SEEK_SIZE, so that the bounded seek is unlikely to - // read outside of the range when finding Ogg page boundaries. - if (cachedLength > MIN_BOUNDED_SEEK_SIZE) { - aRanges.AppendElement(ByteRange(startOffset, endOffset)); - } - } - startOffset = endOffset; - } -} - -nsresult nsOggDecodeStateMachine::Seek(float aTime, nsChannelReader* aReader) -{ - LOG(PR_LOG_DEBUG, ("%p About to seek OggPlay to %fms", mDecoder, aTime)); - nsMediaStream* stream = aReader->Stream(); - nsAutoTArray ranges; - stream->Pin(); - GetBufferedBytes(stream, ranges); - PRInt64 rv = -1; - for (PRUint32 i = 0; rv < 0 && i < ranges.Length(); i++) { - rv = oggplay_seek_to_keyframe(mPlayer, - ogg_int64_t(aTime * 1000), - ranges[i].mStart, - ranges[i].mEnd); - } - stream->Unpin(); - - if (rv < 0) { - // Could not seek in a buffered range, fall back to seeking over the - // entire media. - rv = oggplay_seek_to_keyframe(mPlayer, - ogg_int64_t(aTime * 1000), - 0, - stream->GetLength()); - } - - LOG(PR_LOG_DEBUG, ("%p Finished seeking OggPlay", mDecoder)); - - return (rv < 0) ? NS_ERROR_FAILURE : NS_OK; -} - -PRBool nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor, - float aTime) -{ - // Drop frames before the target time. - float target = aTime - mCallbackPeriod / 2.0; - FrameData* frame = nsnull; - OggPlayErrorCode r; - mLastFrame = 0; - - // Some of the audio data from previous frames actually belongs - // to this frame and later frames. So rescue that data and stuff - // it into the first frame. - float audioTime = 0; - nsTArray audioData; - do { - if (frame) { - audioData.AppendElements(frame->mAudioData); - audioTime += frame->mAudioData.Length() / - (float)mAudioRate / (float)mAudioChannels; - } - do { - aMonitor.Exit(); - r = DecodeFrame(); - aMonitor.Enter(); - } while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT); - - HandleDecodeErrors(r); - - if (mState == DECODER_STATE_SHUTDOWN) - break; - - FrameData* nextFrame = NextFrame(); - if (!nextFrame) - break; - - delete frame; - frame = nextFrame; - } while (frame->mDecodedFrameTime < target); - - if (mState == DECODER_STATE_SHUTDOWN) { - delete frame; - return PR_TRUE; - } - - NS_ASSERTION(frame != nsnull, "No frame after decode!"); - if (frame) { - if (audioTime > frame->mTime) { - // liboggplay gave us more data than expected, we need to prepend - // the extra data to the current frame to keep audio in sync. - audioTime -= frame->mTime; - // numExtraSamples must be evenly divisble by number of channels. - size_t numExtraSamples = mAudioChannels * - PRInt32(NS_ceil(mAudioRate*audioTime)); - float* data = audioData.Elements() + audioData.Length() - numExtraSamples; - float* dst = frame->mAudioData.InsertElementsAt(0, numExtraSamples); - memcpy(dst, data, numExtraSamples * sizeof(float)); - } - - mLastFrame = 0; - frame->mTime = 0; - frame->mState = OGGPLAY_STREAM_JUST_SEEKED; - mDecodedFrames.Push(frame); - UpdatePlaybackPosition(frame->mDecodedFrameTime); - PlayVideo(frame); - } - - return r == E_OGGPLAY_OK; -} - -void nsOggDecodeStateMachine::StopStepDecodeThread(nsAutoMonitor* aMonitor) -{ - PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mDecoder->GetMonitor()); - - if (!mStepDecodeThread) - return; - - if (!mDecodingCompleted) { - // Break the step-decode thread out of the decoding loop. First - // set the exit flag so it will exit the loop. - mExitStepDecodeThread = PR_TRUE; - // Remove liboggplay frame buffer so that the step-decode thread - // can unblock in liboggplay. - delete NextFrame(); - // Now notify to wake it up if it's waiting on the monitor. - aMonitor->NotifyAll(); - } - - aMonitor->Exit(); - mStepDecodeThread->Shutdown(); - aMonitor->Enter(); - mStepDecodeThread = nsnull; -} - -nsresult nsOggDecodeStateMachine::Run() -{ - nsChannelReader* reader = mDecoder->GetReader(); - NS_ENSURE_TRUE(reader, NS_ERROR_NULL_POINTER); - while (PR_TRUE) { - nsAutoMonitor mon(mDecoder->GetMonitor()); - switch(mState) { - case DECODER_STATE_SHUTDOWN: - if (mPlaying) { - StopPlayback(); - } - StopStepDecodeThread(&mon); - NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN, - "How did we escape from the shutdown state???"); - return NS_OK; - - case DECODER_STATE_DECODING_METADATA: - { - mon.Exit(); - LoadOggHeaders(reader); - mon.Enter(); - - OggPlayErrorCode r = E_OGGPLAY_TIMEOUT; - while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT) { - mon.Exit(); - r = DecodeFrame(); - mon.Enter(); - } - - HandleDecodeErrors(r); - - if (mState == DECODER_STATE_SHUTDOWN) - continue; - - mLastFrame = 0; - FrameData* frame = NextFrame(); - if (frame) { - mDecodedFrames.Push(frame); - mDecoder->mPlaybackPosition = frame->mEndStreamPosition; - mPlaybackStartTime = frame->mDecodedFrameTime; - UpdatePlaybackPosition(frame->mDecodedFrameTime); - // Now that we know the start offset, we can tell the channel - // reader the last frame time. - if (mGotDurationFromHeader) { - // Duration was in HTTP header, so the last frame time is - // start frame time + duration. - reader->SetLastFrameTime((PRInt64)(mPlaybackStartTime * 1000) + mDuration); - } - else if (mDuration != -1) { - // Got duration by seeking to end and getting timestamp of last - // page; mDuration holds the timestamp of the end of the last page. - reader->SetLastFrameTime(mDuration); - // Duration needs to be corrected so it's the length of media, not - // the last frame's end time. Note mPlaybackStartTime is - // presentation time, which is the start-time of the frame. - mDuration -= (PRInt64)(mPlaybackStartTime * 1000); - } - PlayVideo(frame); - } - - // Inform the element that we've loaded the Ogg metadata and the - // first frame. - nsCOMPtr metadataLoadedEvent = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, MetadataLoaded); - NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); - - if (mState == DECODER_STATE_DECODING_METADATA) { - if (r == E_OGGPLAY_OK) { - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to COMPLETED", mDecoder)); - mState = DECODER_STATE_COMPLETED; - } else { - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder)); - mState = DECODER_STATE_DECODING; - } - } - } - break; - - case DECODER_STATE_DECODING: - { - // If there is no step decode thread, start it. It may not be running - // due to us having completed and then restarted playback, seeking, - // or if this is the initial play. - if (!mStepDecodeThread) { - nsresult rv = NS_NewThread(getter_AddRefs(mStepDecodeThread)); - if (NS_FAILED(rv)) { - mState = DECODER_STATE_SHUTDOWN; - continue; - } - - mBufferExhausted = PR_FALSE; - mDecodingCompleted = PR_FALSE; - mExitStepDecodeThread = PR_FALSE; - nsCOMPtr event = new nsOggStepDecodeEvent(this, mPlayer); - mStepDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL); - } - - // Get the decoded frames and store them in our queue of decoded frames - QueueDecodedFrames(); - while (mDecodedFrames.IsEmpty() && !mDecodingCompleted && - !mBufferExhausted) { - if (mPlaying) { - PausePlayback(); - } - mon.Wait(); - if (mState != DECODER_STATE_DECODING) - break; - QueueDecodedFrames(); - } - - if (mState != DECODER_STATE_DECODING) - continue; - - if (mDecodingCompleted) { - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING to COMPLETED", mDecoder)); - mState = DECODER_STATE_COMPLETED; - StopStepDecodeThread(&mon); - continue; - } - - // Show at least the first frame if we're not playing - // so we have a poster frame on initial load and after seek. - if (!mPlaying && !mDecodedFrames.IsEmpty()) { - PlayVideo(mDecodedFrames.Peek()); - } - - if (mBufferExhausted && - mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING && - !mDecoder->mReader->Stream()->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && - !mDecoder->mReader->Stream()->IsSuspendedByCache()) { - // There is at most one frame in the queue and there's - // more data to load. Let's buffer to make sure we can play a - // decent amount of video in the future. - if (mPlaying) { - PausePlayback(); - } - - // We need to tell the element that buffering has started. - // We can't just directly send an asynchronous runnable that - // eventually fires the "waiting" event. The problem is that - // there might be pending main-thread events, such as "data - // received" notifications, that mean we're not actually still - // buffering by the time this runnable executes. So instead - // we just trigger UpdateReadyStateForData; when it runs, it - // will check the current state and decide whether to tell - // the element we're buffering or not. - UpdateReadyState(); - - mBufferingStart = TimeStamp::Now(); - PRPackedBool reliable; - double playbackRate = mDecoder->ComputePlaybackRate(&reliable); - mBufferingEndOffset = mDecoder->mDecoderPosition + - BUFFERING_RATE(playbackRate) * BUFFERING_WAIT; - mState = DECODER_STATE_BUFFERING; - if (mPlaying) { - PausePlayback(); - } - LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING to BUFFERING", mDecoder)); - } else { - if (mBufferExhausted) { - // This will wake up the step decode thread and force it to - // call oggplay_step_decoding at least once. This guarantees - // we make progress. - mBufferExhausted = PR_FALSE; - mon.NotifyAll(); - } - PlayFrame(); - } - } - break; - - case DECODER_STATE_SEEKING: - { - // During the seek, don't have a lock on the decoder state, - // otherwise long seek operations can block the main thread. - // The events dispatched to the main thread are SYNC calls. - // These calls are made outside of the decode monitor lock so - // it is safe for the main thread to makes calls that acquire - // the lock since it won't deadlock. We check the state when - // acquiring the lock again in case shutdown has occurred - // during the time when we didn't have the lock. - StopStepDecodeThread(&mon); - if (mState == DECODER_STATE_SHUTDOWN) - continue; - - float seekTime = mSeekTime; - mDecoder->StopProgressUpdates(); - - StopPlayback(); - - // Remove all frames decoded prior to seek from the queue - while (!mDecodedFrames.IsEmpty()) { - delete mDecodedFrames.Pop(); - } - // SeekingStarted will do a UpdateReadyStateForData which will - // inform the element and its users that we have no frames - // to display - - mon.Exit(); - nsCOMPtr startEvent = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStarted); - NS_DispatchToMainThread(startEvent, NS_DISPATCH_SYNC); - - nsresult res = Seek(seekTime, reader); - - // Reactivate all tracks. Liboggplay deactivates tracks when it - // reads to the end of stream, but they must be reactivated in order - // to start reading from them again. - SetTracksActive(); - - mon.Enter(); - mDecoder->StartProgressUpdates(); - mLastFramePosition = mDecoder->mPlaybackPosition; - if (mState == DECODER_STATE_SHUTDOWN) - continue; - - PRBool atEnd = PR_FALSE; - if (NS_SUCCEEDED(res)) { - atEnd = DecodeToFrame(mon, seekTime); - // mSeekTime should not have changed. While we seek, mPlayState - // should always be PLAY_STATE_SEEKING and no-one will call - // nsOggDecoderStateMachine::Seek. - NS_ASSERTION(seekTime == mSeekTime, "No-one should have changed mSeekTime"); - if (mState == DECODER_STATE_SHUTDOWN) { - continue; - } - - if (!atEnd) { - OggPlayErrorCode r; - // Now try to decode another frame to see if we're at the end. - do { - mon.Exit(); - r = DecodeFrame(); - mon.Enter(); - } while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT); - HandleDecodeErrors(r); - if (mState == DECODER_STATE_SHUTDOWN) - continue; - atEnd = r == E_OGGPLAY_OK; - } - QueueDecodedFrames(); - } - - // Change state to DECODING or COMPLETED now. SeekingStopped will - // call nsOggDecodeStateMachine::Seek to reset our state to SEEKING - // if we need to seek again. - nsCOMPtr stopEvent; - if (!atEnd && mDecodedFrames.GetCount() > 1) { - LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to DECODING", - mDecoder, seekTime)); - stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped); - mState = DECODER_STATE_DECODING; - } else { - LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to COMPLETED", - mDecoder, seekTime)); - stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd); - mState = DECODER_STATE_COMPLETED; - } - mon.NotifyAll(); - - mon.Exit(); - NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC); - mon.Enter(); - } - break; - - case DECODER_STATE_BUFFERING: - { - TimeStamp now = TimeStamp::Now(); - if (now - mBufferingStart < TimeDuration::FromSeconds(BUFFERING_WAIT) && - mDecoder->mReader->Stream()->GetCachedDataEnd(mDecoder->mDecoderPosition) < mBufferingEndOffset && - !mDecoder->mReader->Stream()->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && - !mDecoder->mReader->Stream()->IsSuspendedByCache()) { - LOG(PR_LOG_DEBUG, - ("%p In buffering: buffering data until %d bytes available or %f seconds", mDecoder, - PRUint32(mBufferingEndOffset - mDecoder->mReader->Stream()->GetCachedDataEnd(mDecoder->mDecoderPosition)), - BUFFERING_WAIT - (now - mBufferingStart).ToSeconds())); - mon.Wait(PR_MillisecondsToInterval(1000)); - if (mState == DECODER_STATE_SHUTDOWN) - continue; - } else { - LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); - mState = DECODER_STATE_DECODING; - } - - if (mState != DECODER_STATE_BUFFERING) { - mBufferExhausted = PR_FALSE; - // Notify to allow blocked decoder thread to continue - mon.NotifyAll(); - UpdateReadyState(); - if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { - if (!mPlaying) { - ResumePlayback(); - } - } - } - - break; - } - - case DECODER_STATE_COMPLETED: - { - // Get all the remaining decoded frames in the liboggplay buffer and - // place them in the frame queue. - QueueDecodedFrames(); - - // Play the remaining frames in the frame queue - while (mState == DECODER_STATE_COMPLETED && - !mDecodedFrames.IsEmpty()) { - PlayFrame(); - if (mState == DECODER_STATE_COMPLETED) { - // Wait for the time of one frame so we don't tight loop - // and we need to release the monitor so timeupdate and - // invalidate's on the main thread can occur. - mon.Wait(PR_MillisecondsToInterval(PRInt64(mCallbackPeriod*1000))); - QueueDecodedFrames(); - } - } - - if (mState != DECODER_STATE_COMPLETED) - continue; - - if (mAudioStream) { - mon.Exit(); - LOG(PR_LOG_DEBUG, ("%p Begin nsAudioStream::Drain", mDecoder)); - mAudioStream->Drain(); - LOG(PR_LOG_DEBUG, ("%p End nsAudioStream::Drain", mDecoder)); - mon.Enter(); - - // After the drain call the audio stream is unusable. Close it so that - // next time audio is used a new stream is created. The StopPlayback - // call also resets the playing flag so audio is restarted correctly. - StopPlayback(); - - if (mState != DECODER_STATE_COMPLETED) - continue; - } - - if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { - // We were playing, we need to move the current time to the end of - // media, and send an 'ended' event. - mCurrentFrameTime += mCallbackPeriod; - if (mDuration >= 0) { - mCurrentFrameTime = PR_MAX(mCurrentFrameTime, mDuration / 1000.0); - } - - mon.Exit(); - nsCOMPtr event = - NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded); - NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); - mon.Enter(); - } - - while (mState == DECODER_STATE_COMPLETED) { - mon.Wait(); - } - } - break; - } - } - - return NS_OK; -} - -// Initialize our OggPlay struct with the specified limit on video size. -static OggPlay* -OggPlayOpen(OggPlayReader* reader, - int max_frame_pixels) -{ - OggPlay *me = NULL; - int r; - - if ((me = oggplay_new_with_reader(reader)) == NULL) { - return NULL; - } - - r = oggplay_set_max_video_frame_pixels(me, max_frame_pixels); - if (r != E_OGGPLAY_OK) { - oggplay_close(me); - return NULL; - } - - do { - r = oggplay_initialise(me, 0); - } while (r == E_OGGPLAY_TIMEOUT); - - if (r != E_OGGPLAY_OK) { - oggplay_close(me); - return NULL; - } - - return me; -} - -void nsOggDecodeStateMachine::LoadOggHeaders(nsChannelReader* aReader) -{ - LOG(PR_LOG_DEBUG, ("%p Loading Ogg Headers", mDecoder)); - mPlayer = OggPlayOpen(aReader, MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT); - if (!mPlayer) { - nsAutoMonitor mon(mDecoder->GetMonitor()); - mState = DECODER_STATE_SHUTDOWN; - HandleDecodeErrors(E_OGGPLAY_UNINITIALISED); - return; - } - LOG(PR_LOG_DEBUG, ("%p There are %d tracks", mDecoder, oggplay_get_num_tracks(mPlayer))); - - for (int i = 0; i < oggplay_get_num_tracks(mPlayer); ++i) { - LOG(PR_LOG_DEBUG, ("%p Tracks %d: %s", mDecoder, i, oggplay_get_track_typename(mPlayer, i))); - if (mVideoTrack == -1 && oggplay_get_track_type(mPlayer, i) == OGGZ_CONTENT_THEORA) { - oggplay_set_callback_num_frames(mPlayer, i, 1); - mVideoTrack = i; - - int fpsd, fpsn; - oggplay_get_video_fps(mPlayer, i, &fpsd, &fpsn); - mFramerate = fpsd == 0 ? 0.0 : float(fpsn)/float(fpsd); - mCallbackPeriod = 1.0 / mFramerate; - LOG(PR_LOG_DEBUG, ("%p Frame rate: %f", mDecoder, mFramerate)); - - int aspectd, aspectn; - // this can return E_OGGPLAY_UNINITIALISED if the video has - // no aspect ratio data. We assume 1.0 in that case. - OggPlayErrorCode r = - oggplay_get_video_aspect_ratio(mPlayer, i, &aspectd, &aspectn); - mAspectRatio = r == E_OGGPLAY_OK && aspectd > 0 ? - float(aspectn)/float(aspectd) : 1.0; - - int y_width; - int y_height; - oggplay_get_video_y_size(mPlayer, i, &y_width, &y_height); - mDecoder->SetVideoData(gfxIntSize(y_width, y_height), mAspectRatio, - nsnull); - } - else if (mAudioTrack == -1 && oggplay_get_track_type(mPlayer, i) == OGGZ_CONTENT_VORBIS) { - mAudioTrack = i; - oggplay_set_offset(mPlayer, i, OGGPLAY_AUDIO_OFFSET); - oggplay_get_audio_samplerate(mPlayer, i, &mAudioRate); - oggplay_get_audio_channels(mPlayer, i, &mAudioChannels); - LOG(PR_LOG_DEBUG, ("%p samplerate: %d, channels: %d", mDecoder, mAudioRate, mAudioChannels)); - } - } - - if (mVideoTrack == -1 && mAudioTrack == -1) { - nsAutoMonitor mon(mDecoder->GetMonitor()); - HandleDecodeErrors(E_OGGPLAY_UNINITIALISED); - return; - } - - SetTracksActive(); - - if (mVideoTrack == -1) { - oggplay_set_callback_num_frames(mPlayer, mAudioTrack, OGGPLAY_FRAMES_PER_CALLBACK); - mCallbackPeriod = 1.0 / (float(mAudioRate) / OGGPLAY_FRAMES_PER_CALLBACK); - } - LOG(PR_LOG_DEBUG, ("%p Callback Period: %f", mDecoder, mCallbackPeriod)); - - oggplay_use_buffer(mPlayer, OGGPLAY_BUFFER_SIZE); - - // Get the duration from the Ogg file. We only do this if the - // content length of the resource is known as we need to seek - // to the end of the file to get the last time field. We also - // only do this if the resource is seekable and if we haven't - // already obtained the duration via an HTTP header. - { - nsAutoMonitor mon(mDecoder->GetMonitor()); - mGotDurationFromHeader = (mDuration != -1); - if (mState != DECODER_STATE_SHUTDOWN && - aReader->Stream()->GetLength() >= 0 && - mSeekable && - mDuration == -1) { - mDecoder->StopProgressUpdates(); - // Don't hold the monitor during the duration - // call as it can issue seek requests - // and blocks until these are completed. - mon.Exit(); - PRInt64 d = oggplay_get_duration(mPlayer); - oggplay_seek(mPlayer, 0); - mon.Enter(); - mDuration = d; - mDecoder->StartProgressUpdates(); - mDecoder->UpdatePlaybackRate(); - } - if (mState == DECODER_STATE_SHUTDOWN) - return; - } -} - -void nsOggDecodeStateMachine::SetTracksActive() -{ - if (mVideoTrack != -1 && - oggplay_set_track_active(mPlayer, mVideoTrack) < 0) { - LOG(PR_LOG_ERROR, ("%p Could not set track %d active", mDecoder, mVideoTrack)); - } - - if (mAudioTrack != -1 && - oggplay_set_track_active(mPlayer, mAudioTrack) < 0) { - LOG(PR_LOG_ERROR, ("%p Could not set track %d active", mDecoder, mAudioTrack)); - } -} - NS_IMPL_THREADSAFE_ISUPPORTS1(nsOggDecoder, nsIObserver) void nsOggDecoder::Pause() { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (mPlayState == PLAY_STATE_SEEKING || mPlayState == PLAY_STATE_ENDED) { mNextState = PLAY_STATE_PAUSED; return; @@ -1985,9 +72,8 @@ void nsOggDecoder::Pause() void nsOggDecoder::SetVolume(float volume) { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); mInitialVolume = volume; - if (mDecodeStateMachine) { mDecodeStateMachine->SetVolume(volume); } @@ -1995,15 +81,15 @@ void nsOggDecoder::SetVolume(float volume) float nsOggDecoder::GetDuration() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mDuration >= 0) { return static_cast(mDuration) / 1000.0; } - return std::numeric_limits::quiet_NaN(); } nsOggDecoder::nsOggDecoder() : - nsMediaDecoder(), + mMonitor("media.decoder"), mDecoderPosition(0), mPlaybackPosition(0), mCurrentTime(0.0), @@ -2011,15 +97,13 @@ nsOggDecoder::nsOggDecoder() : mRequestedSeekTime(-1.0), mDuration(-1), mSeekable(PR_TRUE), - mReader(nsnull), - mMonitor(nsnull), mPlayState(PLAY_STATE_PAUSED), mNextState(PLAY_STATE_PAUSED), mResourceLoaded(PR_FALSE), mIgnoreProgressData(PR_FALSE) { MOZ_COUNT_CTOR(nsOggDecoder); - + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); #ifdef PR_LOGGING if (!gOggDecoderLog) { gOggDecoderLog = PR_NewLogModule("nsOggDecoder"); @@ -2029,42 +113,32 @@ nsOggDecoder::nsOggDecoder() : PRBool nsOggDecoder::Init(nsHTMLMediaElement* aElement) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (!nsMediaDecoder::Init(aElement)) return PR_FALSE; - mMonitor = nsAutoMonitor::NewMonitor("media.decoder"); - if (!mMonitor) - return PR_FALSE; - nsContentUtils::RegisterShutdownObserver(this); - - mReader = new nsChannelReader(); - NS_ENSURE_TRUE(mReader, PR_FALSE); - mImageContainer = aElement->GetImageContainer(); - return PR_TRUE; } void nsOggDecoder::Stop() { - NS_ASSERTION(NS_IsMainThread(), "Should be called on main thread"); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread"); // The decode thread must die before the state machine can die. // The state machine must die before the reader. // The state machine must die before the decoder. - if (mDecodeThread) - mDecodeThread->Shutdown(); + if (mStateMachineThread) + mStateMachineThread->Shutdown(); - mDecodeThread = nsnull; + mStateMachineThread = nsnull; mDecodeStateMachine = nsnull; - mReader = nsnull; } void nsOggDecoder::Shutdown() { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::Shutdown called on non-main thread"); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2080,14 +154,14 @@ void nsOggDecoder::Shutdown() // Force any outstanding seek and byterange requests to complete // to prevent shutdown from deadlocking. - if (mReader) { - mReader->Stream()->Close(); + if (mStream) { + mStream->Close(); } ChangeState(PLAY_STATE_SHUTDOWN); nsMediaDecoder::Shutdown(); - // We can't destroy mDecodeStateMachine until mDecodeThread is shut down. + // We can't destroy mDecodeStateMachine until mStateMachineThread is shut down. // It's unsafe to Shutdown() the decode thread here, as // nsIThread::Shutdown() may run events, such as JS event handlers, // and we could be running at an unsafe time such as during element @@ -2103,13 +177,14 @@ void nsOggDecoder::Shutdown() nsOggDecoder::~nsOggDecoder() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); MOZ_COUNT_DTOR(nsOggDecoder); - nsAutoMonitor::DestroyMonitor(mMonitor); } nsresult nsOggDecoder::Load(nsMediaStream* aStream, nsIStreamListener** aStreamListener) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (aStreamListener) { *aStreamListener = nsnull; } @@ -2118,7 +193,7 @@ nsresult nsOggDecoder::Load(nsMediaStream* aStream, // Hold the lock while we do this to set proper lock ordering // expectations for dynamic deadlock detectors: decoder lock(s) // should be grabbed before the cache lock - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); nsresult rv = aStream->Open(aStreamListener); if (NS_FAILED(rv)) { @@ -2126,27 +201,31 @@ nsresult nsOggDecoder::Load(nsMediaStream* aStream, return rv; } - mReader->Init(aStream); + mStream = aStream; } - nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread)); + nsresult rv = NS_NewThread(getter_AddRefs(mStateMachineThread)); NS_ENSURE_SUCCESS(rv, rv); - mDecodeStateMachine = new nsOggDecodeStateMachine(this); + mDecodeStateMachine = new nsOggPlayStateMachine(this); + if (NS_FAILED(mDecodeStateMachine->Init())) { + return NS_ERROR_FAILURE; + } { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDecodeStateMachine->SetSeekable(mSeekable); mDecodeStateMachine->SetDuration(mDuration); } ChangeState(PLAY_STATE_LOADING); - return mDecodeThread->Dispatch(mDecodeStateMachine, NS_DISPATCH_NORMAL); + return mStateMachineThread->Dispatch(mDecodeStateMachine, NS_DISPATCH_NORMAL); } nsresult nsOggDecoder::Play() { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (mPlayState == PLAY_STATE_SEEKING) { mNextState = PLAY_STATE_PLAYING; return NS_OK; @@ -2161,7 +240,8 @@ nsresult nsOggDecoder::Play() nsresult nsOggDecoder::Seek(float aTime) { - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (aTime < 0.0) return NS_ERROR_FAILURE; @@ -2185,28 +265,31 @@ nsresult nsOggDecoder::Seek(float aTime) nsresult nsOggDecoder::PlaybackRateChanged() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); return NS_ERROR_NOT_IMPLEMENTED; } float nsOggDecoder::GetCurrentTime() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); return mCurrentTime; } nsMediaStream* nsOggDecoder::GetCurrentStream() { - return mReader ? mReader->Stream() : nsnull; + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + return mStream; } already_AddRefed nsOggDecoder::GetCurrentPrincipal() { - if (!mReader) - return nsnull; - return mReader->Stream()->GetCurrentPrincipal(); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + return mStream ? mStream->GetCurrentPrincipal() : nsnull; } void nsOggDecoder::MetadataLoaded() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2214,7 +297,7 @@ void nsOggDecoder::MetadataLoaded() // to fulfill a seek, otherwise we'll get multiple metadataloaded events. PRBool notifyElement = PR_TRUE; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDuration = mDecodeStateMachine ? mDecodeStateMachine->GetDuration() : -1; notifyElement = mNextState != PLAY_STATE_SEEKING; } @@ -2228,32 +311,29 @@ void nsOggDecoder::MetadataLoaded() if (!mResourceLoaded) { StartProgress(); - } - else if (mElement) - { + } else if (mElement) { // Resource was loaded during metadata loading, when progress // events are being ignored. Fire the final progress event. mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); } - + // Only inform the element of FirstFrameLoaded if not doing a load() in order // to fulfill a seek, otherwise we'll get multiple loadedfirstframe events. - PRBool resourceIsLoaded = !mResourceLoaded && mReader && - mReader->Stream()->IsDataCachedToEndOfStream(mDecoderPosition); + PRBool resourceIsLoaded = !mResourceLoaded && mStream && + mStream->IsDataCachedToEndOfStream(mDecoderPosition); if (mElement && notifyElement) { mElement->FirstFrameLoaded(resourceIsLoaded); } // The element can run javascript via events - // before reaching here, so only change the + // before reaching here, so only change the // state if we're still set to the original // loading state. - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); if (mPlayState == PLAY_STATE_LOADING) { if (mRequestedSeekTime >= 0.0) { ChangeState(PLAY_STATE_SEEKING); - } - else { + } else { ChangeState(mNextState); } } @@ -2265,6 +345,8 @@ void nsOggDecoder::MetadataLoaded() void nsOggDecoder::ResourceLoaded() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + // Don't handle ResourceLoaded if we are shutting down, or if // we need to ignore progress data due to seeking (in the case // that the seek results in reaching end of file, we get a bogus call @@ -2275,7 +357,7 @@ void nsOggDecoder::ResourceLoaded() { // If we are seeking or loading then the resource loaded notification we get // should be ignored, since it represents the end of the seek request. - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); if (mIgnoreProgressData || mResourceLoaded || mPlayState == PLAY_STATE_LOADING) return; @@ -2294,6 +376,7 @@ void nsOggDecoder::ResourceLoaded() void nsOggDecoder::NetworkError() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2305,6 +388,7 @@ void nsOggDecoder::NetworkError() void nsOggDecoder::DecodeError() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2342,6 +426,7 @@ NS_IMETHODIMP nsOggDecoder::Observe(nsISupports *aSubjet, const char *aTopic, const PRUnichar *someData) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { Shutdown(); } @@ -2352,15 +437,16 @@ NS_IMETHODIMP nsOggDecoder::Observe(nsISupports *aSubjet, nsMediaDecoder::Statistics nsOggDecoder::GetStatistics() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); Statistics result; - nsAutoMonitor mon(mMonitor); - if (mReader) { + MonitorAutoEnter mon(mMonitor); + if (mStream) { result.mDownloadRate = - mReader->Stream()->GetDownloadRate(&result.mDownloadRateReliable); + mStream->GetDownloadRate(&result.mDownloadRateReliable); result.mDownloadPosition = - mReader->Stream()->GetCachedDataEnd(mDecoderPosition); - result.mTotalBytes = mReader->Stream()->GetLength(); + mStream->GetCachedDataEnd(mDecoderPosition); + result.mTotalBytes = mStream->GetLength(); result.mPlaybackRate = ComputePlaybackRate(&result.mPlaybackRateReliable); result.mDecoderPosition = mDecoderPosition; result.mPlaybackPosition = mPlaybackPosition; @@ -2380,7 +466,11 @@ nsOggDecoder::GetStatistics() double nsOggDecoder::ComputePlaybackRate(PRPackedBool* aReliable) { - PRInt64 length = mReader ? mReader->Stream()->GetLength() : -1; + GetMonitor().AssertCurrentThreadIn(); + NS_ASSERTION(NS_IsMainThread() || IsThread(mStateMachineThread), + "Should be on main or state machine thread."); + + PRInt64 length = mStream ? mStream->GetLength() : -1; if (mDuration >= 0 && length >= 0) { *aReliable = PR_TRUE; return double(length)*1000.0/mDuration; @@ -2390,28 +480,30 @@ double nsOggDecoder::ComputePlaybackRate(PRPackedBool* aReliable) void nsOggDecoder::UpdatePlaybackRate() { - if (!mReader) + NS_ASSERTION(NS_IsMainThread() || IsThread(mStateMachineThread), + "Should be on main or state machine thread."); + GetMonitor().AssertCurrentThreadIn(); + if (!mStream) return; PRPackedBool reliable; PRUint32 rate = PRUint32(ComputePlaybackRate(&reliable)); if (reliable) { // Avoid passing a zero rate - rate = PR_MAX(rate, 1); + rate = NS_MAX(rate, 1u); } else { // Set a minimum rate of 10,000 bytes per second ... sometimes we just // don't have good data - rate = PR_MAX(rate, 10000); + rate = NS_MAX(rate, 10000u); } - mReader->Stream()->SetPlaybackRate(rate); + mStream->SetPlaybackRate(rate); } void nsOggDecoder::NotifySuspendedStatusChanged() { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::NotifyDownloadSuspended called on non-main thread"); - if (!mReader) + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (!mStream) return; - if (mReader->Stream()->IsSuspendedByCache() && mElement) { + if (mStream->IsSuspendedByCache() && mElement) { // if this is an autoplay element, we need to kick off its autoplaying // now so we consume data and hopefully free up cache space mElement->NotifyAutoplayDataReady(); @@ -2420,19 +512,20 @@ void nsOggDecoder::NotifySuspendedStatusChanged() void nsOggDecoder::NotifyBytesDownloaded() { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::NotifyBytesDownloaded called on non-main thread"); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); UpdateReadyStateForData(); Progress(PR_FALSE); } void nsOggDecoder::NotifyDownloadEnded(nsresult aStatus) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (aStatus == NS_BINDING_ABORTED) return; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); UpdatePlaybackRate(); } @@ -2446,7 +539,9 @@ void nsOggDecoder::NotifyDownloadEnded(nsresult aStatus) void nsOggDecoder::NotifyBytesConsumed(PRInt64 aBytes) { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mDecodeStateMachine->OnStateMachineThread() || mDecodeStateMachine->OnDecodeThread(), + "Should be on play state machine or decode thread."); if (!mIgnoreProgressData) { mDecoderPosition += aBytes; } @@ -2492,11 +587,13 @@ void nsOggDecoder::UpdateReadyStateForData() void nsOggDecoder::SeekingStopped() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mShuttingDown) return; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); // An additional seek was requested while the current seek was // in operation. @@ -2516,12 +613,14 @@ void nsOggDecoder::SeekingStopped() // media. void nsOggDecoder::SeekingStoppedAtEnd() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mShuttingDown) return; PRBool fireEnded = PR_FALSE; { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); // An additional seek was requested while the current seek was // in operation. @@ -2544,6 +643,7 @@ void nsOggDecoder::SeekingStoppedAtEnd() void nsOggDecoder::SeekingStarted() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2555,16 +655,15 @@ void nsOggDecoder::SeekingStarted() void nsOggDecoder::ChangeState(PlayState aState) { - NS_ASSERTION(NS_IsMainThread(), - "nsOggDecoder::ChangeState called on non-main thread"); - nsAutoMonitor mon(mMonitor); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); if (mNextState == aState) { mNextState = PLAY_STATE_PAUSED; } if (mPlayState == PLAY_STATE_SHUTDOWN) { - mon.NotifyAll(); + mMonitor.NotifyAll(); return; } @@ -2593,11 +692,12 @@ void nsOggDecoder::ChangeState(PlayState aState) /* No action needed */ break; } - mon.NotifyAll(); + mMonitor.NotifyAll(); } void nsOggDecoder::PlaybackPositionChanged() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (mShuttingDown) return; @@ -2606,7 +706,7 @@ void nsOggDecoder::PlaybackPositionChanged() // Control the scope of the monitor so it is not // held while the timeupdate and the invalidate is run. { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); if (mDecodeStateMachine) { mCurrentTime = mDecodeStateMachine->GetCurrentTime(); @@ -2625,11 +725,24 @@ void nsOggDecoder::PlaybackPositionChanged() } } +void nsOggDecoder::DurationChanged() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mMonitor); + PRInt64 oldDuration = mDuration; + mDuration = mDecodeStateMachine ? mDecodeStateMachine->GetDuration() : -1; + if (mElement && oldDuration != mDuration) { + LOG(PR_LOG_DEBUG, ("%p duration changed to %lldms", this, mDuration)); + mElement->DispatchSimpleEvent(NS_LITERAL_STRING("durationchange")); + } +} + void nsOggDecoder::SetDuration(PRInt64 aDuration) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); mDuration = aDuration; if (mDecodeStateMachine) { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDecodeStateMachine->SetDuration(mDuration); UpdatePlaybackRate(); } @@ -2637,53 +750,59 @@ void nsOggDecoder::SetDuration(PRInt64 aDuration) void nsOggDecoder::SetSeekable(PRBool aSeekable) { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); mSeekable = aSeekable; if (mDecodeStateMachine) { - nsAutoMonitor mon(mMonitor); + MonitorAutoEnter mon(mMonitor); mDecodeStateMachine->SetSeekable(aSeekable); } } PRBool nsOggDecoder::GetSeekable() { + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); return mSeekable; } void nsOggDecoder::Suspend() { - if (mReader) { - mReader->Stream()->Suspend(PR_TRUE); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mStream) { + mStream->Suspend(PR_TRUE); } } void nsOggDecoder::Resume() { - if (mReader) { - mReader->Stream()->Resume(); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mStream) { + mStream->Resume(); } } void nsOggDecoder::StopProgressUpdates() { + NS_ASSERTION(IsThread(mStateMachineThread), "Should be on state machine thread."); mIgnoreProgressData = PR_TRUE; - if (mReader) { - mReader->Stream()->SetReadMode(nsMediaCacheStream::MODE_METADATA); + if (mStream) { + mStream->SetReadMode(nsMediaCacheStream::MODE_METADATA); } } void nsOggDecoder::StartProgressUpdates() { + NS_ASSERTION(IsThread(mStateMachineThread), "Should be on state machine thread."); mIgnoreProgressData = PR_FALSE; - if (mReader) { - mReader->Stream()->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK); - mDecoderPosition = mPlaybackPosition = mReader->Stream()->Tell(); + if (mStream) { + mStream->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK); + mDecoderPosition = mPlaybackPosition = mStream->Tell(); } } void nsOggDecoder::MoveLoadsToBackground() { - if (mReader) { - mReader->Stream()->MoveLoadsToBackground(); + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + if (mStream) { + mStream->MoveLoadsToBackground(); } } - diff --git a/content/media/ogg/nsOggDecoder.h b/content/media/ogg/nsOggDecoder.h index 3eaba0836103..4f5c74b05b30 100644 --- a/content/media/ogg/nsOggDecoder.h +++ b/content/media/ogg/nsOggDecoder.h @@ -21,6 +21,7 @@ * * Contributor(s): * Chris Double + * Chris Pearce * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,55 +37,67 @@ * * ***** END LICENSE BLOCK ***** */ /* -Each video element has two threads. The first thread, called the Decode thread, -owns the resources for downloading and reading the video file. It goes through the -file, prcessing any decoded theora and vorbis data. It handles the sending of the -audio data to the sound device and the presentation of the video data at the correct -frame rate. +Each video element has three threads. -The second thread is the step decode thread. It uses OggPlay to decode the video and -audio data. It indirectly uses an nsMediaStream to do the file reading and seeking via -Oggplay. + 1) The state machine thread owns the resources for downloading and reading + the media file. It controls the lifetime of the other two threads + and renders the video data at the correct time during playback. -All file reads and seeks must occur on these two threads. Synchronisation is done via -liboggplay internal mutexes to ensure that access to the liboggplay structures is -done correctly in the presence of the threads. + 2) The Audio thread writes the decoded audio data to the audio + hardware. This is done in a seperate thread to ensure that the + audio hardware gets a constant stream of data without + interruption due to decoding or diplay. At some point + libsydneyaudio will be refactored to have a callback interface + where it asks for data and an extra thread will no longer be + needed. -The step decode thread is created and destroyed in the decode thread. When decoding -needs to be done it is created and event dispatched to it to start the decode loop. -This event exits when decoding is completed or no longer required (during seeking -or shutdown). + 3) The decode thread. This thread reads from the media stream and decodes + the Theora and Vorbis data. It places the decoded data in a queue + for the other threads to pull from. + +All file reads and seeks must occur on either the state machine thread +or the decode thread. Synchronisation is done via a monitor owned by +nsOggDecoder. + +The decode thread and the audio thread are created and destroyed in the +state machine thread. When playback needs to occur they are created and +events dispatched to them to start them. These events exit when +decoding is completed or no longer required (during seeking or +shutdown). -When the decode thread is created an event is dispatched to it. The event -runs for the lifetime of the playback of the resource. The decode thread -synchronises with the main thread via a single monitor held by the -nsOggDecoder object. +All threads have one event that is dispatched to it and that event +runs for the lifetime of the playback of the resource. State shared +between them is synchronised with the main thread via a monitor +held by the nsOggDecoder object. The decode thread also has its own +monitor to ensure that its internal state is independent of the other +threads, and to ensure that it's not hogging the monitor while decoding. -The event contains a Run method which consists of an infinite loop -that checks the state that the state machine is in and processes -operations on that state. +The events consist of a Run method which is an infinite loop that +perform the threads operation and checks the state that the state +machine is in and processes operations on that state. -The nsOggDecodeStateMachine class is the event that gets dispatched to -the decode thread. It has the following states: +The nsOggPlayStateMachine class is the event that gets dispatched to +the state machine thread. It has the following states: DECODING_METADATA The Ogg headers are being loaded, and things like framerate, etc are being determined, and the first frame of audio/video data is being decoded. DECODING - Video/Audio frames are being decoded. + The decode and audio threads are started and video frames displayed at + the required time. SEEKING A seek operation is in progress. BUFFERING Decoding is paused while data is buffered for smooth playback. COMPLETED - The resource has completed decoding. + The resource has completed decoding, but not finished playback. SHUTDOWN The decoder object is about to be destroyed. The following result in state transitions. Shutdown() - Clean up any resources the nsOggDecodeStateMachine owns. + Clean up any resources the nsOggPlayStateMachine owns. Decode() Start decoding video frames. Buffer @@ -163,7 +176,7 @@ player SHUTDOWN decoder SHUTDOWN The general sequence of events with these objects is: 1) The video element calls Load on nsMediaDecoder. This creates the - decode thread and starts the channel for downloading the file. It + state machine thread and starts the channel for downloading the file. It instantiates and starts the Decode state machine. The high level LOADING state is entered, which results in the decode state machine to start decoding metadata. These are the headers that give the @@ -188,66 +201,52 @@ The general sequence of events with these objects is: video, if the correct frame time comes around and the decoder play state is PLAYING. -a/v synchronisation is done by a combination of liboggplay and the -Decoder state machine. liboggplay ensures that a decoded frame of data -has both the audio samples and the YUV data for that period of time. +a/v synchronisation is handled by the stete machine thread. It examines the +audio playback time and compares this to the next frame in the queue +of frames. If it is time to play the video frame it is then displayed. -When a frame is decoded by the decode state machine it converts the -YUV encoded video to RGB and copies the sound data to an internal -FrameData object. This is stored in a queue of available decoded frames. -Included in the FrameData object is the time that that frame should -be displayed. +Frame skipping is done in the following ways: -The display state machine keeps track of the time since the last frame it -played. After decoding a frame it checks if it is time to display the next -item in the decoded frame queue. If so, it pops the item off the queue -and displays it. + 1) The state machine thread will skip all frames in the video queue whose + display time is less than the current audio time. This ensures + the correct frame for the current time is always displayed. -Ideally a/v sync would take into account the actual audio clock of the -audio hardware for the sync rather than using the system clock. -Unfortunately getting valid time data out of the audio hardware has proven -to be unreliable across platforms (and even distributions in Linux) depending -on audio hardware, audio backend etc. The current approach works fine in practice -and is a compromise until this issue can be sorted. The plan is to eventually -move to synchronising using the audio hardware. + 2) The decode thread will stop decoding interframes and read to the + next keyframe if it determines that decoding the remaining + interframes will cause playback issues. It detects this by: + a) If the amount of audio data in the audio queue drops + below a threshold whereby audio may start to skip. + b) If the video queue drops below a threshold where it + will be decoding video data that won't be displayed due + to the decode thread dropping the frame immediately. -To prevent audio skipping and framerate dropping it is very important to -make sure no blocking occurs during the decoding process and minimise -expensive time operations at the time a frame is to be displayed. This is -managed by immediately converting video data to RGB on decode (an expensive -operation to do at frame display time) and checking if the sound device will -not block before writing sound data to it. +YCbCr conversion is done on the decode thread when it is time to display +the video frame. This means frames that are skipped will not have the +YCbCr conversion done, improving playback. -Shutdown needs to ensure that the event posted to the decode -thread is completed. The decode thread can potentially block internally -inside liboggplay when reading, seeking, or its internal buffers containing -decoded data are full. When blocked in this manner a call from the main thread -to Shutdown() will hang. +The decode thread pushes decoded audio and videos frames into two +separate queues - one for audio and one for video. These are kept +separate to make it easy to constantly feed audio data to the sound +hardware while allowing frame skipping of video data. These queues are +threadsafe, and neither the decode, audio, or state machine thread should +be able to monopolize them, and cause starvation of the other threads. -This is fixed with a protocol to ensure that the decode event cleanly -completes. The nsMediaStream that the nsChannelReader uses has a -Cancel() method. Calling this before Shutdown() will close any -internal streams or listeners resulting in blocked i/o completing with -an error, and all future i/o on the stream having an error. +Both queues are bounded by a maximum size. When this size is reached +the decode thread will no longer decode video or audio depending on the +queue that has reached the threshold. -This causes the decode thread to exit and Shutdown() can occur. +During playback the audio thread will be idle (via a Wait() on the +monitor) if the audio queue is empty. Otherwise it constantly pops an +item off the queue and plays it with a blocking write to the audio +hardware (via nsAudioStream and libsydneyaudio). -If the decode thread is seeking then the same Cancel() operation -causes an error to be returned from the seek call to liboggplay which -exits out of the seek operation, and stops the seek state running on the -decode thread. - -If the decode thread is blocked due to internal decode buffers being -full, it is unblocked during the shutdown process by calling -oggplay_prepare_for_close. - -In practice the OggPlay internal buffer should never fill as we retrieve and -process the frame immediately on decoding. +The decode thread idles if the video queue is empty or if it is +not yet time to display the next frame. The Shutdown method on nsOggDecoder can spin the event loop as it waits for threads to complete. Spinning the event loop is a bad thing to happen during certain times like destruction of the media element. To work around -this the Shutdown method does nothing by queue an event to the main thread +this the Shutdown method does nothing but queue an event to the main thread to perform the actual Shutdown. This way the shutdown can occur at a safe time. @@ -263,25 +262,27 @@ when destroying the nsOggDecoder object. #include "nsCOMPtr.h" #include "nsIThread.h" #include "nsIChannel.h" -#include "nsChannelReader.h" #include "nsIObserver.h" #include "nsIFrame.h" #include "nsAutoPtr.h" #include "nsSize.h" #include "prlog.h" -#include "prmon.h" #include "gfxContext.h" #include "gfxRect.h" -#include "oggplay/oggplay.h" +#include "nsMediaStream.h" +#include "nsMediaDecoder.h" +#include "mozilla/Monitor.h" + +using mozilla::Monitor; class nsAudioStream; -class nsOggDecodeStateMachine; -class nsOggStepDecodeEvent; +class nsOggPlayStateMachine; +class nsOggReader; class nsOggDecoder : public nsMediaDecoder { - friend class nsOggDecodeStateMachine; - friend class nsOggStepDecodeEvent; + friend class nsOggReader; + friend class nsOggPlayStateMachine; // ISupports NS_DECL_ISUPPORTS @@ -336,7 +337,8 @@ class nsOggDecoder : public nsMediaDecoder virtual void NotifySuspendedStatusChanged(); virtual void NotifyBytesDownloaded(); virtual void NotifyDownloadEnded(nsresult aStatus); - // Called by nsChannelReader on the decoder thread + // Called by the decode thread to keep track of the number of bytes read + // from the resource. void NotifyBytesConsumed(PRInt64 aBytes); // Called when the video file has completed downloading. @@ -366,9 +368,6 @@ class nsOggDecoder : public nsMediaDecoder // Return PR_TRUE if seeking is supported. virtual PRBool GetSeekable(); - // Returns the channel reader. - nsChannelReader* GetReader() { return mReader; } - virtual Statistics GetStatistics(); // Suspend any media downloads that are in progress. Called by the @@ -384,23 +383,25 @@ class nsOggDecoder : public nsMediaDecoder // Tells our nsMediaStream to put all loads in the background. virtual void MoveLoadsToBackground(); - // Stop the state machine thread and drop references to the thread, - // state machine and channel reader. + // Stop the state machine thread and drop references to the thread and + // state machine. void Stop(); + // Called by the state machine to notify the decoder that the duration + // has changed. + void DurationChanged(); + protected: // Returns the monitor for other threads to synchronise access to // state. - PRMonitor* GetMonitor() - { + Monitor& GetMonitor() { return mMonitor; } // Return the current state. Can be called on any thread. If called from // a non-main thread, the decoder monitor must be held. - PlayState GetState() - { + PlayState GetState() { return mPlayState; } @@ -496,8 +497,8 @@ private: // time of the last decoded video frame). nsChannelStatistics mPlaybackStatistics; - // Thread to handle decoding of Ogg data. - nsCOMPtr mDecodeThread; + // Thread to manage playback state machine. + nsCOMPtr mStateMachineThread; // The current playback position of the media resource in units of // seconds. This is updated approximately at the framerate of the @@ -506,14 +507,12 @@ private: float mCurrentTime; // Volume that playback should start at. 0.0 = muted. 1.0 = full - // volume. Readable/Writeable from the main thread. Read from the - // audio thread when it is first started to get the initial volume - // level. + // volume. Readable/Writeable from the main thread. float mInitialVolume; // Position to seek to when the seek notification is received by the - // decoding thread. Written by the main thread and read via the - // decoding thread. Synchronised using mPlayStateMonitor. If the + // decode thread. Written by the main thread and read via the + // decode thread. Synchronised using mMonitor. If the // value is negative then no seek has been requested. When a seek is // started this is reset to negative. float mRequestedSeekTime; @@ -531,26 +530,20 @@ private: * The following member variables can be accessed from any thread. ******/ - // The state machine object for handling the decoding via - // oggplay. It is safe to call methods of this object from other - // threads. Its internal data is synchronised on a monitor. The - // lifetime of this object is after mPlayState is LOADING and before - // mPlayState is SHUTDOWN. It is safe to access it during this - // period. - nsCOMPtr mDecodeStateMachine; + // The state machine object for handling the decoding. It is safe to + // call methods of this object from other threads. Its internal data + // is synchronised on a monitor. The lifetime of this object is + // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It + // is safe to access it during this period. + nsCOMPtr mDecodeStateMachine; - // OggPlay object used to read data from a channel. Created on main - // thread. Passed to liboggplay and the locking for multithreaded - // access is handled by that library. Some methods are called from - // the decoder thread, and the state machine for that thread keeps - // a pointer to this reader. This is safe as the only methods called - // are threadsafe (via the threadsafe nsMediaStream). - nsAutoPtr mReader; + // Stream of media data. + nsAutoPtr mStream; // Monitor for detecting when the video play state changes. A call // to Wait on this monitor will block the thread until the next // state change. - PRMonitor* mMonitor; + Monitor mMonitor; // Set to one of the valid play states. It is protected by the // monitor mMonitor. This monitor must be acquired when reading or diff --git a/content/media/ogg/nsOggHacks.h b/content/media/ogg/nsOggHacks.h new file mode 100644 index 000000000000..a56d897a107c --- /dev/null +++ b/content/media/ogg/nsOggHacks.h @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsOggHacks_h +#define nsOggHacks_h + +// This file contains stuff we'd rather put elsewhere, but which is +// dependent on other changes which we don't want to wait for. We plan to +// remove this file in the near future. + + +// This belongs in prtypes.h +/************************************************************************ + * MACROS: PR_INT64_MAX + * PR_INT64_MIN + * PR_UINT64_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt64 or PRUint64. +************************************************************************/ + +#define PR_INT64_MAX (~((PRInt64)(1) << 63)) +#define PR_INT64_MIN (-PR_INT64_MAX - 1) +#define PR_UINT64_MAX (~(PRUint64)(0)) + + +// This belongs in xpcom/monitor/Monitor.h, once we've made +// mozilla::Monitor non-reentrant. +namespace mozilla { + +/** + * MonitorAutoExit + * Exit the Monitor when it enters scope, and enters it when it leaves + * scope. + * + * MUCH PREFERRED to bare calls to Monitor.Exit and Enter. + */ +class NS_COM_GLUE NS_STACK_CLASS MonitorAutoExit +{ +public: + /** + * Constructor + * The constructor releases the given lock. The destructor + * acquires the lock. The lock must be held before constructing + * this object! + * + * @param aMonitor A valid mozilla::Monitor* returned by + * mozilla::Monitor::NewMonitor. It must be + * already locked. + **/ + MonitorAutoExit(mozilla::Monitor &aMonitor) : + mMonitor(&aMonitor) + { + NS_ASSERTION(mMonitor, "null monitor"); + mMonitor->AssertCurrentThreadIn(); + mMonitor->Exit(); + } + + ~MonitorAutoExit(void) + { + mMonitor->Enter(); + } + +private: + MonitorAutoExit(); + MonitorAutoExit(const MonitorAutoExit&); + MonitorAutoExit& operator =(const MonitorAutoExit&); + static void* operator new(size_t) CPP_THROW_NEW; + static void operator delete(void*); + + mozilla::Monitor* mMonitor; +}; + +} // namespace mozilla +#endif diff --git a/content/media/ogg/nsOggPlayStateMachine.cpp b/content/media/ogg/nsOggPlayStateMachine.cpp new file mode 100644 index 000000000000..a088e3847e81 --- /dev/null +++ b/content/media/ogg/nsOggPlayStateMachine.cpp @@ -0,0 +1,1394 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include "nsAudioStream.h" +#include "nsTArray.h" +#include "nsOggDecoder.h" +#include "nsOggReader.h" +#include "nsOggPlayStateMachine.h" +#include "oggplay/oggplay.h" +#include "mozilla/mozalloc.h" +#include "nsOggHacks.h" + +using namespace mozilla::layers; +using mozilla::MonitorAutoExit; + +// Adds two 32bit unsigned numbers, retuns PR_TRUE if addition succeeded, +// or PR_FALSE the if addition would result in an overflow. +static PRBool AddOverflow(PRUint32 a, PRUint32 b, PRUint32& aResult); + +#ifdef PR_LOGGING +extern PRLogModuleInfo* gOggDecoderLog; +#define LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) +#else +#define LOG(type, msg) +#endif + +// Wait this number of seconds when buffering, then leave and play +// as best as we can if the required amount of data hasn't been +// retrieved. +#define BUFFERING_WAIT 30 + +// The amount of data to retrieve during buffering is computed based +// on the download rate. BUFFERING_MIN_RATE is the minimum download +// rate to be used in that calculation to help avoid constant buffering +// attempts at a time when the average download rate has not stabilised. +#define BUFFERING_MIN_RATE 50000 +#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x)) + +// The frame rate to use if there is no video data in the resource to +// be played. +#define AUDIO_FRAME_RATE 25.0 + +nsOggPlayStateMachine::nsOggPlayStateMachine(nsOggDecoder* aDecoder) : + mDecoder(aDecoder), + mState(DECODER_STATE_DECODING_METADATA), + mAudioMonitor("media.audiostream"), + mCbCrSize(0), + mPlayDuration(0), + mBufferingEndOffset(0), + mStartTime(-1), + mEndTime(-1), + mSeekTime(0), + mCurrentFrameTime(0), + mAudioStartTime(-1), + mAudioEndTime(-1), + mVideoFrameTime(-1), + mVolume(1.0), + mSeekable(PR_TRUE), + mPositionChangeQueued(PR_FALSE), + mAudioCompleted(PR_FALSE), + mBufferExhausted(PR_FALSE), + mGotDurationFromHeader(PR_FALSE), + mStopDecodeThreads(PR_TRUE) +{ + MOZ_COUNT_CTOR(nsOggPlayStateMachine); +} + +nsOggPlayStateMachine::~nsOggPlayStateMachine() +{ + MOZ_COUNT_DTOR(nsOggPlayStateMachine); +} + +void nsOggPlayStateMachine::DecodeLoop() +{ + NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); + PRBool videoPlaying = PR_FALSE; + PRBool audioPlaying = PR_FALSE; + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + videoPlaying = HasVideo(); + audioPlaying = HasAudio(); + } + + // We want to "pump" the decode until we've got a few frames/samples decoded + // before we consider whether decode is falling behind. + PRBool audioPump = PR_TRUE; + PRBool videoPump = PR_TRUE; + + // If the video decode is falling behind the audio, we'll start dropping the + // inter-frames up until the next keyframe which is at or before the current + // playback position. skipToNextKeyframe is PR_TRUE if we're currently + // skipping up to the next keyframe. + PRBool skipToNextKeyframe = PR_FALSE; + + // If we have fewer than videoKeyframeSkipThreshold decoded frames, and + // we're not "pumping video", we'll skip the video up to the next keyframe + // which is at or after the current playback position. + const unsigned videoKeyframeSkipThreshold = 1; + + // Once we've decoded more than videoPumpThreshold video frames, we'll + // no longer be considered to be "pumping video". + const unsigned videoPumpThreshold = 5; + + // If we've got more than videoWaitThreshold decoded video frames waiting in + // the video queue, we will not decode any more video frames until they've + // been consumed by the play state machine thread. + const unsigned videoWaitThreshold = 10; + + // After the audio decode fills with more than audioPumpThresholdMs ms + // of decoded audio, we'll start to check whether the audio or video decode + // is falling behind. + const unsigned audioPumpThresholdMs = 250; + + // If audio queue has less than this many ms of decoded audio, we won't risk + // trying to decode the video, we'll skip decoding video up to the next + // keyframe. + const unsigned lowAudioThresholdMs = 100; + + // If more than this many ms of decoded audio is queued, we'll hold off + // decoding more audio. + const unsigned audioWaitThresholdMs = 2000; + + // Main decode loop. + while (videoPlaying || audioPlaying) { + PRBool audioWait = !audioPlaying; + PRBool videoWait = !videoPlaying; + { + // Wait for more data to download if we've exhausted all our + // buffered data. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + while (!mStopDecodeThreads && + mBufferExhausted && + mState != DECODER_STATE_SHUTDOWN) + { + mon.Wait(); + } + if (mState == DECODER_STATE_SHUTDOWN || mStopDecodeThreads) + break; + } + + PRUint32 videoQueueSize = mReader->mVideoQueue.GetSize(); + // Don't decode any more frames if we've filled our buffers. + // Limits memory consumption. + if (videoQueueSize > videoWaitThreshold) { + videoWait = PR_TRUE; + } + + // We don't want to consider skipping to the next keyframe if we've + // only just started up the decode loop, so wait until we've decoded + // some frames before allowing the keyframe skip. + if (videoPump && videoQueueSize >= videoPumpThreshold) { + videoPump = PR_FALSE; + } + if (!videoPump && + videoPlaying && + videoQueueSize < videoKeyframeSkipThreshold) + { + skipToNextKeyframe = PR_TRUE; + } + + PRInt64 initialDownloadPosition = 0; + PRInt64 currentTime = 0; + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + initialDownloadPosition = + mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition); + currentTime = mCurrentFrameTime + mStartTime; + } + + // Determine how much audio data is decoded ahead of the current playback + // position. + int audioQueueSize = mReader->mAudioQueue.GetSize(); + PRInt64 audioDecoded = mReader->mAudioQueue.Duration(); + + // Don't decode any audio if the audio decode is way ahead, or if we're + // skipping to the next video keyframe and the audio is marginally ahead. + if (audioDecoded > audioWaitThresholdMs || + (skipToNextKeyframe && audioDecoded > audioPumpThresholdMs)) { + audioWait = PR_TRUE; + } + if (audioPump && audioDecoded > audioPumpThresholdMs) { + audioPump = PR_FALSE; + } + if (!audioPump && audioPlaying && audioDecoded < lowAudioThresholdMs) { + skipToNextKeyframe = PR_TRUE; + } + + if (videoPlaying && !videoWait) { + videoPlaying = mReader->DecodeVideoPage(skipToNextKeyframe, currentTime); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (mDecoder->mDecoderPosition >= initialDownloadPosition) { + mBufferExhausted = PR_TRUE; + } + } + } + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + initialDownloadPosition = + mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition); + mDecoder->GetMonitor().NotifyAll(); + } + + if (audioPlaying && !audioWait) { + audioPlaying = mReader->DecodeAudioPage(); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (mDecoder->mDecoderPosition >= initialDownloadPosition) { + mBufferExhausted = PR_TRUE; + } + } + } + + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + + if (!IsPlaying() && + (!audioWait || !videoWait) && + (videoQueueSize < 2 || audioQueueSize < 2)) + { + // Transitioning from 0 to 1 frames or from 1 to 2 frames could + // affect HaveNextFrameData and hence what UpdateReadyStateForData does. + // This could change us from HAVE_CURRENT_DATA to HAVE_FUTURE_DATA + // (or even HAVE_ENOUGH_DATA), so we'd better trigger an + // update to the ready state. We only need to do this if we're + // not playing; if we're playing the playback code will post an update + // whenever it advances a frame. + UpdateReadyState(); + } + + if (mState == DECODER_STATE_SHUTDOWN || mStopDecodeThreads) { + break; + } + if ((!HasAudio() || (audioWait && audioPlaying)) && + (!HasVideo() || (videoWait && videoPlaying))) + { + // All active bitstreams' decode is well ahead of the playback + // position, we may as well wait have for the playback to catch up. + mon.Wait(); + } + } + } + + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (!mStopDecodeThreads && + mState != DECODER_STATE_SHUTDOWN && + mState != DECODER_STATE_SEEKING) + { + mState = DECODER_STATE_COMPLETED; + mDecoder->GetMonitor().NotifyAll(); + } + } + LOG(PR_LOG_DEBUG, ("Shutting down DecodeLoop this=%p", this)); +} + +PRBool nsOggPlayStateMachine::IsPlaying() +{ + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return !mPlayStartTime.IsNull(); +} + +void nsOggPlayStateMachine::AudioLoop() +{ + NS_ASSERTION(OnAudioThread(), "Should be on audio thread."); + LOG(PR_LOG_DEBUG, ("Begun audio thread/loop")); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mAudioCompleted = PR_FALSE; + } + PRInt64 audioStartTime = -1; + while (1) { + + // Wait while we're not playing, and we're not shutting down, or we're + // playing and we've got no audio to play. + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + NS_ASSERTION(mState != DECODER_STATE_DECODING_METADATA, + "Should have meta data before audio started playing."); + while (mState != DECODER_STATE_SHUTDOWN && + !mStopDecodeThreads && + (!IsPlaying() || + mState == DECODER_STATE_BUFFERING || + (mState == DECODER_STATE_DECODING && + mReader->mAudioQueue.GetSize() == 0 && + !mReader->mAudioQueue.AtEndOfStream()))) + { + mon.Wait(); + } + + // If we're shutting down, break out and exit the audio thread. + if (mState == DECODER_STATE_SHUTDOWN || + mStopDecodeThreads || + mReader->mAudioQueue.AtEndOfStream()) + { + break; + } + } + + NS_ASSERTION(mReader->mAudioQueue.GetSize() > 0 && + !mReader->mAudioQueue.AtEndOfStream(), + "Should have data to play"); + nsAutoPtr sound(mReader->mAudioQueue.PopFront()); + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + NS_ASSERTION(IsPlaying(), "Should be playing"); + // Awaken the decode loop if it's waiting for space to free up in the + // audio queue. + mDecoder->GetMonitor().NotifyAll(); + } + + if (audioStartTime == -1) { + // Remember the presentation time of the first audio sample we play. + // We add this to the position/played duration of the audio stream to + // determine the audio clock time. Used for A/V sync. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mAudioStartTime = audioStartTime = sound->mTime; + LOG(PR_LOG_DEBUG, ("First audio sample has timestamp %lldms", mAudioStartTime)); + } + + { + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + // The state machine could have paused since we've released the decoder + // monitor and acquired the audio monitor. Rather than acquire both + // monitors, the audio stream also maintains whether its paused or not. + // This prevents us from doing a blocking write while holding the audio + // monitor while paused; we would block, and the state machine won't be + // able to acquire the audio monitor in order to resume or destroy the + // audio stream. + if (!mAudioStream->IsPaused()) { + mAudioStream->Write(sound->mAudioData, + sound->AudioDataLength(), + PR_TRUE); + } else { + mReader->mAudioQueue.PushFront(sound); + sound.forget(); + } + } + } + mAudioEndTime = sound->mTime + sound->mDuration; + sound = nsnull; + + if (mReader->mAudioQueue.AtEndOfStream()) { + // Last sample pushed to audio hardware, wait for the audio to finish, + // before the audio thread terminates. + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + mAudioStream->Drain(); + } + LOG(PR_LOG_DEBUG, ("%p Reached audio stream end.", mDecoder)); + } + } + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mAudioCompleted = PR_TRUE; + } + LOG(PR_LOG_DEBUG, ("Audio stream finished playing, audio thread exit")); +} + +nsresult nsOggPlayStateMachine::Init() +{ + mReader = new nsOggReader(this); + return mReader->Init(); +} + +void nsOggPlayStateMachine::StopPlayback(eStopMode aMode) +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + // Reset mPlayStartTime before we pause/shutdown the nsAudioStream. This is + // so that if the audio loop is about to write audio, it will have the chance + // to check to see if we're paused and not write the audio. If not, the + // audio thread can block in the write, and we deadlock trying to acquire + // the audio monitor upon resume playback. + if (IsPlaying()) { + mPlayDuration += TimeStamp::Now() - mPlayStartTime; + mPlayStartTime = TimeStamp(); + } + if (HasAudio()) { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + if (aMode == AUDIO_PAUSE) { + mAudioStream->Pause(); + } else if (aMode == AUDIO_SHUTDOWN) { + mAudioStream->Shutdown(); + mAudioStream = nsnull; + } + } + } +} + +void nsOggPlayStateMachine::StartPlayback() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + NS_ASSERTION(!IsPlaying(), "Shouldn't be playing when StartPlayback() is called"); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + LOG(PR_LOG_DEBUG, ("%p StartPlayback", mDecoder)); + if (HasAudio()) { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + // We have an audiostream, so it must have been paused the last time + // StopPlayback() was called. + mAudioStream->Resume(); + } else { + // No audiostream, create one. + mAudioStream = new nsAudioStream(); + mAudioStream->Init(mInfo.mAudioChannels, + mInfo.mAudioRate, + nsAudioStream::FORMAT_FLOAT32); + mAudioStream->SetVolume(mVolume); + } + } + mPlayStartTime = TimeStamp::Now(); + mDecoder->GetMonitor().NotifyAll(); +} + +void nsOggPlayStateMachine::UpdatePlaybackPosition(PRInt64 aTime) +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + NS_ASSERTION(mStartTime >= 0, "Should have positive mStartTime"); + mCurrentFrameTime = aTime - mStartTime; + NS_ASSERTION(mCurrentFrameTime >= 0, "CurrentTime should be positive!"); + if (aTime > mEndTime) { + NS_ASSERTION(mCurrentFrameTime > GetDuration(), + "CurrentTime must be after duration if aTime > endTime!"); + mEndTime = aTime; + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, DurationChanged); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + } + if (!mPositionChangeQueued) { + mPositionChangeQueued = PR_TRUE; + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackPositionChanged); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + } +} + +void nsOggPlayStateMachine::ClearPositionChangeFlag() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + mPositionChangeQueued = PR_FALSE; +} + +nsHTMLMediaElement::NextFrameStatus nsOggPlayStateMachine::GetNextFrameStatus() +{ + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (IsBuffering() || IsSeeking()) { + return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING; + } else if (HaveNextFrameData()) { + return nsHTMLMediaElement::NEXT_FRAME_AVAILABLE; + } + return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE; +} + +void nsOggPlayStateMachine::SetVolume(float volume) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + { + MonitorAutoEnter audioMon(mAudioMonitor); + if (mAudioStream) { + mAudioStream->SetVolume(volume); + } + } + { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + mVolume = volume; + } +} + +float nsOggPlayStateMachine::GetCurrentTime() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return (float)mCurrentFrameTime / 1000.0; +} + +PRInt64 nsOggPlayStateMachine::GetDuration() +{ + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + if (mEndTime == -1 || mStartTime == -1) + return -1; + return mEndTime - mStartTime; +} + +void nsOggPlayStateMachine::SetDuration(PRInt64 aDuration) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + if (mStartTime != -1) { + mEndTime = mStartTime + aDuration; + } else { + mStartTime = 0; + mEndTime = aDuration; + } +} + +void nsOggPlayStateMachine::SetSeekable(PRBool aSeekable) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + mSeekable = aSeekable; +} + +void nsOggPlayStateMachine::Shutdown() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + + // Once we've entered the shutdown state here there's no going back. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + + // Change state before issuing shutdown request to threads so those + // threads can start exiting cleanly during the Shutdown call. + LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN", mDecoder)); + mState = DECODER_STATE_SHUTDOWN; + mDecoder->GetMonitor().NotifyAll(); +} + +void nsOggPlayStateMachine::Decode() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + // When asked to decode, switch to decoding only if + // we are currently buffering. + MonitorAutoEnter mon(mDecoder->GetMonitor()); + if (mState == DECODER_STATE_BUFFERING) { + LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); + mState = DECODER_STATE_DECODING; + mDecoder->GetMonitor().NotifyAll(); + } +} + +void nsOggPlayStateMachine::ResetPlayback() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mVideoFrameTime = -1; + mAudioStartTime = -1; + mAudioEndTime = -1; + mAudioCompleted = PR_FALSE; +} + +void nsOggPlayStateMachine::Seek(float aTime) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); + MonitorAutoEnter mon(mDecoder->GetMonitor()); + // nsOggDecoder::mPlayState should be SEEKING while we seek, and + // in that case nsOggDecoder shouldn't be calling us. + NS_ASSERTION(mState != DECODER_STATE_SEEKING, + "We shouldn't already be seeking"); + NS_ASSERTION(mState >= DECODER_STATE_DECODING, + "We should have loaded metadata"); + double t = aTime * 1000.0; + if (t > PR_INT64_MAX) { + // Prevent integer overflow. + return; + } + + mSeekTime = static_cast(t) + mStartTime; + NS_ASSERTION(mSeekTime >= mStartTime && mSeekTime <= mEndTime, + "Can only seek in range [0,duration]"); + + // Bound the seek time to be inside the media range. + NS_ASSERTION(mStartTime != -1, "Should know start time by now"); + NS_ASSERTION(mEndTime != -1, "Should know end time by now"); + mSeekTime = NS_MIN(mSeekTime, mEndTime); + mSeekTime = NS_MAX(mStartTime, mSeekTime); + LOG(PR_LOG_DEBUG, ("%p Changed state to SEEKING (to %f)", mDecoder, aTime)); + mState = DECODER_STATE_SEEKING; +} + +void nsOggPlayStateMachine::StopDecodeThreads() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + mStopDecodeThreads = PR_TRUE; + mDecoder->GetMonitor().NotifyAll(); + if (mDecodeThread) { + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + mDecodeThread->Shutdown(); + } + mDecodeThread = nsnull; + } + if (mAudioThread) { + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + mAudioThread->Shutdown(); + } + mAudioThread = nsnull; + } +} + +nsresult +nsOggPlayStateMachine::StartDecodeThreads() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + mStopDecodeThreads = PR_FALSE; + if (!mDecodeThread && mState < DECODER_STATE_COMPLETED) { + nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread)); + if (NS_FAILED(rv)) { + mState = DECODER_STATE_SHUTDOWN; + return rv; + } + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggPlayStateMachine, this, DecodeLoop); + mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL); + } + if (HasAudio() && !mAudioThread) { + nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread)); + if (NS_FAILED(rv)) { + mState = DECODER_STATE_SHUTDOWN; + return rv; + } + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggPlayStateMachine, this, AudioLoop); + mAudioThread->Dispatch(event, NS_DISPATCH_NORMAL); + } + return NS_OK; +} + +nsresult nsOggPlayStateMachine::Run() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + nsMediaStream* stream = mDecoder->mStream; + NS_ENSURE_TRUE(stream, NS_ERROR_NULL_POINTER); + + while (PR_TRUE) { + MonitorAutoEnter mon(mDecoder->GetMonitor()); + switch (mState) { + case DECODER_STATE_SHUTDOWN: + if (IsPlaying()) { + StopPlayback(AUDIO_SHUTDOWN); + } + StopDecodeThreads(); + NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN, + "How did we escape from the shutdown state???"); + return NS_OK; + + case DECODER_STATE_DECODING_METADATA: + { + LoadOggHeaders(); + if (mState == DECODER_STATE_SHUTDOWN) { + continue; + } + + VideoData* videoData = FindStartTime(); + if (videoData) { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + RenderVideoFrame(videoData); + } + + // Start the decode threads, so that we can pre buffer the streams. + // and calculate the start time in order to determine the duration. + if (NS_FAILED(StartDecodeThreads())) { + continue; + } + + NS_ASSERTION(mStartTime != -1, "Must have start time"); + NS_ASSERTION((!HasVideo() && !HasAudio()) || + !mSeekable || mEndTime != -1, + "Active seekable media should have end time"); + NS_ASSERTION(!mSeekable || GetDuration() != -1, "Seekable media should have duration"); + LOG(PR_LOG_DEBUG, ("%p Media goes from %lldms to %lldms (duration %lldms) seekable=%d", + mDecoder, mStartTime, mEndTime, GetDuration(), mSeekable)); + + if (mState == DECODER_STATE_SHUTDOWN) + continue; + + // Inform the element that we've loaded the Ogg metadata and the + // first frame. + nsCOMPtr metadataLoadedEvent = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, MetadataLoaded); + NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); + + if (mState == DECODER_STATE_DECODING_METADATA) { + LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder)); + mState = DECODER_STATE_DECODING; + } + + // Start playback. + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + if (!IsPlaying()) { + StartPlayback(); + } + } + } + break; + + case DECODER_STATE_DECODING: + { + if (NS_FAILED(StartDecodeThreads())) { + continue; + } + + AdvanceFrame(); + + if (mState != DECODER_STATE_DECODING) + continue; + + if (mBufferExhausted && + mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING && + !mDecoder->mStream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && + !mDecoder->mStream->IsSuspendedByCache()) { + // There is at most one frame in the queue and there's + // more data to load. Let's buffer to make sure we can play a + // decent amount of video in the future. + if (IsPlaying()) { + StopPlayback(AUDIO_PAUSE); + mDecoder->GetMonitor().NotifyAll(); + } + + // We need to tell the element that buffering has started. + // We can't just directly send an asynchronous runnable that + // eventually fires the "waiting" event. The problem is that + // there might be pending main-thread events, such as "data + // received" notifications, that mean we're not actually still + // buffering by the time this runnable executes. So instead + // we just trigger UpdateReadyStateForData; when it runs, it + // will check the current state and decide whether to tell + // the element we're buffering or not. + UpdateReadyState(); + + mBufferingStart = TimeStamp::Now(); + PRPackedBool reliable; + double playbackRate = mDecoder->ComputePlaybackRate(&reliable); + mBufferingEndOffset = mDecoder->mDecoderPosition + + BUFFERING_RATE(playbackRate) * BUFFERING_WAIT; + mState = DECODER_STATE_BUFFERING; + LOG(PR_LOG_DEBUG, ("Changed state from DECODING to BUFFERING")); + } else { + if (mBufferExhausted) { + // This will wake up the decode thread and force it to try to + // decode video and audio. This guarantees we make progress. + mBufferExhausted = PR_FALSE; + mDecoder->GetMonitor().NotifyAll(); + } + } + + } + break; + + case DECODER_STATE_SEEKING: + { + // During the seek, don't have a lock on the decoder state, + // otherwise long seek operations can block the main thread. + // The events dispatched to the main thread are SYNC calls. + // These calls are made outside of the decode monitor lock so + // it is safe for the main thread to makes calls that acquire + // the lock since it won't deadlock. We check the state when + // acquiring the lock again in case shutdown has occurred + // during the time when we didn't have the lock. + PRInt64 seekTime = mSeekTime; + mDecoder->StopProgressUpdates(); + + StopPlayback(AUDIO_SHUTDOWN); + StopDecodeThreads(); + ResetPlayback(); + + // SeekingStarted will do a UpdateReadyStateForData which will + // inform the element and its users that we have no frames + // to display + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + nsCOMPtr startEvent = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStarted); + NS_DispatchToMainThread(startEvent, NS_DISPATCH_SYNC); + } + if (mCurrentFrameTime != mSeekTime - mStartTime) { + nsresult res; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + // Now perform the seek. We must not hold the state machine monitor + // while we seek, since the seek decodes. + res = mReader->Seek(seekTime, mStartTime, mEndTime); + } + if (NS_SUCCEEDED(res)){ + SoundData* audio = HasAudio() ? mReader->mAudioQueue.PeekFront() : nsnull; + if (audio) { + mPlayDuration = TimeDuration::FromMilliseconds(audio->mTime); + } + if (HasVideo()) { + nsAutoPtr video(mReader->mVideoQueue.PeekFront()); + if (video) { + RenderVideoFrame(video); + if (!audio) { + NS_ASSERTION(video->mTime <= seekTime && + seekTime <= video->mTime + mInfo.mCallbackPeriod, + "Seek target should lie inside the first frame after seek"); + mPlayDuration = TimeDuration::FromMilliseconds(seekTime); + } + } + mReader->mVideoQueue.PopFront(); + } + UpdatePlaybackPosition(seekTime); + } + } + mDecoder->StartProgressUpdates(); + if (mState == DECODER_STATE_SHUTDOWN) + continue; + + // Try to decode another frame to detect if we're at the end... + LOG(PR_LOG_DEBUG, ("Seek completed, mCurrentFrameTime=%lld\n", mCurrentFrameTime)); + + // Change state to DECODING or COMPLETED now. SeekingStopped will + // call nsOggPlayStateMachine::Seek to reset our state to SEEKING + // if we need to seek again. + + nsCOMPtr stopEvent; + if (mCurrentFrameTime == mEndTime) { + LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lldms) to COMPLETED", + mDecoder, seekTime)); + stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd); + mState = DECODER_STATE_COMPLETED; + } else { + LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lldms) to DECODING", + mDecoder, seekTime)); + stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped); + mState = DECODER_STATE_DECODING; + } + mBufferExhausted = PR_FALSE; + mDecoder->GetMonitor().NotifyAll(); + + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC); + } + } + break; + + case DECODER_STATE_BUFFERING: + { + TimeStamp now = TimeStamp::Now(); + if (now - mBufferingStart < TimeDuration::FromSeconds(BUFFERING_WAIT) && + mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition) < mBufferingEndOffset && + !mDecoder->mStream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) && + !mDecoder->mStream->IsSuspendedByCache()) { + LOG(PR_LOG_DEBUG, + ("In buffering: buffering data until %d bytes available or %f seconds", + PRUint32(mBufferingEndOffset - mDecoder->mStream->GetCachedDataEnd(mDecoder->mDecoderPosition)), + BUFFERING_WAIT - (now - mBufferingStart).ToSeconds())); + Wait(1000); + if (mState == DECODER_STATE_SHUTDOWN) + continue; + } else { + LOG(PR_LOG_DEBUG, ("%p Changed state from BUFFERING to DECODING", mDecoder)); + LOG(PR_LOG_DEBUG, ("%p Buffered for %lf seconds", + mDecoder, + (TimeStamp::Now() - mBufferingStart).ToSeconds())); + mState = DECODER_STATE_DECODING; + } + + if (mState != DECODER_STATE_BUFFERING) { + mBufferExhausted = PR_FALSE; + // Notify to allow blocked decoder thread to continue + mDecoder->GetMonitor().NotifyAll(); + UpdateReadyState(); + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + if (!IsPlaying()) { + StartPlayback(); + } + } + } + + break; + } + + case DECODER_STATE_COMPLETED: + { + if (NS_FAILED(StartDecodeThreads())) { + continue; + } + + // Play the remaining media. + while (mState == DECODER_STATE_COMPLETED && + (mReader->mVideoQueue.GetSize() > 0 || + (HasAudio() && !mAudioCompleted))) + { + AdvanceFrame(); + } + + if (mAudioStream) { + // Close the audop stream so that next time audio is used a new stream + // is created. The StopPlayback call also resets the IsPlaying() state + // so audio is restarted correctly. + StopPlayback(AUDIO_SHUTDOWN); + } + + if (mState != DECODER_STATE_COMPLETED) + continue; + + LOG(PR_LOG_DEBUG, ("Shutting down the state machine thread")); + StopDecodeThreads(); + + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + PRInt64 videoTime = HasVideo() ? (mVideoFrameTime + mInfo.mCallbackPeriod) : 0; + PRInt64 clockTime = NS_MAX(mEndTime, NS_MAX(videoTime, GetAudioClock())); + UpdatePlaybackPosition(clockTime); + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, PlaybackEnded); + NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); + } + } + + while (mState == DECODER_STATE_COMPLETED) { + mDecoder->GetMonitor().Wait(); + } + } + break; + } + } + + return NS_OK; +} + +static void ToARGBHook(const PlanarYCbCrImage::Data& aData, PRUint8* aOutput) +{ + OggPlayYUVChannels yuv; + NS_ASSERTION(aData.mYStride == aData.mYSize.width, + "Stride not supported"); + NS_ASSERTION(aData.mCbCrStride == aData.mCbCrSize.width, + "Stride not supported"); + yuv.ptry = aData.mYChannel; + yuv.ptru = aData.mCbChannel; + yuv.ptrv = aData.mCrChannel; + yuv.uv_width = aData.mCbCrSize.width; + yuv.uv_height = aData.mCbCrSize.height; + yuv.y_width = aData.mYSize.width; + yuv.y_height = aData.mYSize.height; + + OggPlayRGBChannels rgb; + rgb.ptro = aOutput; + rgb.rgb_width = aData.mYSize.width; + rgb.rgb_height = aData.mYSize.height; + + oggplay_yuv2bgra(&yuv, &rgb); +} + +void nsOggPlayStateMachine::RenderVideoFrame(VideoData* aData) +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + + if (aData->mDuplicate) { + return; + } + + unsigned xSubsample = (aData->mBuffer[1].width != 0) ? + (aData->mBuffer[0].width / aData->mBuffer[1].width) : 0; + + unsigned ySubsample = (aData->mBuffer[1].height != 0) ? + (aData->mBuffer[0].height / aData->mBuffer[1].height) : 0; + + if (xSubsample == 0 || ySubsample == 0) { + // We can't perform yCbCr to RGB, so we can't render the frame... + return; + } + NS_ASSERTION(mInfo.mPicture.width != 0 && mInfo.mPicture.height != 0, + "We can only render non-zero-sized video"); + + unsigned cbCrStride = mInfo.mPicture.width / xSubsample; + unsigned cbCrHeight = mInfo.mPicture.height / ySubsample; + + // Ensure the picture size specified in the headers can be extracted out of + // the frame we've been supplied without indexing out of bounds. + PRUint32 picXLimit; + PRUint32 picYLimit; + if (!AddOverflow(mInfo.mPicture.x, mInfo.mPicture.width, picXLimit) || + picXLimit > PR_ABS(aData->mBuffer[0].stride) || + !AddOverflow(mInfo.mPicture.y, mInfo.mPicture.height, picYLimit) || + picYLimit > PR_ABS(aData->mBuffer[0].height)) + { + // The specified picture dimensions can't be contained inside the video + // frame, we'll stomp memory if we try to copy it. Fail. + return; + } + + unsigned cbCrSize = PR_ABS(aData->mBuffer[0].stride * aData->mBuffer[0].height) + + PR_ABS(aData->mBuffer[1].stride * aData->mBuffer[1].height) * 2; + if (cbCrSize != mCbCrSize) { + mCbCrSize = cbCrSize; + mCbCrBuffer = static_cast(moz_xmalloc(cbCrSize)); + if (!mCbCrBuffer) { + // Malloc failed... + NS_WARNING("Malloc failure allocating YCbCr->RGB buffer"); + return; + } + } + + unsigned char* data = mCbCrBuffer.get(); + + unsigned char* y = data; + unsigned char* cb = y + (mInfo.mPicture.width * PR_ABS(aData->mBuffer[0].height)); + unsigned char* cr = cb + (cbCrStride * PR_ABS(aData->mBuffer[1].height)); + + unsigned char* p = y; + unsigned yStride = mInfo.mPicture.width; + unsigned char* q = aData->mBuffer[0].data + mInfo.mPicture.x + + aData->mBuffer[0].stride * mInfo.mPicture.y; + for(unsigned i=0; i < mInfo.mPicture.height; ++i) { + NS_ASSERTION(q + mInfo.mPicture.width < + aData->mBuffer[0].data + aData->mBuffer[0].stride * aData->mBuffer[0].height, + "Y read must be in bounds"); + NS_ASSERTION(p + mInfo.mPicture.width < data + mCbCrSize, + "Memory copy 1 will stomp"); + memcpy(p, q, mInfo.mPicture.width); + p += mInfo.mPicture.width; + q += aData->mBuffer[0].stride; + } + + unsigned xo = xSubsample ? (mInfo.mPicture.x / xSubsample) : 0; + unsigned yo = ySubsample ? aData->mBuffer[1].stride * (mInfo.mPicture.y / ySubsample) : 0; + + unsigned cbCrOffset = xo+yo; + p = cb; + q = aData->mBuffer[1].data + cbCrOffset; + unsigned char* p2 = cr; + unsigned char* q2 = aData->mBuffer[2].data + cbCrOffset; +#ifdef DEBUG + unsigned char* buffer1Limit = + aData->mBuffer[1].data + aData->mBuffer[1].stride * aData->mBuffer[1].height; + unsigned char* buffer2Limit = + aData->mBuffer[2].data + aData->mBuffer[2].stride * aData->mBuffer[2].height; +#endif + for(unsigned i=0; i < cbCrHeight; ++i) { + NS_ASSERTION(q + cbCrStride <= buffer1Limit, + "Cb source read must be within bounds"); + NS_ASSERTION(q2 + cbCrStride <= buffer2Limit, + "Cr source read must be within bounds"); + NS_ASSERTION(p + cbCrStride < data + mCbCrSize, + "Cb write destination must be within bounds"); + NS_ASSERTION(p2 + cbCrStride < data + mCbCrSize, + "Cr write destination must be within bounds"); + memcpy(p, q, cbCrStride); + memcpy(p2, q2, cbCrStride); + p += cbCrStride; + p2 += cbCrStride; + q += aData->mBuffer[1].stride; + q2 += aData->mBuffer[2].stride; + } + + ImageContainer* container = mDecoder->GetImageContainer(); + // Currently our Ogg decoder only knows how to output to PLANAR_YCBCR + // format. + Image::Format format = Image::PLANAR_YCBCR; + nsRefPtr image; + if (container) { + image = container->CreateImage(&format, 1); + } + if (image) { + NS_ASSERTION(image->GetFormat() == Image::PLANAR_YCBCR, + "Wrong format?"); + PlanarYCbCrImage* videoImage = static_cast(image.get()); + // XXX this is only temporary until we get YCbCr code in the layer + // system. + videoImage->SetRGBConverter(ToARGBHook); + PlanarYCbCrImage::Data data; + data.mYChannel = y; + data.mYSize = gfxIntSize(mInfo.mPicture.width, mInfo.mPicture.height); + data.mYStride = mInfo.mPicture.width; + data.mCbChannel = cb; + data.mCrChannel = cr; + data.mCbCrSize = gfxIntSize(cbCrStride, cbCrHeight); + data.mCbCrStride = cbCrStride; + videoImage->SetData(data); + mDecoder->SetVideoData(data.mYSize, mInfo.mAspectRatio, image); + } +} + +PRInt64 +nsOggPlayStateMachine::GetAudioClock() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + if (!mAudioStream || !HasAudio()) + return -1; + PRInt64 t = mAudioStream->GetPosition(); + return (t == -1) ? -1 : t + mAudioStartTime; +} + +void nsOggPlayStateMachine::AdvanceFrame() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + // When it's time to display a frame, decode the frame and display it. + if (mDecoder->GetState() == nsOggDecoder::PLAY_STATE_PLAYING) { + if (!IsPlaying()) { + StartPlayback(); + mDecoder->GetMonitor().NotifyAll(); + } + + if (HasAudio() && mAudioStartTime == -1 && !mAudioCompleted) { + // We've got audio (so we should sync off the audio clock), but we've + // not played a sample on the audio thread, so we can't get a time + // from the audio clock. Just wait and then return, to give the audio + // clock time to tick. + Wait(mInfo.mCallbackPeriod); + return; + } + + // Determine the clock time. If we've got audio, and we've not reached + // the end of the audio, use the audio clock. However if we've finished + // audio, or don't have audio, use the system clock. + PRInt64 clock_time = -1; + PRInt64 audio_time = GetAudioClock(); + if (HasAudio() && !mAudioCompleted && audio_time != -1) { + clock_time = audio_time; + // Resync against the audio clock, while we're trusting the + // audio clock. This ensures no "drift", particularly on Linux. + mPlayStartTime = TimeStamp::Now() - TimeDuration::FromMilliseconds(clock_time); + } else { + // Sound is disabled on this system. Sync to the system clock. + TimeDuration t = TimeStamp::Now() - mPlayStartTime + mPlayDuration; + clock_time = (PRInt64)(1000 * t.ToSeconds()); + // Ensure the clock can never go backwards. + NS_ASSERTION(mCurrentFrameTime <= clock_time, "Clock should go forwards"); + clock_time = NS_MAX(mCurrentFrameTime, clock_time) + mStartTime; + } + + NS_ASSERTION(clock_time >= mStartTime, "Should have positive clock time."); + nsAutoPtr videoData; + if (mReader->mVideoQueue.GetSize() > 0) { + VideoData* data = mReader->mVideoQueue.PeekFront(); + while (clock_time >= data->mTime) { + mVideoFrameTime = data->mTime; + videoData = data; + mReader->mVideoQueue.PopFront(); + if (mReader->mVideoQueue.GetSize() == 0) + break; + data = mReader->mVideoQueue.PeekFront(); + } + } + + if (videoData) { + // Decode one frame and display it + NS_ASSERTION(videoData->mTime >= mStartTime, "Should have positive frame time"); + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + // If we have video, we want to increment the clock in steps of the frame + // duration. + RenderVideoFrame(videoData); + } + mDecoder->GetMonitor().NotifyAll(); + videoData = nsnull; + } + + // Cap the current time to the larger of the audio and video end time. + // This ensures that if we're running off the system clock, we don't + // advance the clock to after the media end time. + if (mVideoFrameTime != -1 || mAudioEndTime != -1) { + // These will be non -1 if we've displayed a video frame, or played an audio sample. + clock_time = NS_MIN(clock_time, NS_MAX(mVideoFrameTime, mAudioEndTime)); + if (clock_time - mStartTime > mCurrentFrameTime) { + // Only update the playback position if the clock time is greater + // than the previous playback position. The audio clock can + // sometimes report a time less than its previously reported in + // some situations, and we need to gracefully handle that. + UpdatePlaybackPosition(clock_time); + } + } + + // If the number of audio/video samples queued has changed, either by + // this function popping and playing a video sample, or by the audio + // thread popping and playing an audio sample, we may need to update our + // ready state. Post an update to do so. + UpdateReadyState(); + + Wait(mInfo.mCallbackPeriod); + } else { + if (IsPlaying()) { + StopPlayback(AUDIO_PAUSE); + mDecoder->GetMonitor().NotifyAll(); + } + + if (mState == DECODER_STATE_DECODING || + mState == DECODER_STATE_COMPLETED) { + mDecoder->GetMonitor().Wait(); + } + } +} + +void nsOggPlayStateMachine::Wait(PRUint32 aMs) { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + TimeStamp end = TimeStamp::Now() + TimeDuration::FromMilliseconds(aMs); + TimeStamp now; + while ((now = TimeStamp::Now()) < end && + mState != DECODER_STATE_SHUTDOWN && + mState != DECODER_STATE_SEEKING) + { + TimeDuration d = end - now; + PRInt64 ms = d.ToSeconds() * 1000; + if (ms == 0) { + break; + } + NS_ASSERTION(ms <= aMs && ms > 0, + "nsOggPlayStateMachine::Wait interval very wrong!"); + mDecoder->GetMonitor().Wait(PR_MillisecondsToInterval(ms)); + } +} + +void nsOggPlayStateMachine::LoadOggHeaders() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), + "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + LOG(PR_LOG_DEBUG, ("Loading Ogg Headers")); + + nsMediaStream* stream = mDecoder->mStream; + + nsOggInfo info; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + mReader->ReadOggHeaders(info); + } + mInfo = info; + mDecoder->StartProgressUpdates(); + + if (!mInfo.mHasVideo && !mInfo.mHasAudio) { + mState = DECODER_STATE_SHUTDOWN; + nsCOMPtr event = + NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, DecodeError); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + return; + } + + if (!mInfo.mHasVideo) { + mInfo.mCallbackPeriod = 1000 / AUDIO_FRAME_RATE; + } + LOG(PR_LOG_DEBUG, ("%p Callback Period: %u", mDecoder, mInfo.mCallbackPeriod)); + + // TODO: Get the duration from Skeleton index, if available. + + // Get the duration from the Ogg file. We only do this if the + // content length of the resource is known as we need to seek + // to the end of the file to get the last time field. We also + // only do this if the resource is seekable and if we haven't + // already obtained the duration via an HTTP header. + mGotDurationFromHeader = (GetDuration() != -1); + if (mState != DECODER_STATE_SHUTDOWN && + stream->GetLength() >= 0 && + mSeekable && + mEndTime == -1) + { + mDecoder->StopProgressUpdates(); + FindEndTime(); + mDecoder->StartProgressUpdates(); + mDecoder->UpdatePlaybackRate(); + } +} + +VideoData* nsOggPlayStateMachine::FindStartTime() +{ + NS_ASSERTION(IsThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + PRInt64 startTime = 0; + mStartTime = 0; + VideoData* v = nsnull; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + v = mReader->FindStartTime(mInfo.mDataOffset, startTime); + } + if (startTime != 0) { + mStartTime = startTime; + if (mGotDurationFromHeader) { + NS_ASSERTION(mEndTime != -1, + "We should have mEndTime as supplied duration here"); + // We were specified a duration from a Content-Duration HTTP header. + // Adjust mEndTime so that mEndTime-mStartTime matches the specified + // duration. + mEndTime = mStartTime + mEndTime; + } + } + LOG(PR_LOG_DEBUG, ("%p Media start time is %lldms", mDecoder, mStartTime)); + return v; +} + +void nsOggPlayStateMachine::FindEndTime() +{ + NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread."); + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + nsMediaStream* stream = mDecoder->mStream; + + // Seek to the end of file to find the length and duration. + PRInt64 length = stream->GetLength(); + NS_ASSERTION(length > 0, "Must have a content length to get end time"); + + mEndTime = 0; + PRInt64 endTime = 0; + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + endTime = mReader->FindEndTime(length); + } + if (endTime != -1) { + mEndTime = endTime; + } + + NS_ASSERTION(mInfo.mDataOffset > 0, + "Should have offset of first non-header page"); + { + MonitorAutoExit exitMon(mDecoder->GetMonitor()); + stream->Seek(nsISeekableStream::NS_SEEK_SET, mInfo.mDataOffset); + } + LOG(PR_LOG_DEBUG, ("%p Media end time is %lldms", mDecoder, mEndTime)); +} + +void nsOggPlayStateMachine::UpdateReadyState() { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + nsCOMPtr event; + switch (GetNextFrameStatus()) { + case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING: + event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailableBuffering); + break; + case nsHTMLMediaElement::NEXT_FRAME_AVAILABLE: + event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameAvailable); + break; + case nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE: + event = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, NextFrameUnavailable); + break; + default: + PR_NOT_REACHED("unhandled frame state"); + } + + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); +} + + +static PRBool AddOverflow(PRUint32 a, PRUint32 b, PRUint32& aResult) { + PRUint64 rl = static_cast(a) + static_cast(b); + if (rl > PR_UINT32_MAX) { + return PR_FALSE; + } + aResult = static_cast(rl); + return true; +} diff --git a/content/media/ogg/nsOggPlayStateMachine.h b/content/media/ogg/nsOggPlayStateMachine.h new file mode 100644 index 000000000000..cff645e51204 --- /dev/null +++ b/content/media/ogg/nsOggPlayStateMachine.h @@ -0,0 +1,419 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#if !defined(nsOggPlayStateMachine_h__) +#define nsOggPlayStateMachine_h__ + +#include "prmem.h" +#include "nsThreadUtils.h" +#include "nsOggReader.h" +#include "nsOggDecoder.h" +#include "nsHTMLMediaElement.h" +#include "mozilla/Monitor.h" + +using mozilla::TimeDuration; +using mozilla::TimeStamp; + +class nsOggDecoder; + +// Checks if we're on a specific thread or not. Used in assertions to +// verify thread safety. +static inline PRBool IsThread(nsIThread* aThread) { + return NS_GetCurrentThread() == aThread; +} + +/* + The playback state machine class. This manages the decoding in the + nsOggReader on the decode thread, seeking and in-sync-playback on the + state machine thread, and controls the audio "push" thread. + + All internal state is synchronised via the decoder monitor. NotifyAll + on the monitor is called when the state of the state machine is changed + by the main thread. The following changes to state cause a notify: + + mState and data related to that state changed (mSeekTime, etc) + Ogg Metadata Loaded + First Frame Loaded + Frame decoded + data pushed or popped from the video and audio queues + + See nsOggDecoder.h for more details. +*/ +class nsOggPlayStateMachine : public nsRunnable +{ +public: + // Enumeration for the valid states + enum State { + DECODER_STATE_DECODING_METADATA, + DECODER_STATE_DECODING, + DECODER_STATE_SEEKING, + DECODER_STATE_BUFFERING, + DECODER_STATE_COMPLETED, + DECODER_STATE_SHUTDOWN + }; + + nsOggPlayStateMachine(nsOggDecoder* aDecoder); + ~nsOggPlayStateMachine(); + + // Initializes the state machine, returns NS_OK on success, or + // NS_ERROR_FAILURE on failure. + nsresult Init(); + + // Cause state transitions. These methods obtain the decoder monitor + // to synchronise the change of state, and to notify other threads + // that the state has changed. + void Shutdown(); + void Decode(); + + // Seeks to aTime seconds. + void Seek(float aTime); + + // State machine thread run function. Polls the state, sends frames to be + // displayed at appropriate times, and generally manages the decode. + NS_IMETHOD Run(); + + // This is called on the state machine thread and audio thread. + // The decoder monitor must be obtained before calling this. + PRBool HasAudio() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + return mInfo.mHasAudio; + } + + // This is called on the state machine thread and audio thread. + // The decoder monitor must be obtained before calling this. + PRBool HasVideo() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + return mInfo.mHasVideo; + } + + // Returns the current playback position in seconds. + // Called from the main thread to get the current frame time. The decoder + // monitor must be obtained before calling this. + float GetCurrentTime(); + + // Called from the main thread to get the duration. The decoder monitor + // must be obtained before calling this. It is in units of milliseconds. + PRInt64 GetDuration(); + + // Called from the main thread to set the duration of the media resource + // if it is able to be obtained via HTTP headers. The decoder monitor + // must be obtained before calling this. + void SetDuration(PRInt64 aDuration); + + // Called from the main thread to set whether the media resource can + // be seeked. The decoder monitor must be obtained before calling this. + void SetSeekable(PRBool aSeekable); + + // Set the audio volume. The decoder monitor must be obtained before + // calling this. + void SetVolume(float aVolume); + + // Clear the flag indicating that a playback position change event + // is currently queued. This is called from the main thread and must + // be called with the decode monitor held. + void ClearPositionChangeFlag(); + + // Should be called by main thread. + PRBool HaveNextFrameData() const { + PRUint32 audioQueueSize = mReader->mAudioQueue.GetSize(); + return (mReader->mVideoQueue.GetSize() > 0 && + (!HasAudio() || audioQueueSize > 0)) || + audioQueueSize > 0; + } + + // Must be called with the decode monitor held. + PRBool IsBuffering() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return mState == nsOggPlayStateMachine::DECODER_STATE_BUFFERING; + } + + // Must be called with the decode monitor held. + PRBool IsSeeking() const { + mDecoder->GetMonitor().AssertCurrentThreadIn(); + + return mState == nsOggPlayStateMachine::DECODER_STATE_SEEKING; + } + + // Functions used by assertions to ensure we're calling things + // on the appropriate threads. + PRBool OnStateMachineThread() { + return IsThread(mDecoder->mStateMachineThread); + } + + PRBool OnDecodeThread() { + return IsThread(mDecodeThread); + } + + PRBool OnAudioThread() { + return IsThread(mAudioThread); + } + + // Decode loop, called on the decode thread. + void DecodeLoop(); + + // The decoder object that created this state machine. The decoder + // always outlives us since it controls our lifetime. This is accessed + // read only on the AV, state machine, audio and main thread. + nsOggDecoder* mDecoder; + + // Update the playback position. This can result in a timeupdate event + // and an invalidate of the frame being dispatched asynchronously if + // there is no such event currently queued. + // Only called on the decoder thread. Must be called with + // the decode monitor held. + void UpdatePlaybackPosition(PRInt64 aTime); + + nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus(); + + // The decoder monitor must be obtained before modifying this state. + // NotifyAll on the monitor must be called when the state is changed by + // the main thread so the decoder thread can wake up. + // Accessed on state machine, audio, main, and AV thread. + State mState; + +private: + + // Waits on the decoder Monitor for aMs. If the decoder monitor is awoken + // by a Notify() call, we'll continue waiting, unless we've moved into + // shutdown state. This enables us to ensure that we wait for a specified + // time, and that the myriad of Notify()s we do an the decoder monitor + // don't cause the audio thread to be starved. The decoder monitor must + // be locked. + void Wait(PRUint32 aMs); + + // Dispatches an asynchronous event to update the media element's ready state. + void UpdateReadyState(); + + // Resets playback timing data. Called when we seek, on the state machine + // thread. + void ResetPlayback(); + + // Returns the audio clock, if we have audio, or -1 if we don't. + // Called on the state machine thread. + PRInt64 GetAudioClock(); + + // Returns the presentation time of the first sample or frame in the media. + // If the media has video, it returns the first video frame. The decoder + // monitor must be held with exactly one lock count. Called on the state + // machine thread. + VideoData* FindStartTime(); + + // Finds the end time of the last page in the Ogg file, storing the value + // in mEndTime if successful. The decoder must be held with exactly one lock + // count. Called on the state machine thread. + void FindEndTime(); + + // Performs YCbCr to RGB conversion, and pushes the image down the + // rendering pipeline. Called on the state machine thread. + void RenderVideoFrame(VideoData* aData); + + // If we have video, display a video frame if it's time for display has + // arrived, otherwise sleep until it's time for the next sample. Update + // the current frame time as appropriate, and trigger ready state update. + // The decoder monitor must be held with exactly one lock count. Called + // on the state machine thread. + void AdvanceFrame(); + + // Stops the decode threads. The decoder monitor must be held with exactly + // one lock count. Called on the state machine thread. + void StopDecodeThreads(); + + // Starts the decode threads. The decoder monitor must be held with exactly + // one lock count. Called on the state machine thread. + nsresult StartDecodeThreads(); + + // Reads the Ogg headers using the nsOggReader, and initializes playback. + // Called on the state machine thread. The decoder monitor must be held with + // exactly one lock count. + void LoadOggHeaders(); + + // The main loop for the audio thread. Sent to the thread as + // an NS_NEW_RUNNABLE_METHOD. This continually does blocking writes to + // to audio stream to play audio data. + void AudioLoop(); + + // Stop or pause playback of media. This has two modes, denoted by + // aMode being either AUDIO_PAUSE or AUDIO_SHUTDOWN. + // + // AUDIO_PAUSE: Suspends the audio stream to be resumed later. + // This does not close the OS based audio stream + // + // AUDIO_SHUTDOWN: Closes and destroys the audio stream and + // releases any OS resources. + // + // The decoder monitor must be held with exactly one lock count. Called + // on the state machine thread. + enum eStopMode {AUDIO_PAUSE, AUDIO_SHUTDOWN}; + void StopPlayback(eStopMode aMode); + + // Resume playback of media. Must be called with the decode monitor held. + // This resumes a paused audio stream. The decoder monitor must be held with + // exactly one lock count. Called on the state machine thread. + void StartPlayback(); + + // Returns PR_TRUE if we're currently playing. The decoder monitor must + // be held. + PRBool IsPlaying(); + + // Stores presentation info about required for playback of the media. + nsOggInfo mInfo; + + // Monitor on mAudioStream. This monitor must be held in order to delete + // or use the audio stream. This stops us destroying the audio stream + // while it's being used on another thread (typically when it's being + // written to on the audio thread). + Monitor mAudioMonitor; + + // The reader, don't call its methods with the decoder monitor held. + // This is created in the play state machine's constructor, and destroyed + // in the play state machine's destructor. + nsAutoPtr mReader; + + // The size of the decoded YCbCr frame. + // Accessed on state machine thread. + PRUint32 mCbCrSize; + + // Accessed on state machine thread. + nsAutoArrayPtr mCbCrBuffer; + + // Thread for pushing audio onto the audio hardware. + // The "audio push thread". + nsCOMPtr mAudioThread; + + // Thread for decoding video in background. The "decode thread". + nsCOMPtr mDecodeThread; + + // The time that playback started from the system clock. This is used + // for timing the display of audio frames when there's no audio. + // Accessed only via the state machine thread. + TimeStamp mPlayStartTime; + + // The amount of time we've spent playing already the media. The current + // playback position is therefore (mPlayDuration + (now - mPlayStartTime)). + // Accessed only via the state machine thread. + TimeDuration mPlayDuration; + + // Time that buffering started. Used for buffering timeout and only + // accessed on the state machine thread. + TimeStamp mBufferingStart; + + // Download position where we should stop buffering. Only + // accessed on the state machine thread. + PRInt64 mBufferingEndOffset; + + // Start time of the media, in milliseconds. This is the presentation + // time of the first sample decoded from the media, and is used to calculate + // duration and as a bounds for seeking. Accessed on state machine and + // main thread. Access controlled by decoder monitor. + PRInt64 mStartTime; + + // Time of the last page in the media, in milliseconds. This is the + // end time of the last sample in the media. Accessed on state + // machine and main thread. Access controlled by decoder monitor. + PRInt64 mEndTime; + + // Position to seek to in milliseconds when the seek state transition occurs. + // The decoder monitor lock must be obtained before reading or writing + // this value. Accessed on main and state machine thread. + PRInt64 mSeekTime; + + // The audio stream resource. Used on the state machine, audio, and main + // threads. You must hold the mAudioMonitor, and must NOT hold the decoder + // monitor when using the audio stream! + nsAutoPtr mAudioStream; + + // The time of the current frame in milliseconds. This is referenced from + // 0 which is the initial playback position. Set by the state machine + // thread, and read-only from the main thread to get the current + // time value. Synchronised via decoder monitor. + PRInt64 mCurrentFrameTime; + + // The presentation time of the first audio sample that was played. We can + // add this to the audio stream position to determine the current audio time. + // Accessed on audio and state machine thread. Synchronized by decoder monitor. + PRInt64 mAudioStartTime; + + // The end time of the last audio sample that's been pushed onto the audio + // hardware. This will approximately be the end time of the audio stream, + // unless another sample is pushed to the hardware. + PRInt64 mAudioEndTime; + + // The presentation time of the last video frame which has been displayed. + // Accessed from the state machine thread. + PRInt64 mVideoFrameTime; + + // Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written + // from the state machine and main threads. Synchronised via decoder + // monitor. + float mVolume; + + // PR_TRUE if the media resource can be seeked. Accessed from the state + // machine and main threads. Synchronised via decoder monitor. + PRPackedBool mSeekable; + + // PR_TRUE if an event to notify about a change in the playback + // position has been queued, but not yet run. It is set to PR_FALSE when + // the event is run. This allows coalescing of these events as they can be + // produced many times per second. Synchronised via decoder monitor. + // Accessed on main and state machine threads. + PRPackedBool mPositionChangeQueued; + + // PR_TRUE if the audio playback thread has finished. It is finished + // when either all the audio samples in the Vorbis bitstream have completed + // playing, or we've moved into shutdown state, and the threads are to be + // destroyed. Written by the audio playback thread and read and written by + // the state machine thread. Synchronised via decoder monitor. + PRPackedBool mAudioCompleted; + + // PR_TRUE if the decode thread has indicated that we need to buffer. + // Accessed by the decode thread and the state machine thread. + // Synchronised via the decoder monitor. + PRPackedBool mBufferExhausted; + + // PR_TRUE if mDuration has a value obtained from an HTTP header. + // Accessed on the state machine thread. + PRPackedBool mGotDurationFromHeader; + + // PR_FALSE while decode threads should be running. Accessed on audio, + // state machine and decode threads. Syncrhonised by decoder monitor. + PRPackedBool mStopDecodeThreads; +}; + + +#endif diff --git a/content/media/ogg/nsOggReader.cpp b/content/media/ogg/nsOggReader.cpp new file mode 100644 index 000000000000..b65bd0cf066f --- /dev/null +++ b/content/media/ogg/nsOggReader.cpp @@ -0,0 +1,1540 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISeekableStream.h" +#include "nsClassHashtable.h" +#include "nsTArray.h" +#include "nsOggDecoder.h" +#include "nsOggReader.h" +#include "nsOggCodecState.h" +#include "nsOggPlayStateMachine.h" +#include "mozilla/mozalloc.h" +#include "nsOggHacks.h" + +using mozilla::MonitorAutoExit; + +// Un-comment to enable logging of seek bisections. +//#define SEEK_LOGGING + +#ifdef PR_LOGGING +extern PRLogModuleInfo* gOggDecoderLog; +#define LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) +#ifdef SEEK_LOGGING +#define SEEK_LOG(type, msg) PR_LOG(gOggDecoderLog, type, msg) +#else +#define SEEK_LOG(type, msg) +#endif +#else +#define LOG(type, msg) +#define SEEK_LOG(type, msg) +#endif + +// Chunk size to read when reading Ogg files. Average Ogg page length +// is about 4300 bytes, so we read the file in chunks larger than that. +static const int PAGE_STEP = 8192; + +// 32 bit integer multiplication with overflow checking. Returns PR_TRUE +// if the multiplication was successful, or PR_FALSE if the operation resulted +// in an integer overflow. +PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult) { + PRUint64 a64 = a; + PRUint64 b64 = b; + PRUint64 r64 = a64 * b64; + if (r64 > PR_UINT32_MAX) + return PR_FALSE; + aResult = static_cast(r64); + return PR_TRUE; +} + +VideoData* VideoData::Create(PRInt64 aTime, + th_ycbcr_buffer aBuffer, + PRBool aKeyframe, + PRInt64 aGranulepos) +{ + nsAutoPtr v(new VideoData(aTime, aKeyframe, aGranulepos)); + for (PRUint32 i=0; i < 3; ++i) { + PRUint32 size = 0; + if (!MulOverflow32(PR_ABS(aBuffer[i].height), + PR_ABS(aBuffer[i].stride), + size)) + { + // Invalid frame size. Skip this plane. The plane will have 0 + // dimensions, thanks to our constructor. + continue; + } + unsigned char* p = static_cast(moz_xmalloc(size)); + if (!p) { + NS_WARNING("Failed to allocate memory for video frame"); + return nsnull; + } + v->mBuffer[i].data = p; + v->mBuffer[i].width = aBuffer[i].width; + v->mBuffer[i].height = aBuffer[i].height; + v->mBuffer[i].stride = aBuffer[i].stride; + memcpy(v->mBuffer[i].data, aBuffer[i].data, size); + } + return v.forget(); +} + +nsOggReader::nsOggReader(nsOggPlayStateMachine* aStateMachine) + : mMonitor("media.oggreader"), + mPlayer(aStateMachine), + mTheoraState(nsnull), + mVorbisState(nsnull), + mPageOffset(0), + mDataOffset(0), + mTheoraGranulepos(-1), + mVorbisGranulepos(-1), + mCallbackPeriod(0) +{ + MOZ_COUNT_CTOR(nsOggReader); +} + +nsOggReader::~nsOggReader() +{ + ResetDecode(); + ogg_sync_clear(&mOggState); + MOZ_COUNT_DTOR(nsOggReader); +} + +nsresult nsOggReader::Init() { + PRBool init = mCodecStates.Init(); + NS_ASSERTION(init, "Failed to initialize mCodecStates"); + if (!init) { + return NS_ERROR_FAILURE; + } + int ret = ogg_sync_init(&mOggState); + NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); + return NS_OK; +} + +nsresult nsOggReader::ResetDecode() +{ + nsresult res = NS_OK; + + // Clear the Theora/Vorbis granulepos capture status, so that the next + // decode calls recaptures the granulepos. + mTheoraGranulepos = -1; + mVorbisGranulepos = -1; + + mVideoQueue.Reset(); + mAudioQueue.Reset(); + + MonitorAutoEnter mon(mMonitor); + + // Discard any previously buffered packets/pages. + ogg_sync_reset(&mOggState); + if (mVorbisState && NS_FAILED(mVorbisState->Reset())) { + res = NS_ERROR_FAILURE; + } + if (mTheoraState && NS_FAILED(mTheoraState->Reset())) { + res = NS_ERROR_FAILURE; + } + + return res; +} + +nsresult nsOggReader::DecodeVorbis(nsTArray& aChunks, + ogg_packet* aPacket) +{ + // Successfully read a packet. + if (vorbis_synthesis(&mVorbisState->mBlock, aPacket) != 0) { + return NS_ERROR_FAILURE; + } + if (vorbis_synthesis_blockin(&mVorbisState->mDsp, + &mVorbisState->mBlock) != 0) + { + return NS_ERROR_FAILURE; + } + + float** pcm = 0; + PRUint32 samples = 0; + PRUint32 channels = mVorbisState->mInfo.channels; + while ((samples = vorbis_synthesis_pcmout(&mVorbisState->mDsp, &pcm)) > 0) { + if (samples > 0) { + float* buffer = new float[samples * channels]; + float* p = buffer; + for (PRUint32 i = 0; i < samples; ++i) { + for (PRUint32 j = 0; j < channels; ++j) { + *p++ = pcm[j][i]; + } + } + + PRInt64 duration = mVorbisState->Time((PRInt64)samples); + PRInt64 startTime = (mVorbisGranulepos != -1) ? + mVorbisState->Time(mVorbisGranulepos) : -1; + SoundData* s = new SoundData(startTime, + duration, + samples, + buffer, + channels); + if (mVorbisGranulepos != -1) { + mVorbisGranulepos += samples; + } + aChunks.AppendElement(s); + } + if (vorbis_synthesis_read(&mVorbisState->mDsp, samples) != 0) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +// Decode page, calculate timestamps. +PRBool nsOggReader::DecodeAudioPage() +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on playback or decode thread."); + NS_ASSERTION(mVorbisState!=0, "Need Vorbis state to decode audio"); + ogg_packet packet; + packet.granulepos = -1; + + PRBool endOfStream = PR_FALSE; + + nsAutoTArray chunks; + if (mVorbisGranulepos == -1) { + // Not captured Vorbis granulepos, read up until we get a granulepos, and + // back propagate the granulepos. + + // We buffer the packets' pcm samples until we reach a packet with a granulepos. + // This will be the last packet in a page. Then using that granulepos to + // calculate the packet's end time, we calculate all the packets' start times by + // subtracting their durations. + + // Ensure we've got Vorbis packets; read one more Vorbis page if necessary. + while (packet.granulepos <= 0 && !endOfStream) { + if (!ReadOggPacket(mVorbisState, &packet)) { + endOfStream = PR_TRUE; + break; + } + if (packet.e_o_s != 0) { + // This packet marks the logical end of the Vorbis bitstream. It may + // still contain sound samples, so we must still decode it. + endOfStream = PR_TRUE; + } + + if (NS_FAILED(DecodeVorbis(chunks, &packet))) { + NS_WARNING("Failed to decode Vorbis packet"); + } + } + + if (packet.granulepos > 0) { + // Successfully read up to a non -1 granulepos. + // Calculate the timestamps of the sound samples. + PRInt64 granulepos = packet.granulepos; // Represents end time of last sample. + mVorbisGranulepos = packet.granulepos; + for (int i = chunks.Length() - 1; i >= 0; --i) { + SoundData* s = chunks[i]; + PRInt64 startGranule = granulepos - s->mSamples; + s->mTime = mVorbisState->Time(startGranule); + granulepos = startGranule; + } + } + } else { + // We have already captured the granulepos. The next packet's granulepos + // is its number of samples, plus the previous granulepos. + if (!ReadOggPacket(mVorbisState, &packet)) { + endOfStream = PR_TRUE; + } else { + // Successfully read a packet from the file. Decode it. + endOfStream = packet.e_o_s != 0; + + // Try to decode any packet we've read. + if (NS_FAILED(DecodeVorbis(chunks, &packet))) { + NS_WARNING("Failed to decode Vorbis packet"); + } + + if (packet.granulepos != -1 && packet.granulepos != mVorbisGranulepos) { + // If the packet's granulepos doesn't match our running sample total, + // it's likely the bitstream has been damaged somehow, or perhaps + // oggz-chopped. Just assume the packet's granulepos is correct... + mVorbisGranulepos = packet.granulepos; + } + } + } + + // We've successfully decoded some sound chunks. Push them onto the audio + // queue. + for (PRUint32 i = 0; i < chunks.Length(); ++i) { + mAudioQueue.Push(chunks[i]); + } + + if (endOfStream) { + // We've encountered an end of bitstream packet, or we've hit the end of + // file while trying to decode, so inform the audio queue that there'll + // be no more samples. + mAudioQueue.Finish(); + return PR_FALSE; + } + + return PR_TRUE; +} + +// Returns 1 if the Theora info struct is decoding a media of Theora +// verion (maj,min,sub) or later, otherwise returns 0. +static int +TheoraVersion(th_info* info, + unsigned char maj, + unsigned char min, + unsigned char sub) +{ + ogg_uint32_t ver = (maj << 16) + (min << 8) + sub; + ogg_uint32_t th_ver = (info->version_major << 16) + + (info->version_minor << 8) + + info->version_subminor; + return (th_ver >= ver) ? 1 : 0; +} + +// Ensures that all the VideoData in aFrames array are stored in increasing +// order by timestamp. Used in assertions in debug builds. +static PRBool +AllFrameTimesIncrease(nsTArray& aFrames) +{ + PRInt64 prevTime = -1; + PRInt64 prevGranulepos = -1; + for (PRUint32 i = 0; i < aFrames.Length(); i++) { + VideoData* f = aFrames[i]; + if (f->mTime < prevTime) { + return PR_FALSE; + } + prevTime = f->mTime; + prevGranulepos = f->mGranulepos; + } + return PR_TRUE; +} + +static void Clear(nsTArray& aFrames) { + for (PRUint32 i = 0; i < aFrames.Length(); ++i) { + delete aFrames[i]; + } + aFrames.Clear(); +} + +nsresult nsOggReader::DecodeTheora(nsTArray& aFrames, + ogg_packet* aPacket) +{ + int ret = th_decode_packetin(mTheoraState->mCtx, aPacket, 0); + if (ret != 0 && ret != TH_DUPFRAME) { + return NS_ERROR_FAILURE; + } + PRInt64 time = (aPacket->granulepos != -1) + ? mTheoraState->StartTime(aPacket->granulepos) : -1; + if (ret == TH_DUPFRAME) { + aFrames.AppendElement(VideoData::CreateDuplicate(time, + aPacket->granulepos)); + } else if (ret == 0) { + th_ycbcr_buffer buffer; + ret = th_decode_ycbcr_out(mTheoraState->mCtx, buffer); + NS_ASSERTION(ret == 0, "th_decode_ycbcr_out failed"); + PRBool isKeyframe = th_packet_iskeyframe(aPacket) == 1; + VideoData *v = VideoData::Create(time, + buffer, + isKeyframe, + aPacket->granulepos); + if (!v) { + NS_WARNING("Failed to allocate memory for video frame"); + Clear(aFrames); + return NS_ERROR_OUT_OF_MEMORY; + } + aFrames.AppendElement(v); + } + return NS_OK; +} + +PRBool nsOggReader::DecodeVideoPage(PRBool &aKeyframeSkip, + PRInt64 aTimeThreshold) +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on state machine or AV thread."); + // We chose to keep track of the Theora granulepos ourselves, rather than + // rely on th_decode_packetin() to do it for us. This is because + // th_decode_packetin() simply works by incrementing a counter every time + // it's called, so if we drop frames and don't call it, subsequent granulepos + // will be wrong. Whenever we read a packet which has a granulepos, we use + // its granulepos, otherwise we increment the previous packet's granulepos. + + nsAutoTArray frames; + ogg_packet packet; + PRBool endOfStream = PR_FALSE; + if (mTheoraGranulepos == -1) { + // We've not read a Theora packet with a granulepos, so we don't know what + // timestamp to assign to Theora frames we decode. This will only happen + // the first time we read, or after a seek. We must read and buffer up to + // the first Theora packet with a granulepos, and back-propagate its + // granulepos to calculate the buffered frames' granulepos. + do { + if (!ReadOggPacket(mTheoraState, &packet)) { + // Failed to read another page, must be the end of file. We can't have + // already encountered an end of bitstream packet, else we wouldn't be + // here, so this bitstream must be missing its end of stream packet, or + // is otherwise corrupt (oggz-chop can output files like this). Inform + // the queue that there will be no more frames. + mVideoQueue.Finish(); + return PR_FALSE; + } + + if (packet.granulepos > 0) { + // We've found a packet with a granulepos, we can now determine the + // buffered packet's timestamps, as well as the timestamps for any + // packets we read subsequently. + mTheoraGranulepos = packet.granulepos; + } + + if (DecodeTheora(frames, &packet) == NS_ERROR_OUT_OF_MEMORY) { + NS_WARNING("Theora decode memory allocation failure!"); + return PR_FALSE; + } + + } while (packet.granulepos <= 0 && !endOfStream); + + if (packet.granulepos > 0) { + // We have captured a granulepos. Backpropagate the granulepos + // to determine buffered packets' timestamps. + PRInt64 succGranulepos = packet.granulepos; + int version_3_2_1 = TheoraVersion(&mTheoraState->mInfo,3,2,1); + int shift = mTheoraState->mInfo.keyframe_granule_shift; + for (int i = frames.Length() - 2; i >= 0; --i) { + PRInt64 granulepos = succGranulepos; + if (frames[i]->mKeyframe) { + // This frame is a keyframe. It's granulepos is the previous granule + // number minus 1, shifted by granuleshift. + ogg_int64_t frame_index = th_granule_frame(mTheoraState->mCtx, + granulepos); + granulepos = (frame_index + version_3_2_1 - 1) << shift; + // Theora 3.2.1+ granulepos store frame number [1..N], so granulepos + // should be > 0. + // Theora 3.2.0 granulepos store the frame index [0..(N-1)], so + // granulepos should be >= 0. + NS_ASSERTION((version_3_2_1 && granulepos > 0) || + granulepos >= 0, "Should have positive granulepos"); + } else { + // Packet is not a keyframe. It's granulepos depends on its successor + // packet... + if (frames[i+1]->mKeyframe) { + // The successor frame is a keyframe, so we can't just subtract 1 + // from the "keyframe offset" part of its granulepos, as it + // doesn't have one! So fake it, take the keyframe offset as the + // max possible keyframe offset. This means the granulepos (probably) + // overshoots and claims that it depends on a frame before its actual + // keyframe but at least its granule number will be correct, so the + // times we calculate from this granulepos will also be correct. + ogg_int64_t frameno = th_granule_frame(mTheoraState->mCtx, + granulepos); + ogg_int64_t max_offset = NS_MIN((frameno - 1), + (ogg_int64_t)(1 << shift) - 1); + ogg_int64_t granule = frameno + + TheoraVersion(&mTheoraState->mInfo,3,2,1) - + 1 - max_offset; + NS_ASSERTION(granule > 0, "Must have positive granulepos"); + granulepos = (granule << shift) + max_offset; + } else { + // Neither previous nor this frame are keyframes, so we can just + // decrement the previous granulepos to calculate this frames + // granulepos. + --granulepos; + } + } + // Check that the frame's granule number (it's frame number) is + // one less than the successor frame. + NS_ASSERTION(th_granule_frame(mTheoraState->mCtx, succGranulepos) == + th_granule_frame(mTheoraState->mCtx, granulepos) + 1, + "Granulepos calculation is incorrect!"); + frames[i]->mTime = mTheoraState->StartTime(granulepos); + frames[i]->mGranulepos = granulepos; + succGranulepos = granulepos; + NS_ASSERTION(frames[i]->mTime < frames[i+1]->mTime, "Times should increase"); + } + NS_ASSERTION(AllFrameTimesIncrease(frames), "All frames must have granulepos"); + } + } else { + + NS_ASSERTION(mTheoraGranulepos > 0, "We must Theora granulepos!"); + + if (!ReadOggPacket(mTheoraState, &packet)) { + // Failed to read from file, so EOF or other premature failure. + // Inform the queue that there will be no more frames. + mVideoQueue.Finish(); + return PR_FALSE; + } + + endOfStream = packet.e_o_s != 0; + + // Maintain the Theora granulepos. We must do this even if we drop frames, + // otherwise our clock will be wrong after we've skipped frames. + if (packet.granulepos != -1) { + // Incoming packet has a granulepos, use that as it's granulepos. + mTheoraGranulepos = packet.granulepos; + } else { + // Increment the previous Theora granulepos. + PRInt64 granulepos = 0; + int shift = mTheoraState->mInfo.keyframe_granule_shift; + // Theora 3.2.1+ bitstreams granulepos store frame number; [1..N] + // Theora 3.2.0 bitstreams store the frame index; [0..(N-1)] + if (!th_packet_iskeyframe(&packet)) { + granulepos = mTheoraGranulepos + 1; + } else { + ogg_int64_t frameindex = th_granule_frame(mTheoraState->mCtx, + mTheoraGranulepos); + ogg_int64_t granule = frameindex + + TheoraVersion(&mTheoraState->mInfo,3,2,1) + 1; + NS_ASSERTION(granule > 0, "Must have positive granulepos"); + granulepos = granule << shift; + } + + NS_ASSERTION(th_granule_frame(mTheoraState->mCtx, mTheoraGranulepos) + 1 == + th_granule_frame(mTheoraState->mCtx, granulepos), + "Frame number must increment by 1"); + packet.granulepos = mTheoraGranulepos = granulepos; + } + + PRInt64 time = mTheoraState->StartTime(mTheoraGranulepos); + NS_ASSERTION(packet.granulepos != -1, "Must know packet granulepos"); + if (!aKeyframeSkip || + (th_packet_iskeyframe(&packet) == 1 && time >= aTimeThreshold)) + { + if (DecodeTheora(frames, &packet) == NS_ERROR_OUT_OF_MEMORY) { + NS_WARNING("Theora decode memory allocation failure"); + return PR_FALSE; + } + } + } + + // Push decoded data into the video frame queue. + for (PRUint32 i = 0; i < frames.Length(); i++) { + nsAutoPtr data(frames[i]); + if (!aKeyframeSkip || (aKeyframeSkip && frames[i]->mKeyframe)) { + mVideoQueue.Push(data.forget()); + if (aKeyframeSkip && frames[i]->mKeyframe) { + aKeyframeSkip = PR_FALSE; + } + } else { + frames[i] = nsnull; + data = nsnull; + } + } + + if (endOfStream) { + // We've encountered an end of bitstream packet. Inform the queue that + // there will be no more frames. + mVideoQueue.Finish(); + } + + return !endOfStream; +} + +nsresult nsOggReader::GetBufferedBytes(nsTArray& aRanges) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + mMonitor.AssertCurrentThreadIn(); + PRInt64 startOffset = mDataOffset; + nsMediaStream* stream = mPlayer->mDecoder->mStream; + while (PR_TRUE) { + PRInt64 endOffset = stream->GetCachedDataEnd(startOffset); + if (endOffset == startOffset) { + // Uncached at startOffset. + endOffset = stream->GetNextCachedData(startOffset); + if (endOffset == -1) { + // Uncached at startOffset until endOffset of stream, or we're at + // the end of stream. + break; + } + } else { + // Bytes [startOffset..endOffset] are cached. + PRInt64 startTime = -1; + PRInt64 endTime = -1; + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + FindStartTime(startOffset, startTime); + if (startTime != -1 && + (endTime = FindEndTime(endOffset) != -1)) + { + aRanges.AppendElement(ByteRange(startOffset, + endOffset, + startTime, + endTime)); + } + } + startOffset = endOffset; + } + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +ByteRange +nsOggReader::GetSeekRange(const nsTArray& ranges, + PRInt64 aTarget, + PRInt64 aStartTime, + PRInt64 aEndTime, + PRBool aExact) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + PRInt64 so = mDataOffset; + PRInt64 eo = mPlayer->mDecoder->mStream->GetLength(); + PRInt64 st = aStartTime; + PRInt64 et = aEndTime; + for (PRUint32 i = 0; i < ranges.Length(); i++) { + const ByteRange &r = ranges[i]; + if (r.mTimeStart < aTarget) { + so = r.mOffsetStart; + st = r.mTimeStart; + } + if (r.mTimeEnd >= aTarget && r.mTimeEnd < et) { + eo = r.mOffsetEnd; + et = r.mTimeEnd; + } + + if (r.mTimeStart < aTarget && aTarget <= r.mTimeEnd) { + // Target lies exactly in this range. + return ranges[i]; + } + } + return aExact ? ByteRange() : ByteRange(so, eo, st, et); +} + +nsresult nsOggReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTime) +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mPlayer->mDecoder, aTarget)); + nsMediaStream* stream = mPlayer->mDecoder->mStream; + + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + if (aTarget == aStartTime) { + stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset); + mPageOffset = mDataOffset; + NS_ASSERTION(aStartTime != -1, "mStartTime should be known"); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + mPlayer->UpdatePlaybackPosition(aStartTime); + } + } else { + + // Determine the already downloaded data in the media cache. + nsAutoTArray ranges; + stream->Pin(); + if (NS_FAILED(GetBufferedBytes(ranges))) { + stream->Unpin(); + return NS_ERROR_FAILURE; + } + + // Try to seek in the cached data ranges first, before falling back to + // seeking over the network. This makes seeking in buffered ranges almost + // instantaneous. + ByteRange r = GetSeekRange(ranges, aTarget, aStartTime, aEndTime, PR_TRUE); + nsresult res = NS_ERROR_FAILURE; + if (!r.IsNull()) { + // The frame should be in this buffered range. Seek exactly there. + res = SeekBisection(aTarget, r, 0); + + if (NS_SUCCEEDED(res) && HasVideo()) { + // We have an active Theora bitstream. Decode the next Theora frame, and + // extract its keyframe's time. + PRBool eof; + do { + PRBool skip = PR_FALSE; + eof = !DecodeVideoPage(skip, 0); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + stream->Unpin(); + return NS_ERROR_FAILURE; + } + } + } while (!eof && + mVideoQueue.GetSize() == 0); + + VideoData* video = mVideoQueue.PeekFront(); + if (video && !video->mKeyframe) { + // First decoded frame isn't a keyframe, seek back to previous keyframe, + // otherwise we'll get visual artifacts. + NS_ASSERTION(video->mGranulepos != -1, "Must have a granulepos"); + int shift = mTheoraState->mInfo.keyframe_granule_shift; + PRInt64 keyframeGranulepos = (video->mGranulepos >> shift) << shift; + PRInt64 keyframeTime = mTheoraState->StartTime(keyframeGranulepos); + + SEEK_LOG(PR_LOG_DEBUG, ("Keyframe for %lld is at %lld, seeking back to it", + video->mTime, keyframeTime)); + ByteRange k = GetSeekRange(ranges, + keyframeTime, + aStartTime, + aEndTime, + PR_FALSE); + res = SeekBisection(keyframeTime, k, 500); + NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode"); + NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode"); + } + } + } + + stream->Unpin(); + + if (NS_FAILED(res)) { + // We failed to find the seek target (or perhaps its keyframe, somehow?) + // in a buffered range. Minimize the bisection search space using the + // buffered ranges, and perform a bisection search. + + // If we've got an active Theora bitstream, determine the maximum possible + // time in ms which a keyframe could be before a given interframe. We + // subtract this from our seek target, seek to the new target, and then + // decode forwards to the original seek target. We should encounter a + // keyframe in that interval. This prevents us from needing to run two + // bisections; one for the seek target frame, and another to find its + // keyframe. It's usually faster to just download this extra data, rather + // tham perform two bisections to find the seek target's keyframe. We + // don't do this offsetting when seeking in a buffered ranges (above), + // as the extra decoding causes a noticable speed hit when all the data + // is buffered. + PRInt64 keyframeOffsetMs = 0; + if (HasVideo() && mTheoraState) { + keyframeOffsetMs = mTheoraState->MaxKeyframeOffset(); + } + PRInt64 seekTarget = NS_MAX(aStartTime, aTarget - keyframeOffsetMs); + + ByteRange k = GetSeekRange(ranges, seekTarget, aStartTime, aEndTime, PR_FALSE); + res = SeekBisection(seekTarget, k, 500); + + NS_ENSURE_SUCCESS(res, res); + NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode"); + NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode"); + } + } + + // Decode forward to the seek target frame. Start with video, if we have it. + // We should pass a keyframe while doing this. + if (HasVideo()) { + nsAutoPtr video; + PRBool eof = PR_FALSE; + PRInt64 startTime = -1; + video = nsnull; + while (HasVideo() && !eof) { + while (mVideoQueue.GetSize() == 0 && !eof) { + PRBool skip = PR_FALSE; + eof = !DecodeVideoPage(skip, 0); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return NS_ERROR_FAILURE; + } + } + } + if (mVideoQueue.GetSize() == 0) { + break; + } + video = mVideoQueue.PeekFront(); + // If the frame end time is less than the seek target, we won't want + // to display this frame after the seek, so discard it. + if (video && video->mTime + mCallbackPeriod < aTarget) { + if (startTime == -1) { + startTime = video->mTime; + } + mVideoQueue.PopFront(); + video = nsnull; + } else { + video.forget(); + break; + } + } + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return NS_ERROR_FAILURE; + } + } + SEEK_LOG(PR_LOG_DEBUG, ("First video frame after decode is %lld", startTime)); + } + + if (HasAudio()) { + // Decode audio forward to the seek target. + nsAutoPtr audio; + bool eof = PR_FALSE; + while (HasAudio() && !eof) { + while (!eof && mAudioQueue.GetSize() == 0) { + eof = !DecodeAudioPage(); + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return NS_ERROR_FAILURE; + } + } + } + audio = mAudioQueue.PeekFront(); + if (audio && audio->mTime + audio->mDuration <= aTarget) { + mAudioQueue.PopFront(); + audio = nsnull; + } else { + audio.forget(); + break; + } + } + } + + return NS_OK; +} + +enum PageSyncResult { + PAGE_SYNC_ERROR = 1, + PAGE_SYNC_END_OF_RANGE= 2, + PAGE_SYNC_OK = 3 +}; + +// Reads a page from the media stream. +static PageSyncResult +PageSync(ogg_sync_state* aState, + nsMediaStream* aStream, + PRInt64 aEndOffset, + ogg_page* aPage, + int& aSkippedBytes) +{ + aSkippedBytes = 0; + // Sync to the next page. + int ret = 0; + PRUint32 bytesRead = 0; + while (ret <= 0) { + ret = ogg_sync_pageseek(aState, aPage); + if (ret == 0) { + char* buffer = ogg_sync_buffer(aState, PAGE_STEP); + NS_ASSERTION(buffer, "Must have a buffer"); + + // Read from the file into the buffer + PRInt64 bytesToRead = NS_MIN(static_cast(PAGE_STEP), + aEndOffset - aStream->Tell()); + if (bytesToRead <= 0) { + return PAGE_SYNC_END_OF_RANGE; + } + nsresult rv = aStream->Read(buffer, + static_cast(bytesToRead), + &bytesRead); + if (NS_FAILED(rv)) { + return PAGE_SYNC_ERROR; + } + + if (bytesRead == 0 && NS_SUCCEEDED(rv)) { + // End of file. + return PAGE_SYNC_END_OF_RANGE; + } + + // Update the synchronisation layer with the number + // of bytes written to the buffer + ret = ogg_sync_wrote(aState, bytesRead); + NS_ENSURE_TRUE(ret == 0, PAGE_SYNC_ERROR); + continue; + } + + if (ret < 0) { + NS_ASSERTION(aSkippedBytes >= 0, "Offset >= 0"); + aSkippedBytes += -ret; + NS_ASSERTION(aSkippedBytes >= 0, "Offset >= 0"); + continue; + } + } + + return PAGE_SYNC_OK; +} + +nsresult nsOggReader::SeekBisection(PRInt64 aTarget, + const ByteRange& aRange, + PRUint32 aFuzz) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), + "Should be on state machine thread."); + nsMediaStream* stream = mPlayer->mDecoder->mStream; + + if (aTarget == aRange.mTimeStart) { + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + stream->Seek(nsISeekableStream::NS_SEEK_SET, mDataOffset); + mPageOffset = mDataOffset; + return NS_OK; + } + + // Bisection search, find start offset of last page with end time less than + // the seek target. + ogg_int64_t startOffset = aRange.mOffsetStart; + ogg_int64_t startTime = aRange.mTimeStart; + ogg_int64_t startLength = 0; + ogg_int64_t endOffset = aRange.mOffsetEnd; + ogg_int64_t endTime = aRange.mTimeEnd; + + ogg_int64_t seekTarget = aTarget; + PRInt64 seekLowerBound = NS_MAX(static_cast(0), aTarget - aFuzz); + int hops = 0; + ogg_int64_t previousGuess = -1; + int backsteps = 1; + const int maxBackStep = 10; + NS_ASSERTION(static_cast(PAGE_STEP) * pow(2.0, maxBackStep) < PR_INT32_MAX, + "Backstep calculation must not overflow"); + while (PR_TRUE) { + ogg_int64_t duration = 0; + double target = 0; + ogg_int64_t interval = 0; + ogg_int64_t guess = 0; + ogg_page page; + int skippedBytes = 0; + ogg_int64_t pageOffset = 0; + ogg_int64_t pageLength = 0; + int backoff = 0; + ogg_int64_t granuleTime = -1; + PRInt64 oldPageOffset = 0; + + // Guess where we should bisect to, based on the bit rate and the time + // remaining in the interval. + while (PR_TRUE) { + + // Discard any previously buffered packets/pages. + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + + // Guess bisection point. + duration = endTime - startTime; + target = (double)(seekTarget - startTime) / (double)duration; + interval = endOffset - startOffset - startLength; + guess = startOffset + startLength + + (ogg_int64_t)((double)interval * target) - backoff; + guess = NS_MIN(guess, endOffset - PAGE_STEP); + guess = NS_MAX(guess, startOffset + startLength); + + if (interval == 0 || guess == previousGuess) { + interval = 0; + // Our interval is empty, we've found the optimal seek point, as the + // start page is before the seek target, and the end page after the + // seek target. + break; + } + + NS_ASSERTION(guess >= startOffset + startLength, "Guess must be after range start"); + NS_ASSERTION(guess < endOffset, "Guess must be before range end"); + NS_ASSERTION(guess != previousGuess, "Guess should be differnt to previous"); + previousGuess = guess; + + SEEK_LOG(PR_LOG_DEBUG, ("Seek loop offset_start=%lld start_end=%lld " + "offset_guess=%lld offset_end=%lld interval=%lld " + "target=%lf time_start=%lld time_end=%lld", + startOffset, (startOffset+startLength), guess, + endOffset, interval, target, startTime, endTime)); + hops++; + stream->Seek(nsISeekableStream::NS_SEEK_SET, guess); + + // We've seeked into the media somewhere. Locate the next page, and then + // figure out the granule time of the audio and video bitstreams there. + // We can then make a bisection decision based on our location in the media. + + PageSyncResult res = PageSync(&mOggState, + stream, + endOffset, + &page, + skippedBytes); + if (res == PAGE_SYNC_ERROR) { + return NS_ERROR_FAILURE; + } + + // We've located a page of length |ret| at |guess + skippedBytes|. + // Remember where the page is located. + pageOffset = guess + skippedBytes; + pageLength = page.header_len + page.body_len; + mPageOffset = pageOffset + pageLength; + + if (mPageOffset == endOffset || res == PAGE_SYNC_END_OF_RANGE) { + // Our guess was too close to the end, we've ended up reading the end + // page. Backoff exponentially from the end point, in case the last + // page/frame/sample is huge. + backsteps = NS_MIN(backsteps + 1, maxBackStep); + backoff = PAGE_STEP * pow(2.0, backsteps); + continue; + } + + NS_ASSERTION(mPageOffset < endOffset, "Page read cursor should be inside range"); + + // Read pages until we can determine the granule time of the audio and + // video bitstream. + ogg_int64_t audioTime = -1; + ogg_int64_t videoTime = -1; + int ret; + oldPageOffset = mPageOffset; + while ((mVorbisState && audioTime == -1) || + (mTheoraState && videoTime == -1)) { + + // Add the page to its codec state, determine its granule time. + PRUint32 serial = ogg_page_serialno(&page); + nsOggCodecState* codecState = nsnull; + mCodecStates.Get(serial, &codecState); + if (codecState && codecState->mActive) { + ret = ogg_stream_pagein(&codecState->mState, &page); + NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); + } + + ogg_int64_t granulepos = ogg_page_granulepos(&page); + + if (HasAudio() && + granulepos != -1 && + serial == mVorbisState->mSerial && + audioTime == -1) { + audioTime = mVorbisState->Time(granulepos); + } + + if (HasVideo() && + granulepos != -1 && + serial == mTheoraState->mSerial && + videoTime == -1) { + videoTime = mTheoraState->StartTime(granulepos); + } + + mPageOffset += page.header_len + page.body_len; + if (ReadOggPage(&page) == -1) { + break; + } + } + + if ((HasAudio() && audioTime == -1) || + (HasVideo() && videoTime == -1)) + { + backsteps = NS_MIN(backsteps + 1, maxBackStep); + backoff = PAGE_STEP * pow(2.0, backsteps); + continue; + } + + // We've found appropriate time stamps here. Proceed to bisect + // the search space. + granuleTime = NS_MAX(audioTime, videoTime); + NS_ASSERTION(granuleTime > 0, "Must get a granuletime"); + break; + } + + if (interval == 0) { + // Seek termination condition; we've found the page boundary of the + // last page before the target, and the first page after the target. + SEEK_LOG(PR_LOG_DEBUG, ("Seek loop (interval == 0) break")); + NS_ASSERTION(startTime < aTarget, "Start time must always be less than target"); + stream->Seek(nsISeekableStream::NS_SEEK_SET, startOffset); + mPageOffset = startOffset; + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + break; + } + + SEEK_LOG(PR_LOG_DEBUG, ("Time at offset %lld is %lldms", guess, granuleTime)); + if (granuleTime < seekTarget && granuleTime > seekLowerBound) { + // We're within the fuzzy region in which we want to terminate the search. + stream->Seek(nsISeekableStream::NS_SEEK_SET, oldPageOffset); + mPageOffset = oldPageOffset; + if (NS_FAILED(ResetDecode())) { + return NS_ERROR_FAILURE; + } + break; + } + + if (granuleTime >= seekTarget) { + // We've landed after the seek target. + ogg_int64_t old_offset_end = endOffset; + endOffset = pageOffset; + NS_ASSERTION(endOffset < old_offset_end, "offset_end must decrease"); + endTime = granuleTime; + } else if (granuleTime < seekTarget) { + // Landed before seek target. + ogg_int64_t old_offset_start = startOffset; + startOffset = pageOffset; + startLength = pageLength; + NS_ASSERTION(startOffset > old_offset_start, "offset_start must increase"); + startTime = granuleTime; + } + NS_ASSERTION(startTime < seekTarget, "Must be before seek target"); + NS_ASSERTION(endTime >= seekTarget, "End must be after seek target"); + } + + SEEK_LOG(PR_LOG_DEBUG, ("Seek complete in %d bisections.", hops)); + + return NS_OK; +} + +PRInt64 nsOggReader::ReadOggPage(ogg_page* aPage) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on play state machine or decode thread."); + mMonitor.AssertCurrentThreadIn(); + + int ret = 0; + while((ret = ogg_sync_pageseek(&mOggState, aPage)) <= 0) { + if (ret < 0) { + // Lost page sync, have to skip up to next page. + mPageOffset += -ret; + continue; + } + // Returns a buffer that can be written too + // with the given size. This buffer is stored + // in the ogg synchronisation structure. + char* buffer = ogg_sync_buffer(&mOggState, 4096); + NS_ASSERTION(buffer, "ogg_sync_buffer failed"); + + // Read from the stream into the buffer + PRUint32 bytesRead = 0; + + nsresult rv = mPlayer->mDecoder->mStream->Read(buffer, 4096, &bytesRead); + if (NS_FAILED(rv) || (bytesRead == 0 && ret == 0)) { + // End of file. + return -1; + } + + mPlayer->mDecoder->NotifyBytesConsumed(bytesRead); + // Update the synchronisation layer with the number + // of bytes written to the buffer + ret = ogg_sync_wrote(&mOggState, bytesRead); + NS_ENSURE_TRUE(ret == 0, -1); + } + PRInt64 offset = mPageOffset; + mPageOffset += aPage->header_len + aPage->body_len; + + return offset; +} + +PRBool nsOggReader::ReadOggPacket(nsOggCodecState* aCodecState, + ogg_packet* aPacket) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread() || mPlayer->OnDecodeThread(), + "Should be on play state machine or decode thread."); + mMonitor.AssertCurrentThreadIn(); + + if (!aCodecState || !aCodecState->mActive) { + return PR_FALSE; + } + + int ret = 0; + while ((ret = ogg_stream_packetout(&aCodecState->mState, aPacket)) != 1) { + ogg_page page; + + if (aCodecState->PageInFromBuffer()) { + // The codec state has inserted a previously buffered page into its + // ogg_stream_state, no need to read a page from the channel. + continue; + } + + // The codec state does not have any buffered pages, so try to read another + // page from the channel. + if (ReadOggPage(&page) == -1) { + return PR_FALSE; + } + + PRUint32 serial = ogg_page_serialno(&page); + nsOggCodecState* codecState = nsnull; + mCodecStates.Get(serial, &codecState); + + if (serial == aCodecState->mSerial) { + // This page is from our target bitstream, insert it into the + // codec state's ogg_stream_state so we can read a packet. + ret = ogg_stream_pagein(&codecState->mState, &page); + NS_ENSURE_TRUE(ret == 0, PR_FALSE); + } else if (codecState && codecState->mActive) { + // Page is for another active bitstream, add the page to its codec + // state's buffer for later consumption when that stream next tries + // to read a packet. + codecState->AddToBuffer(&page); + } + } + + return PR_TRUE; +} + +// Returns PR_TRUE when all bitstreams in aBitstreams array have finished +// reading their headers. +static PRBool DoneReadingHeaders(nsTArray& aBitstreams) { + for (PRUint32 i = 0; i < aBitstreams .Length(); i++) { + if (!aBitstreams [i]->DoneReadingHeaders()) { + return PR_FALSE; + } + } + return PR_TRUE; +} + +nsresult nsOggReader::ReadOggHeaders(nsOggInfo& aInfo) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), "Should be on play state machine thread."); + MonitorAutoEnter mon(mMonitor); + + // We read packets until all bitstreams have read all their header packets. + // We record the offset of the first non-header page so that we know + // what page to seek to when seeking to the media start. + + ogg_page page; + PRInt64 pageOffset; + nsAutoTArray bitstreams; + PRBool readAllBOS = PR_FALSE; + mDataOffset = 0; + while (PR_TRUE) { + if (readAllBOS && DoneReadingHeaders(bitstreams)) { + if (mDataOffset == 0) { + // We've previously found the start of the first non-header packet. + mDataOffset = mPageOffset; + } + break; + } + pageOffset = ReadOggPage(&page); + if (pageOffset == -1) { + // Some kind of error... + break; + } + + int ret = 0; + int serial = ogg_page_serialno(&page); + nsOggCodecState* codecState = 0; + + if (ogg_page_bos(&page)) { + NS_ASSERTION(!readAllBOS, "We shouldn't encounter another BOS page"); + codecState = nsOggCodecState::Create(&page); + PRBool r = mCodecStates.Put(serial, codecState); + NS_ASSERTION(r, "Failed to insert into mCodecStates"); + bitstreams.AppendElement(codecState); + if (codecState && + codecState->GetType() == nsOggCodecState::TYPE_VORBIS && + !mVorbisState) + { + // First Vorbis bitstream, we'll play this one. Subsequent Vorbis + // bitstreams will be ignored. + mVorbisState = static_cast(codecState); + } + if (codecState && + codecState->GetType() == nsOggCodecState::TYPE_THEORA && + !mTheoraState) + { + // First Theora bitstream, we'll play this one. Subsequent Theora + // bitstreams will be ignored. + mTheoraState = static_cast(codecState); + } + } else { + // We've encountered the a non Beginning Of Stream page. No more + // BOS pages can follow in this Ogg segment, so there will be no other + // bitstreams in the Ogg (unless it's invalid). + readAllBOS = PR_TRUE; + } + + mCodecStates.Get(serial, &codecState); + NS_ENSURE_TRUE(codecState, NS_ERROR_FAILURE); + + // Add a complete page to the bitstream + ret = ogg_stream_pagein(&codecState->mState, &page); + NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); + + // Process all available header packets in the stream. + ogg_packet packet; + if (codecState->DoneReadingHeaders() && mDataOffset == 0) + { + // Stream has read all header packets, but now there's more data in + // (presumably) a non-header page, we must have finished header packets. + // This can happen in incorrectly chopped streams. + mDataOffset = pageOffset; + continue; + } + while (!codecState->DoneReadingHeaders() && + (ret = ogg_stream_packetout(&codecState->mState, &packet)) != 0) + { + if (ret == -1) { + // Sync lost, we've probably encountered the continuation of a packet + // in a chopped video. + continue; + } + // A packet is available. If it is not a header packet we'll break. + // If it is a header packet, process it as normal. + codecState->DecodeHeader(&packet); + } + if (ogg_stream_packetpeek(&codecState->mState, &packet) != 0 && + mDataOffset == 0) + { + // We're finished reading headers for this bitstream, but there's still + // packets in the bitstream to read. The bitstream is probably poorly + // muxed, and includes the last header packet on a page with non-header + // packets. We need to ensure that this is the media start page offset. + mDataOffset = pageOffset; + } + } + // Deactivate any non-primary bitstreams. + for (PRUint32 i = 0; i < bitstreams.Length(); i++) { + nsOggCodecState* s = bitstreams[i]; + if (s != mVorbisState && s != mTheoraState) { + s->Deactivate(); + } + } + + // Initialize the first Theora and Vorbis bitstreams. According to the + // Theora spec these can be considered the 'primary' bitstreams for playback. + // Extract the metadata needed from these streams. + float aspectRatio = 0; + if (mTheoraState) { + if (mTheoraState->Init()) { + mCallbackPeriod = mTheoraState->mFrameDuration; + aspectRatio = mTheoraState->mAspectRatio; + gfxIntSize sz(mTheoraState->mInfo.pic_width, + mTheoraState->mInfo.pic_height); + mPlayer->mDecoder->SetVideoData(sz, mTheoraState->mAspectRatio, nsnull); + } else { + mTheoraState = nsnull; + } + } + if (mVorbisState) { + mVorbisState->Init(); + } + + aInfo.mHasAudio = HasAudio(); + aInfo.mHasVideo = HasVideo(); + aInfo.mCallbackPeriod = mCallbackPeriod; + if (HasAudio()) { + aInfo.mAudioRate = mVorbisState->mInfo.rate; + aInfo.mAudioChannels = mVorbisState->mInfo.channels; + } + if (HasVideo()) { + aInfo.mFramerate = mTheoraState->mFrameRate; + aInfo.mAspectRatio = mTheoraState->mAspectRatio; + aInfo.mPicture.width = mTheoraState->mInfo.pic_width; + aInfo.mPicture.height = mTheoraState->mInfo.pic_height; + aInfo.mPicture.x = mTheoraState->mInfo.pic_x; + aInfo.mPicture.y = mTheoraState->mInfo.pic_y; + aInfo.mFrame.width = mTheoraState->mInfo.frame_width; + aInfo.mFrame.height = mTheoraState->mInfo.frame_height; + } + aInfo.mDataOffset = mDataOffset; + + LOG(PR_LOG_DEBUG, ("Done loading headers, data offset %lld", mDataOffset)); + + return NS_OK; +} + +template +Data* nsOggReader::DecodeToFirstData(DecodeFn aDecodeFn, + MediaQueue& aQueue) +{ + PRBool eof = PR_FALSE; + while (!eof && aQueue.GetSize() == 0) { + { + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return nsnull; + } + } + eof = !(this->*aDecodeFn)(); + } + Data* d = nsnull; + return (d = aQueue.PeekFront()) ? d : nsnull; +} + +VideoData* nsOggReader::FindStartTime(PRInt64 aOffset, + PRInt64& aOutStartTime) +{ + NS_ASSERTION(mPlayer->OnStateMachineThread(), "Should be on state machine thread."); + + nsMediaStream* stream = mPlayer->mDecoder->mStream; + + stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset); + if (NS_FAILED(ResetDecode())) { + return nsnull; + } + + // Extract the start times of the bitstreams in order to calculate + // the duration. + PRInt64 videoStartTime = PR_INT64_MAX; + PRInt64 audioStartTime = PR_INT64_MAX; + VideoData* videoData = nsnull; + + if (HasVideo()) { + videoData = DecodeToFirstData(&nsOggReader::DecodeVideoPage, + mVideoQueue); + if (videoData) { + videoStartTime = videoData->mTime; + } + } + if (HasAudio()) { + SoundData* soundData = DecodeToFirstData(&nsOggReader::DecodeAudioPage, + mAudioQueue); + if (soundData) { + audioStartTime = soundData->mTime; + } + } + + PRInt64 startTime = PR_MIN(videoStartTime, audioStartTime); + if (startTime != PR_INT64_MAX) { + aOutStartTime = startTime; + } + + return videoData; +} + +// Returns an ogg page's checksum. +static ogg_uint32_t +GetChecksum(ogg_page* page) +{ + if (page == 0 || page->header == 0 || page->header_len < 25) { + return 0; + } + const unsigned char* p = page->header + 22; + PRUint32 c = p[0] + + (p[1] << 8) + + (p[2] << 16) + + (p[3] << 24); + return c; +} + +PRInt64 nsOggReader::FindEndTime(PRInt64 aEndOffset) +{ + MonitorAutoEnter mon(mMonitor); + NS_ASSERTION(mPlayer->OnStateMachineThread(), "Should be on state machine thread."); + + nsMediaStream* stream = mPlayer->mDecoder->mStream; + ogg_sync_reset(&mOggState); + + stream->Seek(nsISeekableStream::NS_SEEK_SET, aEndOffset); + + // We need to find the last page which ends before aEndOffset that + // has a granulepos that we can convert to a timestamp. We do this by + // backing off from aEndOffset until we encounter a page on which we can + // interpret the granulepos. If while backing off we encounter a page which + // we've previously encountered before, we'll either backoff again if we + // haven't found an end time yet, or return the last end time found. + const int step = 5000; + PRInt64 offset = aEndOffset; + PRInt64 endTime = -1; + PRUint32 checksumAfterSeek = 0; + PRUint32 prevChecksumAfterSeek = 0; + PRBool mustBackOff = PR_FALSE; + while (PR_TRUE) { + { + MonitorAutoExit exitReaderMon(mMonitor); + MonitorAutoEnter decoderMon(mPlayer->mDecoder->GetMonitor()); + if (mPlayer->mState == nsOggPlayStateMachine::DECODER_STATE_SHUTDOWN) { + return -1; + } + } + ogg_page page; + int ret = ogg_sync_pageseek(&mOggState, &page); + if (ret == 0) { + // We need more data if we've not encountered a page we've seen before, + // or we've read to the end of file. + if (mustBackOff || stream->Tell() == aEndOffset) { + if (endTime != -1) { + // We have encountered a page before, or we're at the end of file. + break; + } + mustBackOff = PR_FALSE; + prevChecksumAfterSeek = checksumAfterSeek; + checksumAfterSeek = 0; + ogg_sync_reset(&mOggState); + offset = NS_MAX(static_cast(0), offset - step); + stream->Seek(nsISeekableStream::NS_SEEK_SET, offset); + } + NS_ASSERTION(stream->Tell() < aEndOffset, + "Stream pos must be before range end"); + + PRInt64 limit = NS_MIN(static_cast(PR_UINT32_MAX), + aEndOffset - stream->Tell()); + limit = NS_MAX(static_cast(0), limit); + limit = NS_MIN(limit, static_cast(step)); + PRUint32 bytesToRead = static_cast(limit); + PRUint32 bytesRead = 0; + char* buffer = ogg_sync_buffer(&mOggState, + bytesToRead); + NS_ASSERTION(buffer, "Must have buffer"); + stream->Read(buffer, bytesToRead, &bytesRead); + + // Update the synchronisation layer with the number + // of bytes written to the buffer + ret = ogg_sync_wrote(&mOggState, bytesRead); + if (ret != 0) { + endTime = -1; + break; + } + + continue; + } + + if (ret < 0 || ogg_page_granulepos(&page) < 0) { + continue; + } + + PRUint32 checksum = GetChecksum(&page); + if (checksumAfterSeek == 0) { + // This is the first page we've decoded after a backoff/seek. Remember + // the page checksum. If we backoff further and encounter this page + // again, we'll know that we won't find a page with an end time after + // this one, so we'll know to back off again. + checksumAfterSeek = checksum; + } + if (checksum == prevChecksumAfterSeek) { + // This page has the same checksum as the first page we encountered + // after the last backoff/seek. Since we've already scanned after this + // page and failed to find an end time, we may as well backoff again and + // try to find an end time from an earlier page. + mustBackOff = PR_TRUE; + continue; + } + + PRInt64 granulepos = ogg_page_granulepos(&page); + int serial = ogg_page_serialno(&page); + + nsOggCodecState* codecState = nsnull; + mCodecStates.Get(serial, &codecState); + + if (!codecState) { + // This page is from a bitstream which we haven't encountered yet. + // It's probably from a new "link" in a "chained" ogg. Don't + // bother even trying to find a duration... + break; + } + + PRInt64 t = codecState ? codecState->Time(granulepos) : -1; + if (t != -1) { + endTime = t; + } + } + + ogg_sync_reset(&mOggState); + + return endTime; +} diff --git a/content/media/ogg/nsOggReader.h b/content/media/ogg/nsOggReader.h new file mode 100644 index 000000000000..4ee945c49d69 --- /dev/null +++ b/content/media/ogg/nsOggReader.h @@ -0,0 +1,531 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: ML 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Double + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#if !defined(nsOggReader_h_) +#define nsOggReader_h_ + +#include +#include "nsOggCodecState.h" +#include +#include +#include +#include "prmon.h" +#include "nsAutoLock.h" +#include "nsClassHashtable.h" +#include "mozilla/TimeStamp.h" +#include "nsSize.h" +#include "nsRect.h" +#include "mozilla/Monitor.h" + +class nsOggPlayStateMachine; + +using mozilla::Monitor; +using mozilla::MonitorAutoEnter; +using mozilla::TimeDuration; +using mozilla::TimeStamp; + +// Holds chunk a decoded sound samples. +class SoundData { +public: + SoundData(PRInt64 aTime, + PRInt64 aDuration, + PRUint32 aSamples, + float* aData, + PRUint32 aChannels) + : mTime(aTime), + mDuration(aDuration), + mSamples(aSamples), + mAudioData(aData), + mChannels(aChannels) + { + MOZ_COUNT_CTOR(SoundData); + } + + SoundData(PRInt64 aDuration, + PRUint32 aSamples, + float* aData, + PRUint32 aChannels) + : mTime(-1), + mDuration(aDuration), + mSamples(aSamples), + mAudioData(aData), + mChannels(aChannels) + { + MOZ_COUNT_CTOR(SoundData); + } + + ~SoundData() + { + MOZ_COUNT_DTOR(SoundData); + } + + PRUint32 AudioDataLength() { + return mChannels * mSamples; + } + + PRInt64 mTime; // Start time of samples in ms. + const PRInt64 mDuration; // In ms. + const PRUint32 mSamples; + const PRUint32 mChannels; + nsAutoArrayPtr mAudioData; +}; + +// Holds a decoded Theora frame, in YCbCr format. These are queued in the reader. +class VideoData { +public: + + // Constructs a VideoData object. Makes a copy of YCbCr data in aBuffer. + // This may return nsnull if we run out of memory when allocating buffers + // to store the frame. + static VideoData* Create(PRInt64 aTime, + th_ycbcr_buffer aBuffer, + PRBool aKeyframe, + PRInt64 aGranulepos); + + // Constructs a duplicate VideoData object. This intrinsically tells the + // player that it does not need to update the displayed frame when this + // frame is played; this frame is identical to the previous. + static VideoData* CreateDuplicate(PRInt64 aTime, + PRInt64 aGranulepos) + { + return new VideoData(aTime, aGranulepos); + } + + ~VideoData() + { + MOZ_COUNT_DTOR(VideoData); + for (PRUint32 i = 0; i < 3; ++i) { + delete mBuffer[i].data; + } + } + + // Start time of frame in milliseconds. + PRInt64 mTime; + PRInt64 mGranulepos; + + th_ycbcr_buffer mBuffer; + + // When PR_TRUE, denotes that this frame is identical to the frame that + // came before; it's a duplicate. mBuffer will be empty. + PRPackedBool mDuplicate; + PRPackedBool mKeyframe; + +private: + VideoData(PRInt64 aTime, PRInt64 aGranulepos) : + mTime(aTime), + mGranulepos(aGranulepos), + mDuplicate(PR_TRUE), + mKeyframe(PR_FALSE) + { + MOZ_COUNT_CTOR(VideoData); + memset(&mBuffer, 0, sizeof(th_ycbcr_buffer)); + } + + VideoData(PRInt64 aTime, + PRBool aKeyframe, + PRInt64 aGranulepos) + : mTime(aTime), + mGranulepos(aGranulepos), + mDuplicate(PR_FALSE), + mKeyframe(aKeyframe) + { + MOZ_COUNT_CTOR(VideoData); + } + +}; + +// Thread and type safe wrapper around nsDeque. +template +class MediaQueueDeallocator : public nsDequeFunctor { + virtual void* operator() (void* anObject) { + delete static_cast(anObject); + return nsnull; + } +}; + +template class MediaQueue : private nsDeque { + public: + + MediaQueue() + : nsDeque(new MediaQueueDeallocator()), + mMonitor("mediaqueue"), + mEndOfStream(0) + {} + + ~MediaQueue() { + Reset(); + } + + inline PRInt32 GetSize() { + MonitorAutoEnter mon(mMonitor); + return nsDeque::GetSize(); + } + + inline void Push(T* aItem) { + MonitorAutoEnter mon(mMonitor); + nsDeque::Push(aItem); + } + + inline void PushFront(T* aItem) { + MonitorAutoEnter mon(mMonitor); + nsDeque::PushFront(aItem); + } + + inline T* Pop() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::Pop()); + } + + inline T* PopFront() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::PopFront()); + } + + inline T* Peek() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::Peek()); + } + + inline T* PeekFront() { + MonitorAutoEnter mon(mMonitor); + return static_cast(nsDeque::PeekFront()); + } + + inline void Empty() { + MonitorAutoEnter mon(mMonitor); + nsDeque::Empty(); + } + + inline void Erase() { + MonitorAutoEnter mon(mMonitor); + nsDeque::Erase(); + } + + void Reset() { + MonitorAutoEnter mon(mMonitor); + while (GetSize() > 0) { + T* x = PopFront(); + delete x; + } + mEndOfStream = PR_FALSE; + } + + PRBool AtEndOfStream() { + MonitorAutoEnter mon(mMonitor); + return GetSize() == 0 && mEndOfStream; + } + + void Finish() { + MonitorAutoEnter mon(mMonitor); + mEndOfStream = PR_TRUE; + } + + // Returns the approximate number of milliseconds of samples in the queue. + PRInt64 Duration() { + MonitorAutoEnter mon(mMonitor); + if (GetSize() < 2) { + return 0; + } + T* last = Peek(); + T* first = PeekFront(); + return last->mTime - first->mTime; + } + +private: + Monitor mMonitor; + + // PR_TRUE when we've decoded the last packet in the bitstream for which + // we're queueing sample-data. + PRBool mEndOfStream; +}; + +// Represents a section of contiguous media, with a start and end offset, +// and the timestamps of the start and end of that range. Used to denote the +// extremities of a range to seek in. +class ByteRange { +public: + ByteRange() : + mOffsetStart(0), + mOffsetEnd(0), + mTimeStart(0), + mTimeEnd(0) + {} + + ByteRange(PRInt64 aOffsetStart, + PRInt64 aOffsetEnd, + PRInt64 aTimeStart, + PRInt64 aTimeEnd) + : mOffsetStart(aOffsetStart), + mOffsetEnd(aOffsetEnd), + mTimeStart(aTimeStart), + mTimeEnd(aTimeEnd) + {} + + PRBool IsNull() { + return mOffsetStart == 0 && + mOffsetEnd == 0 && + mTimeStart == 0 && + mTimeEnd == 0; + } + + PRInt64 mOffsetStart, mOffsetEnd; // in bytes. + PRInt64 mTimeStart, mTimeEnd; // in ms. +}; + +// Stores info relevant to presenting media samples. +class nsOggInfo { +public: + nsOggInfo() + : mFramerate(0.0), + mAspectRatio(1.0), + mCallbackPeriod(1), + mAudioRate(0), + mAudioChannels(0), + mFrame(0,0), + mHasAudio(PR_FALSE), + mHasVideo(PR_FALSE) + {} + + // Frames per second. + float mFramerate; + + // Aspect ratio, as stored in the video header packet. + float mAspectRatio; + + // Length of a video frame in milliseconds, or the callback period if + // there's no audio. + PRUint32 mCallbackPeriod; + + // Samples per second. + PRUint32 mAudioRate; + + // Number of audio channels. + PRUint32 mAudioChannels; + + // Dimensions of the video frame. + nsIntSize mFrame; + + // The picture region inside the video frame to be displayed. + nsIntRect mPicture; + + // The offset of the first non-header page in the file, in bytes. + // Used to seek to the start of the media. + PRInt64 mDataOffset; + + // PR_TRUE if we have an active audio bitstream. + PRPackedBool mHasAudio; + + // PR_TRUE if we have an active video bitstream. + PRPackedBool mHasVideo; +}; + +// Encapsulates the decoding and reading of Ogg data. Reading can be done +// on either the state machine thread (when loading and seeking) or on +// the reader thread (when it's reading and decoding). The reader encapsulates +// the reading state and maintains it's own monitor to ensure thread safety +// and correctness. Never hold the nsOggDecoder's monitor when calling into +// this class. +class nsOggReader : public nsRunnable { +public: + nsOggReader(nsOggPlayStateMachine* aStateMachine); + ~nsOggReader(); + + PRBool HasAudio() + { + MonitorAutoEnter mon(mMonitor); + return mVorbisState != 0 && mVorbisState->mActive; + } + + PRBool HasVideo() + { + MonitorAutoEnter mon(mMonitor); + return mTheoraState != 0 && mTheoraState->mActive; + } + + // Read header data for all bitstreams in the Ogg file. Fills aInfo with + // the data required to present the media. Returns NS_OK on success, + // or NS_ERROR_FAILURE on failure. + nsresult ReadOggHeaders(nsOggInfo& aInfo); + + // Stores the presentation time of the first sample in the stream in + // aOutStartTime, and returns the first video sample, if we have video. + VideoData* FindStartTime(PRInt64 aOffset, + PRInt64& aOutStartTime); + + // Returns the end time of the last page which occurs before aEndOffset. + // This will not read past aEndOffset. Returns -1 on failure. + PRInt64 FindEndTime(PRInt64 aEndOffset); + + // Decodes one Vorbis page, enqueuing the audio data in mAudioQueue. + // Returns PR_TRUE when there's more audio to decode, PR_FALSE if the + // audio is finished, end of file has been reached, or an un-recoverable + // read error has occured. + PRBool DecodeAudioPage(); + + // Reads and decodes one video frame. If the Theora granulepos has not + // been captured, it may read several packets until one with a granulepos + // has been captured, to ensure that all packets read have valid time info. + // Packets with a timestamp less than aTimeThreshold will be decoded (unless + // they're not keyframes and aKeyframeSkip is PR_TRUE), but will not be + // added to the queue. + PRBool DecodeVideoPage(PRBool &aKeyframeSkip, + PRInt64 aTimeThreshold); + + // Moves the decode head to aTime milliseconds. aStartTime and aEndTime + // denote the start and end times of the media. + nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime); + + // Queue of audio samples. This queue is threadsafe. + MediaQueue mAudioQueue; + + // Queue of video samples. This queue is threadsafe. + MediaQueue mVideoQueue; + + // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE + // on failure. + nsresult Init(); + +private: + + // Ogg reader decode function. Matches DecodeVideoPage() and + // DecodeAudioPage(). + typedef PRBool (nsOggReader::*DecodeFn)(); + + // Calls aDecodeFn on *this until aQueue has a sample, whereupon + // we return the first sample. + template + Data* DecodeToFirstData(DecodeFn aDecodeFn, + MediaQueue& aQueue); + + // Wrapper so that DecodeVideoPage(PRBool&,PRInt64) can be called from + // DecodeToFirstData(). + PRBool DecodeVideoPage() { + PRBool f = PR_FALSE; + return DecodeVideoPage(f, 0); + } + + // Decodes one packet of Vorbis data, storing the resulting chunks of + // PCM samples in aChunks. + nsresult DecodeVorbis(nsTArray& aChunks, + ogg_packet* aPacket); + + // May return NS_ERROR_OUT_OF_MEMORY. + nsresult DecodeTheora(nsTArray& aFrames, + ogg_packet* aPacket); + + // Resets all state related to decoding, emptying all buffers etc. + nsresult ResetDecode(); + + // Read a page of data from the Ogg file. Returns the offset of the start + // of the page, or -1 if the page read failed. + PRInt64 ReadOggPage(ogg_page* aPage); + + // Read a packet for an Ogg bitstream/codec state. Returns PR_TRUE on + // success, or PR_FALSE if the read failed. + PRBool ReadOggPacket(nsOggCodecState* aCodecState, ogg_packet* aPacket); + + // Performs a seek bisection to move the media stream's read cursor to the + // last ogg page boundary which has end time before aTarget ms on both the + // Theora and Vorbis bitstreams. Limits its search to data inside aRange; + // i.e. it will only read inside of the aRange's start and end offsets. + // aFuzz is the number of ms of leniency we'll allow; we'll terminate the + // seek when we land in the range (aTime - aFuzz, aTime) ms. + nsresult SeekBisection(PRInt64 aTarget, + const ByteRange& aRange, + PRUint32 aFuzz); + + // Fills aRanges with ByteRanges denoting the sections of the media which + // have been downloaded and are stored in the media cache. The reader + // monitor must must be held with exactly one lock count. The nsMediaStream + // must be pinned while calling this. + nsresult GetBufferedBytes(nsTArray& aRanges); + + // Returns the range in which you should perform a seek bisection if + // you wish to seek to aTarget ms, given the known (buffered) byte ranges + // in aRanges. If aExact is PR_TRUE, we only return an exact copy of a + // range in which aTarget lies, or a null range if aTarget isn't contained + // in any of the (buffered) ranges. Otherwise, when aExact is PR_FALSE, + // we'll construct the smallest possible range we can, based on the times + // and byte offsets known in aRanges. We can then use this to minimize our + // bisection's search space when the target isn't in a known buffered range. + ByteRange GetSeekRange(const nsTArray& aRanges, + PRInt64 aTarget, + PRInt64 aStartTime, + PRInt64 aEndTime, + PRBool aExact); + + // The lock which we hold whenever we read or decode. This ensures the thread + // safety of the reader and its data fields. + Monitor mMonitor; + + // Reference to the owning player state machine object. Do not hold the + // reader's monitor when accessing the player. + nsOggPlayStateMachine* mPlayer; + + // Maps Ogg serialnos to nsOggStreams. + nsClassHashtable mCodecStates; + + // Decode state of the Theora bitstream we're decoding, if we have video. + nsTheoraState* mTheoraState; + + // Decode state of the Vorbis bitstream we're decoding, if we have audio. + nsVorbisState* mVorbisState; + + // Ogg decoding state. + ogg_sync_state mOggState; + + // The offset of the end of the last page we've read, or the start of + // the page we're about to read. + PRInt64 mPageOffset; + + // The offset of the start of the first non-header page in the file. + // Used to seek to media start time. + PRInt64 mDataOffset; + + // The granulepos of the last decoded Theora frame. + PRInt64 mTheoraGranulepos; + + // The granulepos of the last decoded Vorbis sample. + PRInt64 mVorbisGranulepos; + + // Number of milliseconds of data video/audio data held in a frame. + PRUint32 mCallbackPeriod; + +}; + +#endif diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index 04f9bf719eb8..6b8731af637c 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -104,6 +104,7 @@ _TEST_FILES = \ test_playback_errors.html \ test_reactivate.html \ test_readyState.html \ + test_seek.html \ test_seek2.html \ test_volume.html \ use_large_cache.js \ @@ -113,23 +114,17 @@ _TEST_FILES = \ # test_resume.html \ # -ifneq ($(OS_ARCH),WINNT) -# These tests are disabled on windows until we -# figure out the random failures. See bug 475369. -_TEST_FILES += \ - test_seek.html \ - $(NULL) -endif - # Ogg sample files _TEST_FILES += \ 320x240.ogv \ 320x240.allow-origin.ogv \ 320x240.allow-origin.ogv^headers^ \ 448636.ogv \ + audio-overhang.ogg \ beta-phrasebook.ogg \ bogus.ogv \ bug495129.ogv \ + bug495794.ogg \ bug461281.ogg \ bug482461.ogv \ bug498380.ogv \ @@ -157,6 +152,7 @@ _TEST_FILES += \ short-video.ogv \ small-shot.ogg \ sound.ogg \ + video-overhang.ogg \ $(NULL) # Wave sample files diff --git a/content/media/test/audio-overhang.ogg b/content/media/test/audio-overhang.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c07986e7a1c63d0ae5f1a8232a9236f9acbe6bed GIT binary patch literal 45463 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 jZho literal 0 HcmV?d00001 diff --git a/content/media/test/bug495794.ogg b/content/media/test/bug495794.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1c19a640612dcfab2b3181f9f4da1d1247d11560 GIT binary patch literal 4837 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 literal 0 HcmV?d00001 diff --git a/content/media/test/manifest.js b/content/media/test/manifest.js index b2008c1cf81c..4e30d5b20dfc 100644 --- a/content/media/test/manifest.js +++ b/content/media/test/manifest.js @@ -40,7 +40,7 @@ var gPlayTests = [ // Ogg stream with eof marker { name:"bug461281.ogg", type:"application/ogg" }, // oggz-chop stream - { name:"bug482461.ogv", type:"video/ogg", duration:4.24 }, + { name:"bug482461.ogv", type:"video/ogg", duration:4.34 }, // With first frame a "duplicate" (empty) frame. { name:"bug500311.ogv", type:"video/ogg", duration:1.96 }, // Small audio file @@ -50,9 +50,10 @@ var gPlayTests = [ // First Theora data packet is zero bytes. { name:"bug504613.ogv", type:"video/ogg" }, // Multiple audio streams. - { name:"bug516323.ogv", type:"video/ogg", duration:4.424 }, + { name:"bug516323.ogv", type:"video/ogg", duration:4.208 }, + // Encoded with vorbis beta1, includes unusually sized codebooks - { name:"beta-phrasebook.ogg", type:"audio/ogg", duration:4 }, + { name:"beta-phrasebook.ogg", type:"audio/ogg", duration:4.01 }, // Small file, only 1 frame with audio only. { name:"bug520493.ogg", type:"audio/ogg", duration:0.458 }, // Small file with vorbis comments with 0 length values and names. @@ -61,13 +62,17 @@ var gPlayTests = [ // Various weirdly formed Ogg files { name:"bug499519.ogv", type:"video/ogg", duration:0.24 }, { name:"bug506094.ogv", type:"video/ogg", duration:0 }, - { name:"bug501279.ogg", type:"audio/ogg", duration:0 }, - { name:"bug498855-1.ogv", type:"video/ogg", duration:0.2 }, - { name:"bug498855-2.ogv", type:"video/ogg", duration:0.2 }, - { name:"bug498855-3.ogv", type:"video/ogg", duration:0.2 }, - { name:"bug504644.ogv", type:"video/ogg", duration:1.56 }, + { name:"bug498855-1.ogv", type:"video/ogg", duration:0.24 }, + { name:"bug498855-2.ogv", type:"video/ogg", duration:0.24 }, + { name:"bug498855-3.ogv", type:"video/ogg", duration:0.24 }, + { name:"bug504644.ogv", type:"video/ogg", duration:1.6 }, { name:"chain.ogv", type:"video/ogg", duration:Number.NaN }, - { name:"bug523816.ogv", type:"video/ogg", duration:0.5 }, + { name:"bug523816.ogv", type:"video/ogg", duration:0.533 }, + { name:"bug495129.ogv", type:"video/ogg", duration:2.41 }, + { name:"bug498380.ogv", type:"video/ogg" }, + { name:"bug495794.ogg", type:"audio/ogg", duration:0.3}, + { name:"audio-overhang.ogg", type:"audio/ogg", duration:2.3}, + { name:"video-overhang.ogg", type:"audio/ogg", duration:3.966}, { name:"bogus.duh", type:"bogus/duh" } ]; @@ -82,9 +87,8 @@ var gErrorTests = [ { name:"bogus.wav", type:"audio/x-wav" }, { name:"bogus.ogv", type:"video/ogg" }, { name:"448636.ogv", type:"video/ogg" }, - { name:"bug495129.ogv", type:"video/ogg", duration:2.52 }, - { name:"bug504843.ogv", type:"video/ogg", duration:1.233 }, - { name:"bug498380.ogv", type:"video/ogg" }, + { name:"bug504843.ogv", type:"video/ogg" }, + { name:"bug501279.ogg", type:"audio/ogg" }, { name:"bogus.duh", type:"bogus/duh" } ]; diff --git a/content/media/test/test_duration1.html b/content/media/test/test_duration1.html index f6417782c569..ef2669b5d321 100644 --- a/content/media/test/test_duration1.html +++ b/content/media/test/test_duration1.html @@ -17,7 +17,7 @@ function startTest() { if (completed) return false; var v = document.getElementById('v'); - is(Math.round(v.duration*1000), 3966, "Check duration of video: " + v.duration); + is(Math.round(v.duration*1000), 3999, "Check duration of video: " + v.duration); completed = true; clearTimeout(timeout); SimpleTest.finish(); diff --git a/content/media/test/test_info_leak.html b/content/media/test/test_info_leak.html index 0f24ae376e5d..98f9988a28da 100644 --- a/content/media/test/test_info_leak.html +++ b/content/media/test/test_info_leak.html @@ -158,7 +158,7 @@ function checkState() { "Ready state of " + gMedia.readyState + " was leaked"); test_is(gMedia.seeking, false, "Seeking leaked"); test_is(gMedia.currentTime, 0, "Leaked currentTime"); - test_is(gMedia.duration, 0, "Leaked duration"); + test_ok(isNaN(gMedia.duration), "Leaked duration"); test_is(gMedia.paused, true, "Paused leaked"); test_is(gMedia.ended, false, "Ended leaked"); test_is(gMedia.autoplay, false, "Autoplay leaked"); diff --git a/content/media/test/test_playback.html b/content/media/test/test_playback.html index 33be3e1c1525..fc261be16802 100644 --- a/content/media/test/test_playback.html +++ b/content/media/test/test_playback.html @@ -30,7 +30,9 @@ function startTests() { continue; v.src = test.name; + v.name = test.name; var check = function(test, v) { return function() { + is(test.name, v.name, "Name should match test.name #1"); checkMetadata(test.name, v, test); }}(test, v); var noLoad = function(test, v) { return function() { @@ -39,8 +41,9 @@ function startTests() { var checkEnded = function(test, v) { return function() { if (test.duration) { ok(Math.abs(v.currentTime - test.duration) < 0.1, - test.name + " current time at end: " + v.currentTime); + test.name + " current time at end: " + v.currentTime + " should be: " + test.duration); } + is(test.name, v.name, "Name should match test.name #2"); is(v.readyState, v.HAVE_CURRENT_DATA, test.name + " checking readyState"); ok(v.readyState != v.NETWORK_LOADED, test.name + " shouldn't report NETWORK_LOADED"); ok(v.ended, test.name + " checking playback has ended"); @@ -50,6 +53,7 @@ function startTests() { } }}(test, v); var checkSuspended = function(test, v) { return function() { + is(test.name, v.name, "Name should match test.name #3"); if (v.seenSuspend) return; @@ -61,12 +65,13 @@ function startTests() { } }}(test, v); v.prevTime = 0; - var timeUpdate = function(v) { return function() { + var timeUpdate = function(test, v) { return function() { + is(test.name, v.name, "Name should match test.name #4"); ok(v.prevTime <= v.currentTime, test.name + " time should run forwards: p=" + v.prevTime + " c=" + v.currentTime); v.prevTime = v.currentTime; - }}(v); + }}(test, v); v.addEventListener("load", noLoad, false); v.addEventListener("loadedmetadata", check, false); v.addEventListener("timeupdate", timeUpdate, false); diff --git a/content/media/test/test_timeupdate1.html b/content/media/test/test_timeupdate1.html index 3a747a3bb294..4dc566744e87 100644 --- a/content/media/test/test_timeupdate1.html +++ b/content/media/test/test_timeupdate1.html @@ -29,10 +29,8 @@ function timeUpdated() { var v = document.getElementById('v'); ok(v.currentTime > lastTime, - "Check currentTime of " + - v.currentTime + - " is greater than last time of " + - lastTime); + "currentTime (" + v.currentTime + + ") should be greater than last time (" + lastTime + ")"); lastTime = v.currentTime; return false; } diff --git a/content/media/test/video-overhang.ogg b/content/media/test/video-overhang.ogg new file mode 100644 index 0000000000000000000000000000000000000000..e11b28fb5bbcca2916267a86339f6c5ecdb4d4cc GIT binary patch literal 301831 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 z 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�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

||74`d;{5T}|a*vABF!O6(ht1B`nz~uu7~LpK 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%0D%Ei4F^fvI_`V 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 literal 0 HcmV?d00001 diff --git a/content/media/wave/nsWaveDecoder.cpp b/content/media/wave/nsWaveDecoder.cpp index 6818368a6b79..511edca5c6cc 100644 --- a/content/media/wave/nsWaveDecoder.cpp +++ b/content/media/wave/nsWaveDecoder.cpp @@ -648,7 +648,7 @@ nsWaveStateMachine::Run() PRUint32 lengthInSamples = got / sampleSize; monitor.Exit(); - mAudioStream->Write(buf.get(), lengthInSamples); + mAudioStream->Write(buf.get(), lengthInSamples, PR_FALSE); monitor.Enter(); FirePositionChanged(PR_FALSE); From 70e2bdb1abc0c31e7298febb66c6362d61f7008b Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 2 Apr 2010 08:47:05 -0700 Subject: [PATCH 59/69] Fix for Qt build bustage. Need to #include class before using it in a nsRefPtr. Nobug --- gfx/thebes/public/gfxQtNativeRenderer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gfx/thebes/public/gfxQtNativeRenderer.h b/gfx/thebes/public/gfxQtNativeRenderer.h index 9dd8de5482ad..57628d77854f 100644 --- a/gfx/thebes/public/gfxQtNativeRenderer.h +++ b/gfx/thebes/public/gfxQtNativeRenderer.h @@ -39,9 +39,8 @@ #define GFXQTNATIVERENDER_H_ #include "gfxColor.h" - -class gfxASurface; -class gfxContext; +#include "gfxASurface.h" +#include "gfxContext.h" class QWidget; class QRect; From 06593edeb7dabe197b3ef25d261fd21caa662b33 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Thu, 1 Apr 2010 22:19:35 -0700 Subject: [PATCH 60/69] Bug 531340 - Fix wait-on-audio-queue-empty condition in ogg decoder audio playback loop. r=doublec --- content/media/ogg/nsOggPlayStateMachine.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/content/media/ogg/nsOggPlayStateMachine.cpp b/content/media/ogg/nsOggPlayStateMachine.cpp index a088e3847e81..a1d512828d60 100644 --- a/content/media/ogg/nsOggPlayStateMachine.cpp +++ b/content/media/ogg/nsOggPlayStateMachine.cpp @@ -319,8 +319,7 @@ void nsOggPlayStateMachine::AudioLoop() !mStopDecodeThreads && (!IsPlaying() || mState == DECODER_STATE_BUFFERING || - (mState == DECODER_STATE_DECODING && - mReader->mAudioQueue.GetSize() == 0 && + (mReader->mAudioQueue.GetSize() == 0 && !mReader->mAudioQueue.AtEndOfStream()))) { mon.Wait(); @@ -335,8 +334,7 @@ void nsOggPlayStateMachine::AudioLoop() } } - NS_ASSERTION(mReader->mAudioQueue.GetSize() > 0 && - !mReader->mAudioQueue.AtEndOfStream(), + NS_ASSERTION(mReader->mAudioQueue.GetSize() > 0, "Should have data to play"); nsAutoPtr sound(mReader->mAudioQueue.PopFront()); { From 348f3082bf3e58fc43b5b63b61589426d075bde2 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 1 Apr 2010 23:07:40 -0700 Subject: [PATCH 61/69] Bug 383488: don't accept trailing tokens in 'value' in style.setProperty(prop,value,"important"). r=dbaron --- content/svg/content/src/nsSVGElement.cpp | 2 +- layout/reftests/bugs/383488-1-ref.html | 28 +++++++++++++ layout/reftests/bugs/383488-1.html | 53 ++++++++++++++++++++++++ layout/reftests/bugs/reftest.list | 1 + layout/style/nsCSSParser.cpp | 30 ++++++++------ layout/style/nsCSSParser.h | 3 +- layout/style/nsDOMCSSDeclaration.cpp | 26 ++++++------ layout/style/nsDOMCSSDeclaration.h | 3 +- layout/style/nsStyleAnimation.cpp | 2 +- 9 files changed, 120 insertions(+), 28 deletions(-) create mode 100644 layout/reftests/bugs/383488-1-ref.html create mode 100644 layout/reftests/bugs/383488-1.html diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index 6aca93d9b948..b0a68971af21 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -1132,7 +1132,7 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName, nsCSSProps::LookupProperty(nsAtomString(aMappedAttrName)); PRBool changed; // outparam for ParseProperty. (ignored) mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI, - mNodePrincipal, mDecl, &changed); + mNodePrincipal, mDecl, &changed, PR_FALSE); } already_AddRefed diff --git a/layout/reftests/bugs/383488-1-ref.html b/layout/reftests/bugs/383488-1-ref.html new file mode 100644 index 000000000000..0b2df13e5a2b --- /dev/null +++ b/layout/reftests/bugs/383488-1-ref.html @@ -0,0 +1,28 @@ + + + + +

The X'es below should have the same size:

+ +

XXXXXXXXXXXXXXXX

+ + diff --git a/layout/reftests/bugs/383488-1.html b/layout/reftests/bugs/383488-1.html new file mode 100644 index 000000000000..cd5df2b4b86c --- /dev/null +++ b/layout/reftests/bugs/383488-1.html @@ -0,0 +1,53 @@ + + + + + +

The X'es below should have the same size:

+ +

XXXXXXXXXXXXXXXX

+ diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 77bd01f7e830..26b08b684b82 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -671,6 +671,7 @@ random-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 379316-2.html 379316-2-ref.html # bug == 382916-1.html 382916-1-ref.html == 383035-1.html about:blank == 383035-2.html about:blank +== 383488-1.html 383488-1-ref.html == 383551-1.html 383551-1-ref.html == 383883-1.html 383883-1-ref.html == 383883-2.html 383883-2-ref.html diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 70ec1e2c1c4b..1d59799240ed 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -215,7 +215,8 @@ public: nsIURI* aBaseURL, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged); + PRBool* aChanged, + PRBool aIsImportant); nsresult ParseMediaList(const nsSubstring& aBuffer, nsIURI* aURL, // for error reporting @@ -1089,7 +1090,8 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, nsIURI* aBaseURI, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged) + PRBool* aChanged, + PRBool aIsImportant) { NS_PRECONDITION(aSheetPrincipal, "Must have principal here!"); AssertInitialState(); @@ -1117,17 +1119,20 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, mData.AssertInitialState(); mTempData.AssertInitialState(); - // We know that our new value is not !important, and that we don't need to - // force a ValueAppended call for it. So if there's already a value for this - // property in the declaration, and it's not !important, and our prop is not - // a shorthand, we parse successfully, then we can just directly copy our - // parsed value into the declaration without going through the whole - // expand/compress thing. + // We know we don't need to force a ValueAppended call for the new + // value. So if we are not processing an !important decl or a + // shorthand, there's already a value for this property in the + // declaration, it's not !important, and we parse successfully, then + // we can just directly copy our parsed value into the declaration + // without going through the whole expand/compress thing. if (!aDeclaration->EnsureMutable()) { NS_WARNING("out of memory"); return NS_ERROR_OUT_OF_MEMORY; } - void* valueSlot = aDeclaration->SlotForValue(aPropID); + void* valueSlot = nsnull; + if (!aIsImportant) { + valueSlot = aDeclaration->SlotForValue(aPropID); + } if (!valueSlot) { // Do it the slow way aDeclaration->ExpandTo(&mData); @@ -1139,7 +1144,7 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, CopyValue(mTempData.PropertyAt(aPropID), valueSlot, aPropID, aChanged); mTempData.ClearPropertyBit(aPropID); } else { - TransferTempData(aDeclaration, aPropID, PR_FALSE, PR_FALSE, aChanged); + TransferTempData(aDeclaration, aPropID, aIsImportant, PR_FALSE, aChanged); } } else { if (parsedOK) { @@ -9229,11 +9234,12 @@ nsCSSParser::ParseProperty(const nsCSSProperty aPropID, nsIURI* aBaseURI, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged) + PRBool* aChanged, + PRBool aIsImportant) { return static_cast(mImpl)-> ParseProperty(aPropID, aPropValue, aSheetURI, aBaseURI, - aSheetPrincipal, aDeclaration, aChanged); + aSheetPrincipal, aDeclaration, aChanged, aIsImportant); } nsresult diff --git a/layout/style/nsCSSParser.h b/layout/style/nsCSSParser.h index f0bbe971e002..2f5135d64657 100644 --- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -151,7 +151,8 @@ public: nsIURI* aBaseURL, nsIPrincipal* aSheetPrincipal, nsCSSDeclaration* aDeclaration, - PRBool* aChanged); + PRBool* aChanged, + PRBool aIsImportant); /** * Parse aBuffer into a media list |aMediaList|, which must be diff --git a/layout/style/nsDOMCSSDeclaration.cpp b/layout/style/nsDOMCSSDeclaration.cpp index 30b4a8ca8e46..6b69ca375fcb 100644 --- a/layout/style/nsDOMCSSDeclaration.cpp +++ b/layout/style/nsDOMCSSDeclaration.cpp @@ -103,7 +103,7 @@ nsDOMCSSDeclaration::SetPropertyValue(const nsCSSProperty aPropID, return RemoveProperty(aPropID); } - return ParsePropertyValue(aPropID, aValue); + return ParsePropertyValue(aPropID, aValue, PR_FALSE); } @@ -206,24 +206,24 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName, if (propID == eCSSProperty_UNKNOWN) { return NS_OK; } - + if (aValue.IsEmpty()) { // If the new value of the property is an empty string we remove the // property. + // XXX this ignores the priority string, should it? return RemoveProperty(propID); } if (aPriority.IsEmpty()) { - return ParsePropertyValue(propID, aValue); + return ParsePropertyValue(propID, aValue, PR_FALSE); } - // ParsePropertyValue does not handle priorities correctly -- it's - // optimized for speed. And the priority is not part of the - // property value anyway.... So we have to use the full-blown - // ParseDeclaration() - return ParseDeclaration(aPropertyName + NS_LITERAL_STRING(":") + - aValue + NS_LITERAL_STRING("!") + aPriority, - PR_TRUE, PR_FALSE); + if (aPriority.EqualsLiteral("important")) { + return ParsePropertyValue(propID, aValue, PR_TRUE); + } + + // XXX silent failure? + return NS_OK; } NS_IMETHODIMP @@ -245,7 +245,8 @@ nsDOMCSSDeclaration::RemoveProperty(const nsAString& aPropertyName, nsresult nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSProperty aPropID, - const nsAString& aPropValue) + const nsAString& aPropValue, + PRBool aIsImportant) { nsCSSDeclaration* decl; nsresult result = GetCSSDeclaration(&decl, PR_TRUE); @@ -275,7 +276,8 @@ nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSProperty aPropID, nsCSSParser cssParser(cssLoader); PRBool changed; result = cssParser.ParseProperty(aPropID, aPropValue, sheetURI, baseURI, - sheetPrincipal, decl, &changed); + sheetPrincipal, decl, &changed, + aIsImportant); if (NS_SUCCEEDED(result) && changed) { result = DeclarationChanged(); } diff --git a/layout/style/nsDOMCSSDeclaration.h b/layout/style/nsDOMCSSDeclaration.h index e86c6cb4c1dd..8eaa102970ee 100644 --- a/layout/style/nsDOMCSSDeclaration.h +++ b/layout/style/nsDOMCSSDeclaration.h @@ -122,7 +122,8 @@ protected: mozilla::css::Loader** aCSSLoader) = 0; nsresult ParsePropertyValue(const nsCSSProperty aPropID, - const nsAString& aPropValue); + const nsAString& aPropValue, + PRBool aIsImportant); nsresult ParseDeclaration(const nsAString& aDecl, PRBool aParseOnlyOneDecl, PRBool aClearOldDecl); diff --git a/layout/style/nsStyleAnimation.cpp b/layout/style/nsStyleAnimation.cpp index 9a1e03cd5873..8954f5d56a7e 100644 --- a/layout/style/nsStyleAnimation.cpp +++ b/layout/style/nsStyleAnimation.cpp @@ -954,7 +954,7 @@ BuildStyleRule(nsCSSProperty aProperty, NS_FAILED(parser.ParseProperty(aProperty, aSpecifiedValue, doc->GetDocumentURI(), baseURI, aTargetElement->NodePrincipal(), - declaration, &changed)) || + declaration, &changed, PR_FALSE)) || // check whether property parsed without CSS parsing errors !declaration->HasNonImportantValueFor(propertyToCheck) || NS_FAILED(NS_NewCSSStyleRule(getter_AddRefs(styleRule), nsnull, From 835ff67dda7693c73aa548e45443dc014f3e790f Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Thu, 1 Apr 2010 23:07:42 -0700 Subject: [PATCH 62/69] Bug 494117: remove PresContext argument to nsStyleSet::GetContext. r=bzbarsky --- layout/base/nsFrameManager.cpp | 10 +-- layout/style/nsStyleSet.cpp | 139 ++++++++++++--------------------- layout/style/nsStyleSet.h | 15 ++-- 3 files changed, 63 insertions(+), 101 deletions(-) diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index 53f14769ed1e..e8db21b0f9c5 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -773,12 +773,11 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) nsStyleContext* oldContext = aFrame->GetStyleContext(); // XXXbz can oldContext really ever be null? if (oldContext) { - nsPresContext *presContext = GetPresContext(); nsRefPtr newContext; nsIFrame* providerFrame = nsnull; PRBool providerIsChild = PR_FALSE; nsIFrame* providerChild = nsnull; - aFrame->GetParentStyleContextFrame(presContext, &providerFrame, + aFrame->GetParentStyleContextFrame(GetPresContext(), &providerFrame, &providerIsChild); nsStyleContext* newParentContext = nsnull; if (providerIsChild) { @@ -835,7 +834,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) // continuation). newContext = prevContinuationContext; } else { - newContext = mStyleSet->ReParentStyleContext(presContext, oldContext, + newContext = mStyleSet->ReparentStyleContext(oldContext, newParentContext); } @@ -848,7 +847,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) // nsTransitionManager::ConsiderStartingTransition. #if 0 if (!copyFromContinuation) { - TryStartingTransition(presContext, aFrame->GetContent(), + TryStartingTransition(GetPresContext(), aFrame->GetContent(), oldContext, &newContext); } #endif @@ -918,8 +917,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) aFrame->GetAdditionalStyleContext(++contextIndex); if (oldExtraContext) { nsRefPtr newExtraContext; - newExtraContext = mStyleSet->ReParentStyleContext(presContext, - oldExtraContext, + newExtraContext = mStyleSet->ReparentStyleContext(oldExtraContext, newContext); if (newExtraContext) { if (newExtraContext != oldExtraContext) { diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 9079602a57d0..7a3e1a720ce1 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -427,8 +427,7 @@ EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) * |aParentContext| could itself be a shared context.) */ already_AddRefed -nsStyleSet::GetContext(nsPresContext* aPresContext, - nsStyleContext* aParentContext, +nsStyleSet::GetContext(nsStyleContext* aParentContext, nsRuleNode* aRuleNode, nsIAtom* aPseudoTag, nsCSSPseudoElements::Type aPseudoType) @@ -442,7 +441,7 @@ nsStyleSet::GetContext(nsPresContext* aPresContext, "Pseudo mismatch"); nsStyleContext* result = nsnull; - + if (aParentContext) result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode).get(); @@ -455,7 +454,7 @@ nsStyleSet::GetContext(nsPresContext* aPresContext, if (!result) { result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType, - aRuleNode, aPresContext).get(); + aRuleNode, PresContext()).get(); if (!aParentContext && result) mRoots.AppendElement(result); } @@ -740,25 +739,16 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent, nsStyleContext* aParentContext) { NS_ENSURE_FALSE(mInShutdown, nsnull); - - nsStyleContext* result = nsnull; - nsPresContext* presContext = PresContext(); + NS_ASSERTION(aContent && aContent->IsNodeOfType(nsINode::eELEMENT), + "aContent must be element"); - NS_ASSERTION(aContent, "must have content"); - NS_ASSERTION(aContent->IsNodeOfType(nsINode::eELEMENT), - "content must be element"); + nsRuleWalker ruleWalker(mRuleTree); + ElementRuleProcessorData data(PresContext(), aContent, &ruleWalker); + FileRules(EnumRulesMatching, &data, aContent, + &ruleWalker); - if (aContent && presContext) { - nsRuleWalker ruleWalker(mRuleTree); - ElementRuleProcessorData data(presContext, aContent, &ruleWalker); - FileRules(EnumRulesMatching, &data, aContent, - &ruleWalker); - result = GetContext(presContext, aParentContext, - ruleWalker.CurrentNode(), nsnull, - nsCSSPseudoElements::ePseudo_NotPseudoElement).get(); - } - - return result; + return GetContext(aParentContext, ruleWalker.CurrentNode(), + nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement); } already_AddRefed @@ -769,39 +759,27 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext, const nsCOMArray &aRules) { NS_ENSURE_FALSE(mInShutdown, nsnull); - nsStyleContext* result = nsnull; - nsPresContext *presContext = PresContext(); - if (presContext) { - nsRuleWalker ruleWalker(mRuleTree); - if (aRuleNode) - ruleWalker.SetCurrentNode(aRuleNode); - // FIXME: Perhaps this should be passed in, but it probably doesn't - // matter. - ruleWalker.SetLevel(eDocSheet, PR_FALSE, PR_FALSE); - for (PRInt32 i = 0; i < aRules.Count(); i++) { - ruleWalker.Forward(aRules.ObjectAt(i)); - } - result = GetContext(presContext, aParentContext, - ruleWalker.CurrentNode(), aPseudoTag, - aPseudoType).get(); + nsRuleWalker ruleWalker(mRuleTree); + if (aRuleNode) + ruleWalker.SetCurrentNode(aRuleNode); + // FIXME: Perhaps this should be passed in, but it probably doesn't + // matter. + ruleWalker.SetLevel(eDocSheet, PR_FALSE, PR_FALSE); + for (PRInt32 i = 0; i < aRules.Count(); i++) { + ruleWalker.Forward(aRules.ObjectAt(i)); } - return result; + + return GetContext(aParentContext, ruleWalker.CurrentNode(), + aPseudoTag, aPseudoType); } already_AddRefed nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) { - nsStyleContext* result = nsnull; - nsPresContext *presContext = PresContext(); - - if (presContext) { - result = GetContext(presContext, aParentContext, mRuleTree, - nsCSSAnonBoxes::mozNonElement, - nsCSSPseudoElements::ePseudo_AnonBox).get(); - } - - return result; + return GetContext(aParentContext, mRuleTree, + nsCSSAnonBoxes::mozNonElement, + nsCSSPseudoElements::ePseudo_AnonBox); } void @@ -830,14 +808,13 @@ nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent, "aParentContent must be element"); nsRuleWalker ruleWalker(mRuleTree); - nsPresContext *presContext = PresContext(); - PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker, - aType); + PseudoElementRuleProcessorData data(PresContext(), aParentContent, + &ruleWalker, aType); WalkRestrictionRule(aType, &ruleWalker); FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), + return GetContext(aParentContext, ruleWalker.CurrentNode(), nsCSSPseudoElements::GetPseudoAtom(aType), aType); } @@ -847,7 +824,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, nsStyleContext* aParentContext) { NS_ENSURE_FALSE(mInShutdown, nsnull); - + NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, "must have pseudo element type"); NS_ASSERTION(aParentContent && @@ -855,12 +832,9 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, "aParentContent must be element"); nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); - - nsPresContext *presContext = PresContext(); - nsRuleWalker ruleWalker(mRuleTree); - PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker, - aType); + PseudoElementRuleProcessorData data(PresContext(), aParentContent, + &ruleWalker, aType); WalkRestrictionRule(aType, &ruleWalker); // not the root if there was a restriction rule nsRuleNode *adjustedRoot = ruleWalker.CurrentNode(); @@ -873,7 +847,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, } nsRefPtr result = - GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType); + GetContext(aParentContext, ruleNode, pseudoTag, aType); // For :before and :after pseudo-elements, having display: none or no // 'content' property is equivalent to not having the pseudo-element @@ -889,7 +863,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, result = nsnull; } } - + return result.forget(); } @@ -909,12 +883,11 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, #endif nsRuleWalker ruleWalker(mRuleTree); - nsPresContext *presContext = PresContext(); - AnonBoxRuleProcessorData data(presContext, aPseudoTag, &ruleWalker); + AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker); FileRules(EnumRulesMatching, &data, nsnull, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), + return GetContext(aParentContext, ruleWalker.CurrentNode(), aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox); } @@ -934,14 +907,12 @@ nsStyleSet::ResolveXULTreePseudoStyle(nsIContent* aParentContent, "Unexpected pseudo"); nsRuleWalker ruleWalker(mRuleTree); - nsPresContext *presContext = PresContext(); - - XULTreeRuleProcessorData data(presContext, aParentContent, &ruleWalker, + XULTreeRuleProcessorData data(PresContext(), aParentContent, &ruleWalker, aPseudoTag, aComparator); FileRules(EnumRulesMatching, &data, aParentContent, &ruleWalker); - return GetContext(presContext, aParentContext, ruleWalker.CurrentNode(), + return GetContext(aParentContext, ruleWalker.CurrentNode(), aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree); } #endif @@ -1042,30 +1013,24 @@ nsStyleSet::GCRuleTrees() } already_AddRefed -nsStyleSet::ReParentStyleContext(nsPresContext* aPresContext, - nsStyleContext* aStyleContext, +nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext, nsStyleContext* aNewParentContext) { - NS_ASSERTION(aPresContext, "must have pres context"); - NS_ASSERTION(aStyleContext, "must have style context"); - - if (aPresContext && aStyleContext) { - if (aStyleContext->GetParent() == aNewParentContext) { - aStyleContext->AddRef(); - return aStyleContext; - } - else { // really a new parent - nsIAtom* pseudoTag = aStyleContext->GetPseudo(); - nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); - nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); - - already_AddRefed result = - GetContext(aPresContext, aNewParentContext, ruleNode, pseudoTag, - pseudoType); - return result; - } + if (!aStyleContext) { + NS_NOTREACHED("must have style context"); + return nsnull; } - return nsnull; + + if (aStyleContext->GetParent() == aNewParentContext) { + aStyleContext->AddRef(); + return aStyleContext; + } + + nsIAtom* pseudoTag = aStyleContext->GetPseudo(); + nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); + nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); + + return GetContext(aNewParentContext, ruleNode, pseudoTag, pseudoType); } struct StatefulData : public StateRuleProcessorData { diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 4d56e1238ab8..574baa4df0bb 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -173,9 +173,8 @@ class nsStyleSet // The new context will be the same as the old if the new parent is the // same as the old parent. already_AddRefed - ReParentStyleContext(nsPresContext* aPresContext, - nsStyleContext* aStyleContext, - nsStyleContext* aNewParentContext); + ReparentStyleContext(nsStyleContext* aStyleContext, + nsStyleContext* aNewParentContext); // Test if style is dependent on a document state. PRBool HasDocumentStateDependentStyle(nsPresContext* aPresContext, @@ -336,11 +335,11 @@ class nsStyleSet RuleProcessorData* aData, PRBool aWalkAllXBLStylesheets); - already_AddRefed GetContext(nsPresContext* aPresContext, - nsStyleContext* aParentContext, - nsRuleNode* aRuleNode, - nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType); + already_AddRefed + GetContext(nsStyleContext* aParentContext, + nsRuleNode* aRuleNode, + nsIAtom* aPseudoTag, + nsCSSPseudoElements::Type aPseudoType); nsPresContext* PresContext() { return mRuleTree->GetPresContext(); } From ca65e30e9c3b0addf6bef4a593b4a8fa17f21041 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Thu, 1 Apr 2010 23:07:43 -0700 Subject: [PATCH 63/69] Bug 494117: Mechanically change 'ReParent' to 'Reparent' throughout the tree. r=bzbarsky --- layout/base/nsCSSFrameConstructor.cpp | 2 +- layout/base/nsFrameManager.cpp | 12 ++++++------ layout/base/nsFrameManager.h | 2 +- layout/forms/nsFieldSetFrame.cpp | 10 +++++----- layout/generic/nsFirstLetterFrame.cpp | 2 +- layout/generic/nsFrame.cpp | 2 +- layout/generic/nsInlineFrame.cpp | 24 ++++++++++++------------ layout/style/nsTransitionManager.cpp | 2 +- toolkit/xre/nsNativeAppSupportWin.cpp | 1 - tools/trace-malloc/spacecategory.c | 4 ++-- 10 files changed, 30 insertions(+), 31 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 63e4319bca5d..749705520b15 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -422,7 +422,7 @@ ReparentFrame(nsFrameManager* aFrameManager, nsIFrame* aFrame) { aFrame->SetParent(aNewParentFrame); - aFrameManager->ReParentStyleContext(aFrame); + aFrameManager->ReparentStyleContext(aFrame); if (aFrame->GetStateBits() & (NS_FRAME_HAS_VIEW | NS_FRAME_HAS_CHILD_WITH_VIEW)) { // No need to walk up the tree, since the bits are already set diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index e8db21b0f9c5..c5c566deea07 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -757,7 +757,7 @@ TryStartingTransition(nsPresContext *aPresContext, nsIContent *aContent, } nsresult -nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) +nsFrameManager::ReparentStyleContext(nsIFrame* aFrame) { if (nsGkAtoms::placeholderFrame == aFrame->GetType()) { // Also reparent the out-of-flow @@ -765,7 +765,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame); NS_ASSERTION(outOfFlow, "no out-of-flow frame"); - ReParentStyleContext(outOfFlow); + ReparentStyleContext(outOfFlow); } // DO NOT verify the style tree before reparenting. The frame @@ -781,7 +781,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) &providerIsChild); nsStyleContext* newParentContext = nsnull; if (providerIsChild) { - ReParentStyleContext(providerFrame); + ReparentStyleContext(providerFrame); newParentContext = providerFrame->GetStyleContext(); providerChild = providerFrame; } else if (providerFrame) { @@ -841,7 +841,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) if (newContext) { if (newContext != oldContext) { // We probably don't want to initiate transitions from - // ReParentStyleContext, since we call it during frame + // ReparentStyleContext, since we call it during frame // construction rather than in response to dynamic changes. // Also see the comment at the start of // nsTransitionManager::ConsiderStartingTransition. @@ -886,7 +886,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) } #endif - ReParentStyleContext(child); + ReparentStyleContext(child); } child = child->GetNextSibling(); @@ -906,7 +906,7 @@ nsFrameManager::ReParentStyleContext(nsIFrame* aFrame) nsIFrame* sib = static_cast (aFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling())); if (sib) { - ReParentStyleContext(sib); + ReparentStyleContext(sib); } } diff --git a/layout/base/nsFrameManager.h b/layout/base/nsFrameManager.h index d8b184788695..d26909b6f309 100644 --- a/layout/base/nsFrameManager.h +++ b/layout/base/nsFrameManager.h @@ -148,7 +148,7 @@ public: * * @param aFrame the root of the subtree to reparent. Must not be null. */ - NS_HIDDEN_(nsresult) ReParentStyleContext(nsIFrame* aFrame); + NS_HIDDEN_(nsresult) ReparentStyleContext(nsIFrame* aFrame); /* * Re-resolve the style contexts for a frame tree, building diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index d6486ec260d9..dbea8cc62ab2 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -120,7 +120,7 @@ public: protected: virtual PRIntn GetSkipSides() const; - void ReParentFrameList(const nsFrameList& aFrameList); + void ReparentFrameList(const nsFrameList& aFrameList); nsIFrame* mLegendFrame; nsIFrame* mContentFrame; @@ -621,7 +621,7 @@ nsFieldSetFrame::AppendFrames(nsIAtom* aListName, nsFrameList& aFrameList) { // aFrameList is not allowed to contain "the legend" for this fieldset - ReParentFrameList(aFrameList); + ReparentFrameList(aFrameList); return mContentFrame->AppendFrames(aListName, aFrameList); } @@ -635,7 +635,7 @@ nsFieldSetFrame::InsertFrames(nsIAtom* aListName, "inserting after sibling frame with different parent"); // aFrameList is not allowed to contain "the legend" for this fieldset - ReParentFrameList(aFrameList); + ReparentFrameList(aFrameList); if (NS_UNLIKELY(aPrevFrame == mLegendFrame)) { aPrevFrame = nsnull; } @@ -665,14 +665,14 @@ NS_IMETHODIMP nsFieldSetFrame::GetAccessible(nsIAccessible** aAccessible) #endif void -nsFieldSetFrame::ReParentFrameList(const nsFrameList& aFrameList) +nsFieldSetFrame::ReparentFrameList(const nsFrameList& aFrameList) { nsFrameManager* frameManager = PresContext()->FrameManager(); for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) { NS_ASSERTION(mLegendFrame || e.get()->GetType() != nsGkAtoms::legendFrame, "The fieldset's legend is not allowed in this list"); e.get()->SetParent(mContentFrame); - frameManager->ReParentStyleContext(e.get()); + frameManager->ReparentStyleContext(e.get()); } mContentFrame->AddStateBits(GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW); } diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 08d38947975c..47ffdefc0647 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -108,7 +108,7 @@ nsFirstLetterFrame::SetInitialChildList(nsIAtom* aListName, for (nsFrameList::Enumerator e(aChildList); !e.AtEnd(); e.Next()) { NS_ASSERTION(e.get()->GetParent() == this, "Unexpected parent"); - frameManager->ReParentStyleContext(e.get()); + frameManager->ReparentStyleContext(e.get()); } mFrames.SetFrames(aChildList); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e469b661f488..cbe4a9a2f7d8 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -5824,7 +5824,7 @@ nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent, } // Otherwise, walk up out of all anon boxes. For placeholder frames, walk out - // of all pseudo-elements as well. Otherwise ReParentStyleContext could cause + // of all pseudo-elements as well. Otherwise ReparentStyleContext could cause // style data to be out of sync with the frame tree. nsIFrame* parent = aProspectiveParent; do { diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 927392224eb9..40b949462bdd 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -304,7 +304,7 @@ nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer, } static void -ReParentChildListStyle(nsPresContext* aPresContext, +ReparentChildListStyle(nsPresContext* aPresContext, const nsFrameList::Slice& aFrames, nsIFrame* aParentFrame) { @@ -312,7 +312,7 @@ ReParentChildListStyle(nsPresContext* aPresContext, for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) { NS_ASSERTION(e.get()->GetParent() == aParentFrame, "Bogus parentage"); - frameManager->ReParentStyleContext(e.get()); + frameManager->ReparentStyleContext(e.get()); } } @@ -374,7 +374,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext, // we reparent the style contexts when we set their parents in // nsInlineFrame::ReflowFrames and nsInlineFrame::ReflowInlineFrame. if (aReflowState.mLineLayout->GetInFirstLine()) { - ReParentChildListStyle(aPresContext, newFrames, this); + ReparentChildListStyle(aPresContext, newFrames, this); } } } @@ -522,7 +522,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, } frame->SetParent(this); if (inFirstLine) { - frameManager->ReParentStyleContext(frame); + frameManager->ReparentStyleContext(frame); } // We also need to check if frame has a next-in-flow. If it does, then set // its parent frame pointer, too. Otherwise, if we reflow frame and it's @@ -540,7 +540,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, } nextInFlow->SetParent(this); if (inFirstLine) { - frameManager->ReParentStyleContext(nextInFlow); + frameManager->ReparentStyleContext(nextInFlow); } } @@ -559,7 +559,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, if (mFrames.ContainsFrame(nextInFlow)) { nextInFlow->SetParent(this); if (inFirstLine) { - frameManager->ReParentStyleContext(nextInFlow); + frameManager->ReparentStyleContext(nextInFlow); } } else { @@ -744,7 +744,7 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext, for (nsIFrame* f = aFrame->GetNextSibling(); f; f = f->GetNextSibling()) { f->SetParent(this); if (lineLayout->GetInFirstLine()) { - aPresContext->FrameManager()->ReParentStyleContext(f); + aPresContext->FrameManager()->ReparentStyleContext(f); } } } @@ -1005,7 +1005,7 @@ nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowState& i // We are a first-line frame. Fixup the child frames // style-context that we just pulled. NS_ASSERTION(frame->GetParent() == this, "Incorrect parent?"); - aPresContext->FrameManager()->ReParentStyleContext(frame); + aPresContext->FrameManager()->ReparentStyleContext(frame); } return frame; } @@ -1035,7 +1035,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, } const nsFrameList::Slice& newFrames = mFrames.InsertFrames(this, nsnull, *prevOverflowFrames); - ReParentChildListStyle(aPresContext, newFrames, this); + ReparentChildListStyle(aPresContext, newFrames, this); } } @@ -1046,7 +1046,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, const nsFrameList::Slice& newFrames = mFrames.AppendFrames(nsnull, *overflowFrames); - ReParentChildListStyle(aPresContext, newFrames, this); + ReparentChildListStyle(aPresContext, newFrames, this); } // Set our own reflow state (additional state above and beyond @@ -1108,7 +1108,7 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext, SetStyleContext(newSC); // Re-resolve all children - ReParentChildListStyle(aPresContext, mFrames, this); + ReparentChildListStyle(aPresContext, mFrames, this); } } } @@ -1135,7 +1135,7 @@ nsFirstLineFrame::PullOverflowsFromPrevInFlow() // Assume that our prev-in-flow has the same line container that we do. const nsFrameList::Slice& newFrames = mFrames.InsertFrames(this, nsnull, *prevOverflowFrames); - ReParentChildListStyle(PresContext(), newFrames, this); + ReparentChildListStyle(PresContext(), newFrames, this); } } } diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 8cf6305c242b..52533b5e77e5 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -393,7 +393,7 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement, NS_PRECONDITION(aOldStyleContext->GetPseudo() == aNewStyleContext->GetPseudo(), "pseudo type mismatch"); - // If we were called from ReParentStyleContext, this assertion would + // If we were called from ReparentStyleContext, this assertion would // actually fire. If we need to be called from there, we can probably // just remove it; the condition probably isn't critical, although // it's worth thinking about some more. diff --git a/toolkit/xre/nsNativeAppSupportWin.cpp b/toolkit/xre/nsNativeAppSupportWin.cpp index 6ed9a16c6a2d..707028373288 100644 --- a/toolkit/xre/nsNativeAppSupportWin.cpp +++ b/toolkit/xre/nsNativeAppSupportWin.cpp @@ -343,7 +343,6 @@ private: static void ActivateLastWindow(); static nsresult OpenWindow( const char *urlstr, const char *args ); static nsresult OpenBrowserWindow(); - static nsresult ReParent( nsISupports *window, HWND newParent ); static void SetupSysTrayIcon(); static void RemoveSysTrayIcon(); diff --git a/tools/trace-malloc/spacecategory.c b/tools/trace-malloc/spacecategory.c index c71b7b27addb..bac61a829ef8 100644 --- a/tools/trace-malloc/spacecategory.c +++ b/tools/trace-malloc/spacecategory.c @@ -122,7 +122,7 @@ AddChild(STCategoryNode * parent, STCategoryNode * child) } int -ReParent(STCategoryNode * parent, STCategoryNode * child) +Reparent(STCategoryNode * parent, STCategoryNode * child) { PRUint32 i; @@ -312,7 +312,7 @@ ProcessCategoryParentRule(STCategoryRule * parentRule, STCategoryNode * root, ** we would have created it as the child of root. Now we need to ** remove it from root's child list and add it into this node */ - ReParent(node, child); + Reparent(node, child); } } From 1ee1380a7ad62da8f227f21993623106f3eb96e1 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Thu, 1 Apr 2010 23:53:38 -0700 Subject: [PATCH 64/69] Bug 531340 - AudioLoop() fix; don't dereference nsAutoPtr after forget(). r=bustage-fix --- content/media/ogg/nsOggPlayStateMachine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/media/ogg/nsOggPlayStateMachine.cpp b/content/media/ogg/nsOggPlayStateMachine.cpp index a1d512828d60..558a74d5328b 100644 --- a/content/media/ogg/nsOggPlayStateMachine.cpp +++ b/content/media/ogg/nsOggPlayStateMachine.cpp @@ -368,13 +368,13 @@ void nsOggPlayStateMachine::AudioLoop() mAudioStream->Write(sound->mAudioData, sound->AudioDataLength(), PR_TRUE); + mAudioEndTime = sound->mTime + sound->mDuration; } else { mReader->mAudioQueue.PushFront(sound); sound.forget(); } } } - mAudioEndTime = sound->mTime + sound->mDuration; sound = nsnull; if (mReader->mAudioQueue.AtEndOfStream()) { From c40f0cea4471f3008678ff76ca5fa323593ccbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Fri, 2 Apr 2010 09:17:59 +0200 Subject: [PATCH 65/69] Bug 556482 - Remove dead onDestroy method. r=gavin --- browser/base/content/nsContextMenu.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 976ab11d8fd7..9662b9bb64c1 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -100,10 +100,6 @@ function nsContextMenu(aXulMenu, aBrowser) { // Prototype for nsContextMenu "class." nsContextMenu.prototype = { - // onDestroy is a no-op at this point. - onDestroy: function () { - }, - // Initialize context menu. initMenu: function CM_initMenu(aPopup, aBrowser) { this.menu = aPopup; From 49fa584b50563f4e5010d9e86c569573a56227d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Fri, 2 Apr 2010 09:19:57 +0200 Subject: [PATCH 66/69] Bug 555337 - Capture tab previews only when needed. r=gavin --- browser/base/content/browser-tabPreviews.js | 17 +++++++++++++++++ browser/base/content/browser.js | 2 -- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/browser/base/content/browser-tabPreviews.js b/browser/base/content/browser-tabPreviews.js index 38fc6fc99d88..3a31aa7cc948 100644 --- a/browser/base/content/browser-tabPreviews.js +++ b/browser/base/content/browser-tabPreviews.js @@ -44,18 +44,26 @@ var tabPreviews = { aspectRatio: 0.5625, // 16:9 init: function tabPreviews_init() { + if (this._selectedTab) + return; + this._selectedTab = gBrowser.selectedTab; + this.width = Math.ceil(screen.availWidth / 5.75); this.height = Math.round(this.width * this.aspectRatio); + window.addEventListener("unload", this, false); gBrowser.tabContainer.addEventListener("TabSelect", this, false); gBrowser.tabContainer.addEventListener("SSTabRestored", this, false); }, uninit: function tabPreviews_uninit() { + window.removeEventListener("unload", this, false); gBrowser.tabContainer.removeEventListener("TabSelect", this, false); gBrowser.tabContainer.removeEventListener("SSTabRestored", this, false); this._selectedTab = null; }, get: function tabPreviews_get(aTab) { + this.init(); + if (aTab.__thumbnail_lastURI && aTab.__thumbnail_lastURI != aTab.linkedBrowser.currentURI.spec) { aTab.__thumbnail = null; @@ -64,6 +72,8 @@ var tabPreviews = { return aTab.__thumbnail || this.capture(aTab, !aTab.hasAttribute("busy")); }, capture: function tabPreviews_capture(aTab, aStore) { + this.init(); + var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); thumbnail.mozOpaque = true; thumbnail.height = this.height; @@ -105,6 +115,9 @@ var tabPreviews = { case "SSTabRestored": this.capture(event.target, true); break; + case "unload": + this.uninit(); + break; } } }; @@ -225,6 +238,8 @@ var ctrlTab = { init: function ctrlTab_init() { if (!this._recentlyUsedTabs) { + tabPreviews.init(); + this._recentlyUsedTabs = [gBrowser.selectedTab]; this._init(true); } @@ -577,6 +592,8 @@ var allTabs = { return; this._initiated = true; + tabPreviews.init(); + Array.forEach(gBrowser.tabs, function (tab) { this._addPreview(tab); }, this); diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 2c1c52810ea1..fd57222961f1 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1307,7 +1307,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) { // themselves. gBrowser.addEventListener("command", BrowserOnCommand, false); - tabPreviews.init(); ctrlTab.readPref(); gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false); gPrefService.addObserver(allTabs.prefName, allTabs, false); @@ -1373,7 +1372,6 @@ function BrowserShutdown() gPrefService.removeObserver(ctrlTab.prefName, ctrlTab); gPrefService.removeObserver(allTabs.prefName, allTabs); - tabPreviews.uninit(); ctrlTab.uninit(); allTabs.uninit(); From 986b546ddd6a31dc88651f58c1c4bb70af809f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Fri, 2 Apr 2010 09:20:42 +0200 Subject: [PATCH 67/69] use Services.* in browser chrome tests --- .../base/content/test/browser_bug484315.js | 4 +--- .../content/test/browser_getshortcutoruri.js | 10 +++----- browser/base/content/test/browser_pageInfo.js | 10 +++----- .../test/browser_pluginnotification.js | 11 +++------ .../test/browser_sanitize-download-history.js | 24 ++++++++----------- .../content/test/browser_sanitizeDialog.js | 20 +++++++--------- .../test/browser_sanitizeDialog_treeView.js | 20 +++++++--------- .../preferences/tests/browser_bug410900.js | 7 ++---- .../preferences/tests/privacypane_tests.js | 18 ++++++-------- .../browser_privatebrowsing_beforeunload.js | 8 ++----- ...rowser_privatebrowsing_certexceptionsui.js | 12 ++++------ ...wser_privatebrowsing_commandline_toggle.js | 6 ++--- ...wser_privatebrowsing_cookieacceptdialog.js | 6 ++--- ...browser_privatebrowsing_downloadmonitor.js | 8 ++----- .../browser_privatebrowsing_forgetthissite.js | 16 ++++++------- .../browser_privatebrowsing_transition.js | 6 ++--- .../browser/browser_privatebrowsing_ui.js | 6 ++--- .../browser_privatebrowsing_urlbarundo.js | 6 ++--- .../browser_privatebrowsing_viewsource.js | 20 +++++++--------- .../components/search/test/browser_415700.js | 9 +++---- .../components/search/test/browser_426329.js | 9 +++---- .../components/search/test/browser_483086.js | 11 ++++----- .../test/browser/browser_248970_a.js | 6 ++--- .../test/browser/browser_354894.js | 10 +++----- .../test/browser/browser_394759.js | 4 +--- .../browser/browser_394759_privatebrowsing.js | 10 +++----- .../test/browser/browser_423132.js | 4 +--- .../test/browser/browser_448741.js | 9 ++++--- .../test/browser/browser_461634.js | 4 +--- .../test/browser/browser_464199.js | 4 +--- .../test/browser/browser_465223.js | 4 +--- .../test/browser/browser_477657.js | 4 +--- .../test/browser/browser_480148.js | 4 +--- .../test/browser/browser_490040.js | 22 +++++++---------- .../test/browser/browser_491168.js | 7 ++---- .../test/browser/browser_491577.js | 4 +--- .../test/browser/browser_493467.js | 4 +--- .../test/browser/browser_495495.js | 4 +--- .../test/browser/browser_514751.js | 4 +--- .../test/browser/browser_522545.js | 4 +--- .../test/browser/browser_524745.js | 6 +---- .../test/browser/browser_526613.js | 12 ++++------ .../test/browser/browser_528776.js | 3 +-- browser/fuel/test/browser_Application.js | 11 ++------- .../fuel/test/browser_ApplicationQuitting.js | 11 ++++----- browser/fuel/test/browser_Bookmarks.js | 6 +---- docshell/test/browser/browser_bug134911.js | 6 +---- docshell/test/browser/browser_bug349769.js | 3 +-- docshell/test/browser/browser_bug388121-1.js | 3 +-- docshell/test/browser/browser_bug388121-2.js | 3 +-- docshell/test/browser/browser_bug92473.js | 6 +---- .../test/browser/browser_bug414214.js | 17 ++++--------- .../browser/browser_nsIDownloadManagerUI.js | 6 ++--- .../test/browser/browser_passwordmgr_sort.js | 18 +++++--------- .../test/browser/browser_passwordmgrdlg.js | 18 +++++--------- .../browser/browser_aboutCrashesResubmit.js | 10 +++----- .../test/browser/browser_bug510909.js | 8 ++----- 57 files changed, 169 insertions(+), 337 deletions(-) diff --git a/browser/base/content/test/browser_bug484315.js b/browser/base/content/test/browser_bug484315.js index ff395b7dc0e4..fb23ae33a43d 100644 --- a/browser/base/content/test/browser_bug484315.js +++ b/browser/base/content/test/browser_bug484315.js @@ -1,8 +1,6 @@ function test() { var contentWin = window.open("about:blank", "", "width=100,height=100"); - var enumerator = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + var enumerator = Services.wm.getEnumerator("navigator:browser"); while (enumerator.hasMoreElements()) { let win = enumerator.getNext(); diff --git a/browser/base/content/test/browser_getshortcutoruri.js b/browser/base/content/test/browser_getshortcutoruri.js index 52dfc2912094..1b319ded812d 100644 --- a/browser/base/content/test/browser_getshortcutoruri.js +++ b/browser/base/content/test/browser_getshortcutoruri.js @@ -100,8 +100,6 @@ function test() { var gBMFolder = null; var gAddedEngines = []; function setupKeywords() { - var searchService = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); gBMFolder = Application.bookmarks.menu.addFolder("keyword-test"); for each (var item in testData) { var data = item[0]; @@ -113,8 +111,8 @@ function setupKeywords() { } if (data instanceof searchKeywordData) { - searchService.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec); - var addedEngine = searchService.getEngineByName(data.keyword); + Services.search.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec); + var addedEngine = Services.search.getEngineByName(data.keyword); if (data.postData) { var [paramName, paramValue] = data.postData.split("="); addedEngine.addParam(paramName, paramValue, null); @@ -126,8 +124,6 @@ function setupKeywords() { } function cleanupKeywords() { - var searchService = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); gBMFolder.remove(); - gAddedEngines.map(searchService.removeEngine); + gAddedEngines.map(Services.search.removeEngine); } diff --git a/browser/base/content/test/browser_pageInfo.js b/browser/base/content/test/browser_pageInfo.js index 766223cebb35..9c088840d992 100644 --- a/browser/base/content/test/browser_pageInfo.js +++ b/browser/base/content/test/browser_pageInfo.js @@ -1,5 +1,3 @@ -var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - function test() { waitForExplicitFinish(); @@ -8,7 +6,7 @@ function test() { gBrowser.selectedBrowser.addEventListener("load", function () { gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); pageInfo = BrowserPageInfo(); - obs.addObserver(observer, "page-info-dialog-loaded", false); + Services.obs.addObserver(observer, "page-info-dialog-loaded", false); }, true); content.location = "https://example.com/browser/browser/base/content/test/feed_tab.html"; @@ -29,7 +27,7 @@ function test() { break; case 2: atTest++; - obs.removeObserver(observer, "page-info-dialog-loaded"); + Services.obs.removeObserver(observer, "page-info-dialog-loaded"); testLockDoubleClick(); break; } @@ -76,9 +74,7 @@ function test() { } function testLockDoubleClick() { - var pageInfoDialogs = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("Browser:page-info"); + var pageInfoDialogs = Services.wm.getEnumerator("Browser:page-info"); var i = 0; while (pageInfoDialogs.hasMoreElements()) { i++; diff --git a/browser/base/content/test/browser_pluginnotification.js b/browser/base/content/test/browser_pluginnotification.js index 606e68e5d718..7c59e4622d33 100644 --- a/browser/base/content/test/browser_pluginnotification.js +++ b/browser/base/content/test/browser_pluginnotification.js @@ -4,8 +4,7 @@ var gTestBrowser = null; var gNextTest = null; function get_test_plugin() { - var ph = Components.classes["@mozilla.org/plugin/host;1"] - .getService(Components.interfaces.nsIPluginHost); + var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); var tags = ph.getPluginTags(); // Find the test plugin @@ -23,9 +22,7 @@ function WindowOpenListener(url, opencallback, closecallback) { this.opencallback = opencallback; this.closecallback = closecallback; - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.addListener(this); + Services.wm.addListener(this); } WindowOpenListener.prototype = { @@ -61,9 +58,7 @@ WindowOpenListener.prototype = { if (this.window != window) return; - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.removeListener(this); + Services.wm.removeListener(this); this.opencallback = null; this.window = null; this.domwindow = null; diff --git a/browser/base/content/test/browser_sanitize-download-history.js b/browser/base/content/test/browser_sanitize-download-history.js index 29af83417d1d..184b966de9a5 100644 --- a/browser/base/content/test/browser_sanitize-download-history.js +++ b/browser/base/content/test/browser_sanitize-download-history.js @@ -71,13 +71,11 @@ function test() let history = doc.getElementById("history-checkbox"); // Add download to DB - let ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); let file = Cc["@mozilla.org/file/directory_service;1"]. getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile); file.append("satitize-dm-test.file"); file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); - let testPath = ios.newFileURI(file).spec; + let testPath = Services.io.newFileURI(file).spec; let data = { name: "381603.patch", source: "https://bugzilla.mozilla.org/attachment.cgi?id=266520", @@ -142,22 +140,20 @@ function test() db.executeSimpleSQL("DELETE FROM moz_downloads"); // Close the UI if necessary - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - let win = ww.getWindowByName("Sanatize", null); + let win = Services.ww.getWindowByName("Sanatize", null); if (win && (win instanceof Ci.nsIDOMWindowInternal)) win.close(); // Start the test when the sanitize window loads - ww.registerNotification(function (aSubject, aTopic, aData) { - ww.unregisterNotification(arguments.callee); + Services.ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.unregisterNotification(arguments.callee); aSubject.QueryInterface(Ci.nsIDOMEventTarget) .addEventListener("DOMContentLoaded", doTest, false); }); // Let the methods that run onload finish before we test let doTest = function() setTimeout(function() { - let win = ww.getWindowByName("Sanitize", null) + let win = Services.ww.getWindowByName("Sanitize", null) .QueryInterface(Ci.nsIDOMWindowInternal); for (let i = 0; i < tests.length; i++) @@ -168,11 +164,11 @@ function test() }, 0); // Show the UI - ww.openWindow(window, - "chrome://browser/content/sanitize.xul", - "Sanitize", - "chrome,titlebar,centerscreen", - null); + Services.ww.openWindow(window, + "chrome://browser/content/sanitize.xul", + "Sanitize", + "chrome,titlebar,centerscreen", + null); waitForExplicitFinish(); } diff --git a/browser/base/content/test/browser_sanitizeDialog.js b/browser/base/content/test/browser_sanitizeDialog.js index 2d0d2531fa69..2b3e86b8a2ae 100644 --- a/browser/base/content/test/browser_sanitizeDialog.js +++ b/browser/base/content/test/browser_sanitizeDialog.js @@ -51,15 +51,13 @@ */ Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://mochikit/content/MochiKit/packed.js"); Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://browser/content/sanitize.js"); -const winWatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); const dm = Cc["@mozilla.org/download-manager;1"]. getService(Ci.nsIDownloadManager); const bhist = Cc["@mozilla.org/browser/global-history;2"]. @@ -540,7 +538,7 @@ WindowHelper.prototype = { if (aTopic != "domwindowopened") return; - winWatch.unregisterNotification(windowObserver); + Services.ww.unregisterNotification(windowObserver); var loaded = false; let win = aSubject.QueryInterface(Ci.nsIDOMWindow); @@ -597,12 +595,12 @@ WindowHelper.prototype = { }); }, false); } - winWatch.registerNotification(windowObserver); - winWatch.openWindow(null, - "chrome://browser/content/sanitize.xul", - "SanitizeDialog", - "chrome,titlebar,dialog,centerscreen,modal", - null); + Services.ww.registerNotification(windowObserver); + Services.ww.openWindow(null, + "chrome://browser/content/sanitize.xul", + "SanitizeDialog", + "chrome,titlebar,dialog,centerscreen,modal", + null); }, /** diff --git a/browser/base/content/test/browser_sanitizeDialog_treeView.js b/browser/base/content/test/browser_sanitizeDialog_treeView.js index 6c023f079d17..5b9be10d6fca 100644 --- a/browser/base/content/test/browser_sanitizeDialog_treeView.js +++ b/browser/base/content/test/browser_sanitizeDialog_treeView.js @@ -50,15 +50,13 @@ */ Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://mochikit/content/MochiKit/packed.js"); Cc["@mozilla.org/moz/jssubscript-loader;1"]. - getService(Components.interfaces.mozIJSSubScriptLoader). + getService(Ci.mozIJSSubScriptLoader). loadSubScript("chrome://browser/content/sanitize.js"); -const winWatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); const dm = Cc["@mozilla.org/download-manager;1"]. getService(Ci.nsIDownloadManager); const bhist = Cc["@mozilla.org/browser/global-history;2"]. @@ -622,7 +620,7 @@ function openWindow(aOnloadCallback) { if (aTopic != "domwindowopened") return; - winWatch.unregisterNotification(windowObserver); + Services.ww.unregisterNotification(windowObserver); let win = aSubject.QueryInterface(Ci.nsIDOMWindow); win.addEventListener("load", function onload(event) { win.removeEventListener("load", onload, false); @@ -641,12 +639,12 @@ function openWindow(aOnloadCallback) { }); }, false); } - winWatch.registerNotification(windowObserver); - winWatch.openWindow(null, - "chrome://browser/content/sanitize.xul", - "Sanitize", - "chrome,titlebar,dialog,centerscreen,modal", - null); + Services.ww.registerNotification(windowObserver); + Services.ww.openWindow(null, + "chrome://browser/content/sanitize.xul", + "Sanitize", + "chrome,titlebar,dialog,centerscreen,modal", + null); } /////////////////////////////////////////////////////////////////////////////// diff --git a/browser/components/preferences/tests/browser_bug410900.js b/browser/components/preferences/tests/browser_bug410900.js index 043d065608a3..bfb52303de1a 100644 --- a/browser/components/preferences/tests/browser_bug410900.js +++ b/browser/components/preferences/tests/browser_bug410900.js @@ -16,17 +16,14 @@ function test() { getService(Ci.nsIHandlerService); hserv.store(info); - var obs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - function observer(win, topic, data) { if (topic != "app-handler-pane-loaded") return; - obs.removeObserver(observer, "app-handler-pane-loaded"); + Services.obs.removeObserver(observer, "app-handler-pane-loaded"); runTest(win); } - obs.addObserver(observer, "app-handler-pane-loaded", false); + Services.obs.addObserver(observer, "app-handler-pane-loaded", false); openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences", "chrome,titlebar,toolbar,centerscreen,dialog=no", "paneApplications"); diff --git a/browser/components/preferences/tests/privacypane_tests.js b/browser/components/preferences/tests/privacypane_tests.js index 1c20c619271a..eacb712e4355 100644 --- a/browser/components/preferences/tests/privacypane_tests.js +++ b/browser/components/preferences/tests/privacypane_tests.js @@ -36,28 +36,26 @@ * ***** END LICENSE BLOCK ***** */ function runTestOnPrivacyPrefPane(testFunc) { - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); let observer = { observe: function(aSubject, aTopic, aData) { if (aTopic == "domwindowopened") { - ww.unregisterNotification(this); + Services.ww.unregisterNotification(this); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function() { win.removeEventListener("load", arguments.callee, false); testFunc(dialog.document.defaultView); - ww.registerNotification(observer); + Services.ww.registerNotification(observer); dialog.close(); }, false); } else if (aTopic == "domwindowclosed") { - ww.unregisterNotification(this); + Services.ww.unregisterNotification(this); testRunner.runNext(); } } }; - ww.registerNotification(observer); + Services.ww.registerNotification(observer); let dialog = openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences", "chrome,titlebar,toolbar,centerscreen,dialog=no", "panePrivacy"); @@ -528,10 +526,8 @@ function reset_preferences(win) { let testRunner; function run_test_subset(subset) { - let psvc = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); - let instantApplyOrig = psvc.getBoolPref("browser.preferences.instantApply"); - psvc.setBoolPref("browser.preferences.instantApply", true); + let instantApplyOrig = Services.prefs.getBoolPref("browser.preferences.instantApply"); + Services.prefs.setBoolPref("browser.preferences.instantApply", true); waitForExplicitFinish(); @@ -541,7 +537,7 @@ function run_test_subset(subset) { runNext: function() { if (this.counter == this.tests.length) { // cleanup - psvc.setBoolPref("browser.preferences.instantApply", instantApplyOrig); + Services.prefs.setBoolPref("browser.preferences.instantApply", instantApplyOrig); finish(); } else { let self = this; diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js index 401a0e7df7c7..6eab0933918a 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_beforeunload.js @@ -57,9 +57,7 @@ function test() { dialogWin.document.documentElement.getButton("cancel").click(); } - Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService) - .addObserver(promptObserver, "common-dialog-loaded", false); + Services.obs.addObserver(promptObserver, "common-dialog-loaded", false); waitForExplicitFinish(); let browser1 = gBrowser.getBrowserForTab(gBrowser.addTab()); @@ -150,9 +148,7 @@ function test() { gBrowser.removeTab(gBrowser.tabContainer.lastChild); gBrowser.removeTab(gBrowser.tabContainer.lastChild); - Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService) - .removeObserver(promptObserver, "common-dialog-loaded", false); + Services.obs.removeObserver(promptObserver, "common-dialog-loaded", false); finish(); } for (let i = 0; i < gBrowser.browsers.length; ++i) diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js index 6db7821af7aa..7ba575a65802 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js @@ -63,10 +63,8 @@ function test() { prefetchCert: true, }; function testCheckbox() { - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { - obsSvc.removeObserver(arguments.callee, "cert-exception-ui-ready", false); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false); ok(win.gCert, "The certificate information should be available now"); let checkbox = win.document.getElementById("permanent"); @@ -90,10 +88,8 @@ function test() { prefetchCert: true, }; function testCheckbox() { - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { - obsSvc.removeObserver(arguments.callee, "cert-exception-ui-ready", false); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false); ok(win.gCert, "The certificate information should be available now"); let checkbox = win.document.getElementById("permanent"); diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js index 873203cfde07..360953b02f94 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_commandline_toggle.js @@ -42,8 +42,6 @@ function test() { // initialization let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); waitForExplicitFinish(); @@ -120,7 +118,7 @@ function test() { function observer(aSubject, aTopic, aData) { isnot(aTopic, "domwindowopened", "The -private-toggle argument should be silent"); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); let tab = gBrowser.selectedTab; let browser = gBrowser.getBrowserForTab(tab); @@ -149,7 +147,7 @@ function test() { let newTab = gBrowser.addTab(); gBrowser.removeTab(tab); - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); finish(); }, true); }, true); diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js index f0d23707d36a..d877a328056e 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cookieacceptdialog.js @@ -42,8 +42,6 @@ function test() { // initialization let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); let cp = Cc["@mozilla.org/embedcomp/cookieprompt-service;1"]. getService(Ci.nsICookiePromptService); @@ -54,7 +52,7 @@ function test() { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMWindow); win.addEventListener("load", function onLoad(event) { win.removeEventListener("load", onLoad, false); @@ -76,7 +74,7 @@ function test() { }); }, false); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); let remember = {}; const time = (new Date("Jan 1, 2030")).getTime() / 1000; diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js index 8ec728d14def..f61a601092b3 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadmonitor.js @@ -46,8 +46,6 @@ function test() { getService(Ci.nsIDownloadManager); if (!gDownloadMgr) gDownloadMgr = dm; - let iosvc = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); let panel = document.getElementById("download-monitor"); waitForExplicitFinish(); @@ -159,10 +157,8 @@ function addDownload(dm, aParams) return dl; } -function createURI(aObj) -{ - let ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); +function createURI(aObj) { + let ios = Services.io; return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) : ios.newURI(aObj, null, null); } diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js index 804cd41f7a83..9a610e6ae313 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_forgetthissite.js @@ -42,8 +42,6 @@ function test() { // initialization let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); waitForExplicitFinish(); // Add a history entry. @@ -59,7 +57,7 @@ function test() { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow); organizer.addEventListener("load", function onLoad(event) { organizer.removeEventListener("load", onLoad, false); @@ -103,12 +101,12 @@ function test() { }, false); } - ww.registerNotification(observer); - ww.openWindow(null, - "chrome://browser/content/places/places.xul", - "", - "chrome,toolbar=yes,dialog=no,resizable", - null); + Services.ww.registerNotification(observer); + Services.ww.openWindow(null, + "chrome://browser/content/places/places.xul", + "", + "chrome,toolbar=yes,dialog=no,resizable", + null); } testForgetThisSiteVisibility(true, function() { diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js index 09e469384cbf..c494f3f9df7c 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_transition.js @@ -42,8 +42,6 @@ let cookieManager = Cc["@mozilla.org/cookiemanager;1"]. getService(Ci.nsICookieManager2); let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); -let _obs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); let observerNotified = 0, firstUnloadFired = 0, secondUnloadFired = 0; function pbObserver(aSubject, aTopic, aData) { @@ -56,7 +54,7 @@ function pbObserver(aSubject, aTopic, aData) { is(firstUnloadFired, 1, "The first unload event should have been processed by now"); break; case "exit": - _obs.removeObserver(pbObserver, "private-browsing"); + Services.obs.removeObserver(pbObserver, "private-browsing"); observerNotified++; is(observerNotified, 2, "This should be the second notification"); is(secondUnloadFired, 1, "The second unload event should have been processed by now"); @@ -66,7 +64,7 @@ function pbObserver(aSubject, aTopic, aData) { function test() { waitForExplicitFinish(); - _obs.addObserver(pbObserver, "private-browsing", false); + Services.obs.addObserver(pbObserver, "private-browsing", false); is(gBrowser.tabs.length, 1, "There should only be one tab"); let testTab = gBrowser.addTab(); gBrowser.selectedTab = testTab; diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js index bc439e726e49..d210dac2a958 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js @@ -48,9 +48,7 @@ function test() { if (aTopic == "private-browsing") observerData = aData; } - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.addObserver(observer, "private-browsing", false); + Services.obs.addObserver(observer, "private-browsing", false); let pbMenuItem = document.getElementById("privateBrowsingItem"); // add a new blank tab to ensure the title can be meaningfully compared later gBrowser.selectedTab = gBrowser.addTab(); @@ -92,6 +90,6 @@ function test() { // cleanup gBrowser.removeCurrentTab(); - os.removeObserver(observer, "private-browsing"); + Services.obs.removeObserver(observer, "private-browsing"); gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session"); } diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js index 0e6df75dc621..acf1581b5801 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarundo.js @@ -39,9 +39,7 @@ function test() { // initialization - let prefBranch = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch); - prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true); + Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true); let pb = Cc["@mozilla.org/privatebrowsing;1"]. getService(Ci.nsIPrivateBrowsingService); @@ -61,6 +59,6 @@ function test() { "The undo history of the URL bar should be cleared after leaving the private browsing mode"); // cleanup - prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session"); + Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session"); } diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js index 9e5b1350af4e..c6d6b3504f3f 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js @@ -50,13 +50,11 @@ function test() { aboutBrowser.addEventListener("load", function () { aboutBrowser.removeEventListener("load", arguments.callee, true); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); function observer(aSubject, aTopic, aData) { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function () { @@ -71,7 +69,7 @@ function test() { }, true); }, false); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); openViewSource(); @@ -84,14 +82,14 @@ function test() { function observer(aSubject, aTopic, aData) { if (aTopic == "domwindowclosed") { ok(true, "Entering the private browsing mode should close the view source window"); - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); step2(); } else if (aTopic == "domwindowopened") ok(false, "Entering the private browsing mode should not open any view source window"); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); gBrowser.addTabsProgressListener({ onLocationChange: function() {}, @@ -124,7 +122,7 @@ function test() { if (aTopic != "domwindowopened") return; - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function () { @@ -139,7 +137,7 @@ function test() { }, true); }, false); } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); openViewSource(); } @@ -151,12 +149,12 @@ function test() { if (aTopic == "domwindowclosed") { ok(true, "Leaving the private browsing mode should close the existing view source window"); if (++events == 2) - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); } else if (aTopic == "domwindowopened") { ok(true, "Leaving the private browsing mode should restore the previous view source window"); if (++events == 2) - ww.unregisterNotification(observer); + Services.ww.unregisterNotification(observer); let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("load", function () { @@ -177,7 +175,7 @@ function test() { }, false); } } - ww.registerNotification(observer); + Services.ww.registerNotification(observer); // exit private browsing mode pb.privateBrowsingEnabled = false; diff --git a/browser/components/search/test/browser_415700.js b/browser/components/search/test/browser_415700.js index 44c872aa95df..a5899e749918 100644 --- a/browser/components/search/test/browser_415700.js +++ b/browser/components/search/test/browser_415700.js @@ -33,10 +33,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -var gSS = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); -var gObs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); +var gSS = Services.search; function observers(aSubject, aTopic, aData) { switch (aData) { @@ -54,7 +51,7 @@ function observers(aSubject, aTopic, aData) { function test() { waitForExplicitFinish(); - gObs.addObserver(observers, "browser-search-engine-modified", false); + Services.obs.addObserver(observers, "browser-search-engine-modified", false); gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml", Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC", @@ -83,6 +80,6 @@ function test4() { ok(engine, "An engine is present."); isnot(engine.name, "Foo", "Current engine reset after removal"); - gObs.removeObserver(observers, "browser-search-engine-modified"); + Services.obs.removeObserver(observers, "browser-search-engine-modified"); finish(); } diff --git a/browser/components/search/test/browser_426329.js b/browser/components/search/test/browser_426329.js index 8d38693623a5..2cab4518fccf 100644 --- a/browser/components/search/test/browser_426329.js +++ b/browser/components/search/test/browser_426329.js @@ -8,10 +8,7 @@ function test() { searchBar.value = "test"; - var obs = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - var ss = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); + var ss = Services.search; function observer(aSub, aTopic, aData) { switch (aData) { @@ -26,13 +23,13 @@ function test() { testReturn(); break; case "engine-removed": - obs.removeObserver(observer, "browser-search-engine-modified"); + Services.obs.removeObserver(observer, "browser-search-engine-modified"); finish(); break; } } - obs.addObserver(observer, "browser-search-engine-modified", false); + Services.obs.addObserver(observer, "browser-search-engine-modified", false); ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml", Ci.nsISearchEngine.DATA_XML, "data:image/x-icon,%00", false); diff --git a/browser/components/search/test/browser_483086.js b/browser/components/search/test/browser_483086.js index f449ebe73228..536a0e5ff577 100644 --- a/browser/components/search/test/browser_483086.js +++ b/browser/components/search/test/browser_483086.js @@ -33,8 +33,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -let gSS = Cc["@mozilla.org/browser/search-service;1"]. - getService(Ci.nsIBrowserSearchService); +let gSS = Services.search; let gObs = Cc["@mozilla.org/observer-service;1"]. getService(Ci.nsIObserverService); @@ -51,13 +50,13 @@ function test() { gSS.removeEngine(engine); break; case "engine-removed": - gObs.removeObserver(observer, "browser-search-engine-modified"); + Services.obs.removeObserver(observer, "browser-search-engine-modified"); test2(); break; } } - gObs.addObserver(observer, "browser-search-engine-modified", false); + Services.obs.addObserver(observer, "browser-search-engine-modified", false); gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-1.xml", Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00", false); @@ -73,13 +72,13 @@ function test2() { gSS.removeEngine(engine); break; case "engine-removed": - gObs.removeObserver(observer, "browser-search-engine-modified"); + Services.obs.removeObserver(observer, "browser-search-engine-modified"); finish(); break; } } - gObs.addObserver(observer, "browser-search-engine-modified", false); + Services.obs.addObserver(observer, "browser-search-engine-modified", false); gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/483086-2.xml", Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00", false); diff --git a/browser/components/sessionstore/test/browser/browser_248970_a.js b/browser/components/sessionstore/test/browser/browser_248970_a.js index 4937d07694be..0184d804be7c 100644 --- a/browser/components/sessionstore/test/browser/browser_248970_a.js +++ b/browser/components/sessionstore/test/browser/browser_248970_a.js @@ -63,13 +63,11 @@ function test() { return -1; } - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); function waitForFileExistence(aMessage, aDoNext) { const TOPIC = "sessionstore-state-write-complete"; - os.addObserver(function (aSubject, aTopic, aData) { + Services.obs.addObserver(function (aSubject, aTopic, aData) { // Remove the observer so we do not leak. - os.removeObserver(arguments.callee, TOPIC); + Services.obs.removeObserver(arguments.callee, TOPIC); // Check that the file exists. ok(getSessionstoreFile().exists(), aMessage); diff --git a/browser/components/sessionstore/test/browser/browser_354894.js b/browser/components/sessionstore/test/browser/browser_354894.js index 46d761554089..1107d64582bf 100644 --- a/browser/components/sessionstore/test/browser/browser_354894.js +++ b/browser/components/sessionstore/test/browser/browser_354894.js @@ -109,9 +109,7 @@ function browserWindowsCount(expected, msg) { if (typeof expected == "number") expected = [expected, expected]; let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -172,8 +170,6 @@ function test() { aCancel.QueryInterface(Ci.nsISupportsPRBool).data = true; } } - let observerService = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); /** * Helper: Sets prefs as the testsuite requires @@ -194,7 +190,7 @@ function test() { function setupTestsuite(testFn) { // Register our observers for (let o in observing) - observerService.addObserver(observer, o, false); + Services.obs.addObserver(observer, o, false); // Make the main test window not count as a browser window any longer oldWinType = document.documentElement.getAttribute("windowtype"); @@ -207,7 +203,7 @@ function test() { function cleanupTestsuite(callback) { // Finally remove observers again for (let o in observing) - observerService.removeObserver(observer, o, false); + Services.obs.removeObserver(observer, o, false); // Reset the prefs we touched [ diff --git a/browser/components/sessionstore/test/browser/browser_394759.js b/browser/components/sessionstore/test/browser/browser_394759.js index 37938c9b75bb..9c7ed76da23f 100644 --- a/browser/components/sessionstore/test/browser/browser_394759.js +++ b/browser/components/sessionstore/test/browser/browser_394759.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js b/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js index eb95a62294fb..ef42f42c414c 100644 --- a/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js +++ b/browser/components/sessionstore/test/browser/browser_394759_privatebrowsing.js @@ -39,9 +39,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -74,10 +72,8 @@ function test() { // Wait for the sessionstore.js file to be written before going on. // Note: we don't wait for the complete event, since if asyncCopy fails we // would timeout. - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - os.addObserver(function (aSubject, aTopic, aData) { - os.removeObserver(arguments.callee, aTopic); + Services.obs.addObserver(function (aSubject, aTopic, aData) { + Services.obs.removeObserver(arguments.callee, aTopic); info("sessionstore.js is being written"); executeSoon(continue_test); }, "sessionstore-state-write", false); diff --git a/browser/components/sessionstore/test/browser/browser_423132.js b/browser/components/sessionstore/test/browser/browser_423132.js index 3f33eff14dd2..253b24bec0b2 100644 --- a/browser/components/sessionstore/test/browser/browser_423132.js +++ b/browser/components/sessionstore/test/browser/browser_423132.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_448741.js b/browser/components/sessionstore/test/browser/browser_448741.js index 88d0bfd66dfc..5d2548222757 100644 --- a/browser/components/sessionstore/test/browser/browser_448741.js +++ b/browser/components/sessionstore/test/browser/browser_448741.js @@ -39,7 +39,6 @@ function test() { // test setup let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); waitForExplicitFinish(); let uniqueName = "bug 448741"; @@ -71,7 +70,7 @@ function test() { ok(valueWasCleaned, "found and removed the specific tab value"); aSubject.data = uneval(state); - os.removeObserver(cleaningObserver, aTopic, false); + Services.obs.removeObserver(cleaningObserver, aTopic, false); } // make sure that all later observers don't see that value any longer @@ -82,15 +81,15 @@ function test() { // clean up gBrowser.removeTab(tab); - os.removeObserver(checkingObserver, aTopic, false); + Services.obs.removeObserver(checkingObserver, aTopic, false); if (gPrefService.prefHasUserValue("browser.sessionstore.interval")) gPrefService.clearUserPref("browser.sessionstore.interval"); finish(); } // last added observers are invoked first - os.addObserver(checkingObserver, "sessionstore-state-write", false); - os.addObserver(cleaningObserver, "sessionstore-state-write", false); + Services.obs.addObserver(checkingObserver, "sessionstore-state-write", false); + Services.obs.addObserver(cleaningObserver, "sessionstore-state-write", false); // trigger an immediate save operation gPrefService.setIntPref("browser.sessionstore.interval", 0); diff --git a/browser/components/sessionstore/test/browser/browser_461634.js b/browser/components/sessionstore/test/browser/browser_461634.js index 512ee8ab7383..0e2f15db818f 100644 --- a/browser/components/sessionstore/test/browser/browser_461634.js +++ b/browser/components/sessionstore/test/browser/browser_461634.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_464199.js b/browser/components/sessionstore/test/browser/browser_464199.js index ddc0e0cf9566..60575c448c23 100644 --- a/browser/components/sessionstore/test/browser/browser_464199.js +++ b/browser/components/sessionstore/test/browser/browser_464199.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_465223.js b/browser/components/sessionstore/test/browser/browser_465223.js index bc388534978a..6e39b20debcf 100644 --- a/browser/components/sessionstore/test/browser/browser_465223.js +++ b/browser/components/sessionstore/test/browser/browser_465223.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_477657.js b/browser/components/sessionstore/test/browser/browser_477657.js index 1efae3bb6182..68b4f3e1fe07 100644 --- a/browser/components/sessionstore/test/browser/browser_477657.js +++ b/browser/components/sessionstore/test/browser/browser_477657.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_480148.js b/browser/components/sessionstore/test/browser/browser_480148.js index d6705c8b9ddf..18f7abcc025d 100644 --- a/browser/components/sessionstore/test/browser/browser_480148.js +++ b/browser/components/sessionstore/test/browser/browser_480148.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_490040.js b/browser/components/sessionstore/test/browser/browser_490040.js index 9ea372e7b24a..bdfdb8f214a2 100644 --- a/browser/components/sessionstore/test/browser/browser_490040.js +++ b/browser/components/sessionstore/test/browser/browser_490040.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -53,10 +51,6 @@ function test() { let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); waitForExplicitFinish(); @@ -98,7 +92,7 @@ function test() { break; case "domwindowclosed": - ww.unregisterNotification(windowObserver); + Services.ww.unregisterNotification(windowObserver); // Use executeSoon to ensure this happens after SS observer. executeSoon(function () { is(ss.getClosedWindowCount(), @@ -110,12 +104,12 @@ function test() { break; } } - ww.registerNotification(windowObserver); - ww.openWindow(null, - location, - "_blank", - "chrome,all,dialog=no", - null); + Services.ww.registerNotification(windowObserver); + Services.ww.openWindow(null, + location, + "_blank", + "chrome,all,dialog=no", + null); } // Only windows with open tabs are restorable. Windows where a lone tab is diff --git a/browser/components/sessionstore/test/browser/browser_491168.js b/browser/components/sessionstore/test/browser/browser_491168.js index 91ecdef7a59b..6acb929b5a6f 100644 --- a/browser/components/sessionstore/test/browser/browser_491168.js +++ b/browser/components/sessionstore/test/browser/browser_491168.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -52,7 +50,6 @@ function test() { // test setup let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); waitForExplicitFinish(); @@ -91,6 +88,6 @@ function test() { }, true); },true); - let referrerURI = ioService.newURI(REFERRER1, null, null); + let referrerURI = Services.io.newURI(REFERRER1, null, null); browser.loadURI("http://example.org", referrerURI, null); } diff --git a/browser/components/sessionstore/test/browser/browser_491577.js b/browser/components/sessionstore/test/browser/browser_491577.js index b068c7f17a6c..40fcd2925bc8 100644 --- a/browser/components/sessionstore/test/browser/browser_491577.js +++ b/browser/components/sessionstore/test/browser/browser_491577.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_493467.js b/browser/components/sessionstore/test/browser/browser_493467.js index 5359f243cecb..6b5fcdb9b644 100644 --- a/browser/components/sessionstore/test/browser/browser_493467.js +++ b/browser/components/sessionstore/test/browser/browser_493467.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_495495.js b/browser/components/sessionstore/test/browser/browser_495495.js index 7c2faaadd1d2..6c7bacb0c4e0 100644 --- a/browser/components/sessionstore/test/browser/browser_495495.js +++ b/browser/components/sessionstore/test/browser/browser_495495.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_514751.js b/browser/components/sessionstore/test/browser/browser_514751.js index 015d1b5b755b..4d740af206fa 100644 --- a/browser/components/sessionstore/test/browser/browser_514751.js +++ b/browser/components/sessionstore/test/browser/browser_514751.js @@ -36,9 +36,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_522545.js b/browser/components/sessionstore/test/browser/browser_522545.js index 53f619663f47..99247d2dc334 100644 --- a/browser/components/sessionstore/test/browser/browser_522545.js +++ b/browser/components/sessionstore/test/browser/browser_522545.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/components/sessionstore/test/browser/browser_524745.js b/browser/components/sessionstore/test/browser/browser_524745.js index d2dfe57b2e1d..0d10c7998ac4 100644 --- a/browser/components/sessionstore/test/browser/browser_524745.js +++ b/browser/components/sessionstore/test/browser/browser_524745.js @@ -37,9 +37,7 @@ function browserWindowsCount() { let count = 0; - let e = Cc["@mozilla.org/appshell/window-mediator;1"] - .getService(Ci.nsIWindowMediator) - .getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -53,8 +51,6 @@ function test() { let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); let uniqKey = "bug524745"; let uniqVal = Date.now(); diff --git a/browser/components/sessionstore/test/browser/browser_526613.js b/browser/components/sessionstore/test/browser/browser_526613.js index 095136474223..2014c63047d7 100644 --- a/browser/components/sessionstore/test/browser/browser_526613.js +++ b/browser/components/sessionstore/test/browser/browser_526613.js @@ -41,15 +41,11 @@ function test() { // test setup let ss = Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore); - let os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - let wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); waitForExplicitFinish(); function browserWindowsCount(expected) { let count = 0; - let e = wm.getEnumerator("navigator:browser"); + let e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; @@ -87,7 +83,7 @@ function test() { // let the first window be focused (see above) function pollMostRecentWindow() { - if (wm.getMostRecentWindow("navigator:browser") == window) { + if (Services.wm.getMostRecentWindow("navigator:browser") == window) { ss.setBrowserState(oldState); } else { info("waiting for the current window to become active"); @@ -100,11 +96,11 @@ function test() { else { browserWindowsCount(1); ok(!window.closed, "Restoring the old state should have left this window open"); - os.removeObserver(observer, "sessionstore-browser-state-restored"); + Services.obs.removeObserver(observer, "sessionstore-browser-state-restored"); finish(); } } - os.addObserver(observer, "sessionstore-browser-state-restored", false); + Services.obs.addObserver(observer, "sessionstore-browser-state-restored", false); // set browser to test state ss.setBrowserState(JSON.stringify(testState)); diff --git a/browser/components/sessionstore/test/browser/browser_528776.js b/browser/components/sessionstore/test/browser/browser_528776.js index 5b4d169003bf..5534a69a981b 100644 --- a/browser/components/sessionstore/test/browser/browser_528776.js +++ b/browser/components/sessionstore/test/browser/browser_528776.js @@ -1,9 +1,8 @@ var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); -var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); function browserWindowsCount(expected) { var count = 0; - var e = wm.getEnumerator("navigator:browser"); + var e = Services.wm.getEnumerator("navigator:browser"); while (e.hasMoreElements()) { if (!e.getNext().closed) ++count; diff --git a/browser/fuel/test/browser_Application.js b/browser/fuel/test/browser_Application.js index 25d5a8408567..e7b0074243ce 100644 --- a/browser/fuel/test/browser_Application.js +++ b/browser/fuel/test/browser_Application.js @@ -1,6 +1,3 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - // This listens for the next opened window and checks it is of the right url. // opencallback is called when the new window is fully loaded // closecallback is called when the window is closed @@ -9,9 +6,7 @@ function WindowOpenListener(url, opencallback, closecallback) { this.opencallback = opencallback; this.closecallback = closecallback; - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - wm.addListener(this); + Services.wm.addListener(this); } WindowOpenListener.prototype = { @@ -47,9 +42,7 @@ WindowOpenListener.prototype = { if (this.window != window) return; - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - wm.removeListener(this); + Services.wm.removeListener(this); this.opencallback = null; this.window = null; this.domwindow = null; diff --git a/browser/fuel/test/browser_ApplicationQuitting.js b/browser/fuel/test/browser_ApplicationQuitting.js index f709cc128cf1..520acfb6dbd1 100644 --- a/browser/fuel/test/browser_ApplicationQuitting.js +++ b/browser/fuel/test/browser_ApplicationQuitting.js @@ -5,14 +5,13 @@ function test() { "Received a quit request we're going to deny"); aSubject.data = true; } - + // ensure that we don't accidentally quit - let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.addObserver(quitRequestObserver, "quit-application-requested", false); - + Services.obs.addObserver(quitRequestObserver, "quit-application-requested", false); + ok(!Application.quit(), "Tried to quit - and didn't succeed"); ok(!Application.restart(), "Tried to restart - and didn't succeed"); - + // clean up - os.removeObserver(quitRequestObserver, "quit-application-requested", false); + Services.obs.removeObserver(quitRequestObserver, "quit-application-requested", false); } diff --git a/browser/fuel/test/browser_Bookmarks.js b/browser/fuel/test/browser_Bookmarks.js index fd71f2fcfa56..552c9572b7df 100644 --- a/browser/fuel/test/browser_Bookmarks.js +++ b/browser/fuel/test/browser_Bookmarks.js @@ -1,12 +1,8 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - var gLastFolderAction = ""; var gLastBookmarkAction = ""; function url(spec) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return ios.newURI(spec, null, null); + return Services.io.newURI(spec, null, null); } function test() { diff --git a/docshell/test/browser/browser_bug134911.js b/docshell/test/browser/browser_bug134911.js index 5a2e9dcdb9c3..368439b130a0 100644 --- a/docshell/test/browser/browser_bug134911.js +++ b/docshell/test/browser/browser_bug134911.js @@ -1,6 +1,3 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - /* The test text decoded correctly as Shift_JIS */ const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059"; @@ -42,6 +39,5 @@ function afterChangeCharset() { } function url(spec) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return ios.newURI(spec, null, null); + return Services.io.newURI(spec, null, null); } diff --git a/docshell/test/browser/browser_bug349769.js b/docshell/test/browser/browser_bug349769.js index eecf6bf892ec..35eef985df5c 100644 --- a/docshell/test/browser/browser_bug349769.js +++ b/docshell/test/browser/browser_bug349769.js @@ -3,8 +3,7 @@ function test() { var newTab; var newBrowser; - const secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager); + const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); var iteration = 1; const uris = [undefined, "about:blank"]; var uri; diff --git a/docshell/test/browser/browser_bug388121-1.js b/docshell/test/browser/browser_bug388121-1.js index 54c3140e9878..f19c2bbff526 100644 --- a/docshell/test/browser/browser_bug388121-1.js +++ b/docshell/test/browser/browser_bug388121-1.js @@ -3,8 +3,7 @@ function test() { var newTab; var newBrowser; - const secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager); + const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); function testLoad(event) { newBrowser.removeEventListener("load", testLoad, true); diff --git a/docshell/test/browser/browser_bug388121-2.js b/docshell/test/browser/browser_bug388121-2.js index 5f5d8c422246..6c050d971a39 100644 --- a/docshell/test/browser/browser_bug388121-2.js +++ b/docshell/test/browser/browser_bug388121-2.js @@ -2,8 +2,7 @@ function test() { waitForExplicitFinish(); var w; - const secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]. - getService(Components.interfaces.nsIScriptSecurityManager); + const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); var iteration = 1; const uris = ["", "about:blank"]; var uri; diff --git a/docshell/test/browser/browser_bug92473.js b/docshell/test/browser/browser_bug92473.js index 2ed330b09085..026048e963d8 100644 --- a/docshell/test/browser/browser_bug92473.js +++ b/docshell/test/browser/browser_bug92473.js @@ -1,6 +1,3 @@ -const Ci = Components.interfaces; -const Cc = Components.classes; - /* The test text decoded correctly as Shift_JIS */ const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059"; @@ -11,8 +8,7 @@ const wrongText="\u0453\u2020\u0453\u006A\u0453\u0052\u0403\u005B\u0453\u0068\u2 var testPage; function url(spec) { - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); - return ios.newURI(spec, null, null); + return Services.io.newURI(spec, null, null); } function testContent(text) { diff --git a/toolkit/components/downloads/test/browser/browser_bug414214.js b/toolkit/components/downloads/test/browser/browser_bug414214.js index f9ab87f2ae3d..93b34a11c58e 100644 --- a/toolkit/components/downloads/test/browser/browser_bug414214.js +++ b/toolkit/components/downloads/test/browser/browser_bug414214.js @@ -46,23 +46,17 @@ function test() db.executeSimpleSQL("DELETE FROM moz_downloads"); // See if the DM is already open, and if it is, close it! - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - var win = wm.getMostRecentWindow("Download:Manager"); + var win = Services.wm.getMostRecentWindow("Download:Manager"); if (win) win.close(); // We need to set browser.download.manager.closeWhenDone to true to test this - Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch). - setBoolPref(PREF_BDM_CLOSEWHENDONE, true); - - var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); + Services.prefs.setBoolPref(PREF_BDM_CLOSEWHENDONE, true); // register a callback to add a load listener to know when the download // manager opens - ww.registerNotification(function (aSubject, aTopic, aData) { - ww.unregisterNotification(arguments.callee); + Services.ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.unregisterNotification(arguments.callee); var win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); win.addEventListener("DOMContentLoaded", finishUp, false); @@ -76,8 +70,7 @@ function test() // Reset the pref to its default value try { - Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch). - clearUserPref(PREF_BDM_CLOSEWHENDONE); + Services.prefs.clearUserPref(PREF_BDM_CLOSEWHENDONE); } catch (err) { } diff --git a/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js b/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js index 1edaea808a6d..bdc557e9d12d 100644 --- a/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js +++ b/toolkit/components/downloads/test/browser/browser_nsIDownloadManagerUI.js @@ -105,9 +105,7 @@ function test() db.executeSimpleSQL("DELETE FROM moz_downloads"); // See if the DM is already open, and if it is, close it! - var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - var win = wm.getMostRecentWindow("Download:Manager"); + var win = Services.wm.getMostRecentWindow("Download:Manager"); if (win) win.close(); @@ -117,7 +115,7 @@ function test() // The window doesn't open once we call show, so we need to wait a little bit function finishUp() { - var win = wm.getMostRecentWindow("Download:Manager"); + var win = Services.wm.getMostRecentWindow("Download:Manager"); // Now we can run our tests for each (var t in testFuncs) diff --git a/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js b/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js index a49ffeba923b..ecdccce9f053 100644 --- a/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js +++ b/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_sort.js @@ -89,10 +89,6 @@ function test() { pwmgr.addLogin(new nsLoginInfo(urls[i], urls[i], null, users[i], pwds[i], "u"+(i+1), "p"+(i+1))); - // Detect when the password manager window is opened - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - // Open the password manager dialog const PWMGR_DLG = "chrome://passwordmgr/content/passwordManager.xul"; let pwmgrdlg = window.openDialog(PWMGR_DLG, "Toolkit:PasswordManager", ""); @@ -115,9 +111,9 @@ function test() { // only watch for a confirmation dialog every other time being called if (showMode) { - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { if (aTopic == "domwindowclosed") - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); else if (aTopic == "domwindowopened") { let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); SimpleTest.waitForFocus(function() { @@ -127,11 +123,9 @@ function test() { }); } - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { + Services.obs.addObserver(function (aSubject, aTopic, aData) { if (aTopic == "passwordmgr-password-toggle-complete") { - obsSvc.removeObserver(arguments.callee, aTopic, false); + Services.obs.removeObserver(arguments.callee, aTopic, false); func(); } }, "passwordmgr-password-toggle-complete", false); @@ -234,9 +228,9 @@ function test() { checkColumnEntries(2, expectedValues); checkSortDirection(passwordCol, true); // cleanup - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { // unregister ourself - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); pwmgr.removeAllLogins(); finish(); diff --git a/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js b/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js index 5c6db7d89409..4d1c0e7d63d8 100644 --- a/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js +++ b/toolkit/components/passwordmgr/test/browser/browser_passwordmgrdlg.js @@ -74,10 +74,6 @@ function test() { ]; logins.forEach(function (login) pwmgr.addLogin(login)); - // Detect when the password manager window is opened - let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher); - // Open the password manager dialog const PWMGR_DLG = "chrome://passwordmgr/content/passwordManager.xul"; let pwmgrdlg = window.openDialog(PWMGR_DLG, "Toolkit:PasswordManager", ""); @@ -125,9 +121,9 @@ function test() { // only watch for a confirmation dialog every other time being called if (showMode) { - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { if (aTopic == "domwindowclosed") - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); else if (aTopic == "domwindowopened") { let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget); SimpleTest.waitForFocus(function() { @@ -137,11 +133,9 @@ function test() { }); } - let obsSvc = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - obsSvc.addObserver(function (aSubject, aTopic, aData) { + Services.obs.addObserver(function (aSubject, aTopic, aData) { if (aTopic == "passwordmgr-password-toggle-complete") { - obsSvc.removeObserver(arguments.callee, aTopic, false); + Services.obs.removeObserver(arguments.callee, aTopic, false); func(); } }, "passwordmgr-password-toggle-complete", false); @@ -219,9 +213,9 @@ function test() { function lastStep() { // cleanup - ww.registerNotification(function (aSubject, aTopic, aData) { + Services.ww.registerNotification(function (aSubject, aTopic, aData) { // unregister ourself - ww.unregisterNotification(arguments.callee); + Services.ww.unregisterNotification(arguments.callee); pwmgr.removeAllLogins(); finish(); diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js index 2480d4ea4660..124833ea098a 100644 --- a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js +++ b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js @@ -7,9 +7,7 @@ function cleanup_and_finish() { try { cleanup_fake_appdir(); } catch(ex) {} - let prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - prefs.clearUserPref("breakpad.reportURL"); + Services.prefs.clearUserPref("breakpad.reportURL"); gBrowser.removeTab(gBrowser.selectedTab); finish(); } @@ -135,10 +133,8 @@ function test() { crashes.sort(function(a,b) b.date - a.date); // set this pref so we can link to our test server - let prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - - prefs.setCharPref("breakpad.reportURL", "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs?id="); + Services.prefs.setCharPref("breakpad.reportURL", + "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs?id="); let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank"); let browser = gBrowser.getBrowserForTab(tab); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug510909.js b/toolkit/mozapps/extensions/test/browser/browser_bug510909.js index d3a33d3539e9..ed6629b30451 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug510909.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug510909.js @@ -5,9 +5,7 @@ var win = null; function WindowListener(url) { this.url = url; - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.addListener(this); + Services.wm.addListener(this); } WindowListener.prototype = { @@ -38,9 +36,7 @@ WindowListener.prototype = { }, onCloseWindow: function(window) { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - wm.removeListener(this); + Services.wm.removeListener(this); }, QueryInterface: function(iid) { From 410cab1d6fd90dced64c29992edab7052c21edde Mon Sep 17 00:00:00 2001 From: David Bolter Date: Fri, 2 Apr 2010 09:33:55 -0400 Subject: [PATCH 68/69] Bug 551684 - No statechange event for aria-expanded on native HTML elements, is fired on ARIA widgets; r=MarcoZ,surkov --- accessible/src/base/nsDocAccessible.cpp | 38 +++++---- accessible/tests/mochitest/events/Makefile.in | 1 + .../events/test_aria_statechange.html | 85 +++++++++++++++++++ 3 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 accessible/tests/mochitest/events/test_aria_statechange.html diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index ea937e33f1b8..eeec02a40dd6 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -1179,6 +1179,9 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) if (!targetNode) return; + // Note: For universal/global ARIA states and properties we don't care if + // there is an ARIA role present or not. + if (aAttribute == nsAccessibilityAtoms::aria_required) { nsRefPtr event = new nsAccStateChangeEvent(targetNode, @@ -1209,6 +1212,24 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) return; } + // For aria drag and drop changes we fire a generic attribute change event; + // at least until native API comes up with a more meaningful event. + if (aAttribute == nsAccessibilityAtoms::aria_grabbed || + aAttribute == nsAccessibilityAtoms::aria_dropeffect) { + FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, + targetNode); + } + + // We treat aria-expanded as a global ARIA state for historical reasons + if (aAttribute == nsAccessibilityAtoms::aria_expanded) { + nsRefPtr event = + new nsAccStateChangeEvent(targetNode, + nsIAccessibleStates::STATE_EXPANDED, + PR_FALSE); + FireDelayedAccessibleEvent(event); + return; + } + if (!aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) { // We don't care about these other ARIA attribute changes unless there is // an ARIA role set for the element @@ -1249,15 +1270,6 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) return; } - if (aAttribute == nsAccessibilityAtoms::aria_expanded) { - nsRefPtr event = - new nsAccStateChangeEvent(targetNode, - nsIAccessibleStates::STATE_EXPANDED, - PR_FALSE); - FireDelayedAccessibleEvent(event); - return; - } - if (aAttribute == nsAccessibilityAtoms::aria_readonly) { nsRefPtr event = new nsAccStateChangeEvent(targetNode, @@ -1290,14 +1302,6 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE); return; } - - // For aria drag and drop changes we fire a generic attribute change event; - // at least until native API comes up with a more meaningful event. - if (aAttribute == nsAccessibilityAtoms::aria_grabbed || - aAttribute == nsAccessibilityAtoms::aria_dropeffect) { - FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, - targetNode); - } } void nsDocAccessible::ContentAppended(nsIDocument *aDocument, diff --git a/accessible/tests/mochitest/events/Makefile.in b/accessible/tests/mochitest/events/Makefile.in index c95ddb5ce7f2..4cccd0b5bbb7 100644 --- a/accessible/tests/mochitest/events/Makefile.in +++ b/accessible/tests/mochitest/events/Makefile.in @@ -48,6 +48,7 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES =\ focus.html \ scroll.html \ + test_aria_statechange.html \ test_attrs.html \ test_caretmove.html \ $(warning test_coalescence.html temporarily disabled) \ diff --git a/accessible/tests/mochitest/events/test_aria_statechange.html b/accessible/tests/mochitest/events/test_aria_statechange.html new file mode 100644 index 000000000000..2a8f20ae9294 --- /dev/null +++ b/accessible/tests/mochitest/events/test_aria_statechange.html @@ -0,0 +1,85 @@ + + + + ARIA state change event testing + + + + + + + + + + + + + + + +
+ Mozilla Bug 551684 + + +

+ +
+  
+
+ + + + + + + From 72f302972224379a62bd7e75c6bdefaa248aebbe Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Fri, 2 Apr 2010 18:59:35 +0530 Subject: [PATCH 69/69] Bug 556735 - single directory xpcshell-tests and check-one don't work. r=ted --HG-- extra : rebase_source : 78465fc45518ae116dfa5d438d9b0dc64a69f32d --- testing/xpcshell/runxpcshelltests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index beb696e52f97..104e0e96ac70 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -261,7 +261,7 @@ class XPCShellTests(object): testfiles = sorted(glob(os.path.join(os.path.abspath(testdir), "test_*.js"))) if self.singleFile: if self.singleFile in [os.path.basename(x) for x in testfiles]: - testfiles = os.path.abspath([os.path.join(testdir, self.singleFile)]) + testfiles = [os.path.abspath(os.path.join(testdir, self.singleFile))] else: # not in this dir? skip it return None @@ -518,7 +518,7 @@ def main(): print >>sys.stderr, "Error: You must specify a test filename in interactive mode!" sys.exit(1) - if not xpcsh.runTests(args[0], **options.__dict__): + if not xpcsh.runTests(args[0], testdirs=args[1:], **options.__dict__): sys.exit(1) if __name__ == '__main__':