diff --git a/README.txt b/README.txt index bc85852ed9b6..33f7e516220b 100644 --- a/README.txt +++ b/README.txt @@ -1,306 +1,20 @@ -============================================================== +For information on how to build Mozilla from the source code, see: -= = = = = = = = = = Mozilla Read Me = = = = = = = = = = = + http://developer.mozilla.org/en/docs/Build_Documentation -============================================================== +To have your bug fix / feature added to Mozilla, you should create a patch and +submit it to Bugzilla (http://bugzilla.mozilla.org). Instructions are at: -Mozilla is subject to the terms detailed in the license -agreement accompanying it. + http://developer.mozilla.org/en/docs/Creating_a_patch + http://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree -This Read Me file contains information about system -requirements and installation instructions for the Windows, -Mac OS, and Linux builds of Mozilla. +If you have a question about developing Mozilla, and can't find the solution +on http://developer.mozilla.org, you can try asking your question in a +mozilla.* Usenet group, or on IRC at irc.mozilla.org. [The Mozilla news groups +are accessible on Google Groups, or news.mozilla.org with a NNTP reader.] -For more info on Mozilla, see www.mozilla.org. To submit bugs -or other feedback, see the Navigator QA menu and check out -Bugzilla at http://bugzilla.mozilla.org for links to known -bugs, bug-writing guidelines, and more. You can also get help -with Bugzilla by pointing your IRC client to #mozillazine -at irc.mozilla.org. +You can download nightly development builds from the the Mozilla FTP server. +Keep in mind that nightly builds, which are used by Mozilla developers for +testing, may be buggy. Firefox nightlies, for example, can be found at: - -============================================================== - - Getting Mozilla - -============================================================== - -You can download nightly builds of Mozilla from the -Mozilla.org FTP site at - - ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/ - -For the very latest builds, see - - ftp://ftp.mozilla.org/pub/mozilla.org/mozilla/nightly/latest-trunk - -Keep in mind that nightly builds, which are used by -Mozilla.org developers for testing, may be buggy. If you are -looking for a more polished version of Mozilla, Mozilla.org -releases Milestone builds of Mozilla every six weeks or so -that you can download from - - http://www.mozilla.org/releases - -Be sure to read the Mozilla release notes for information -on known problems and installation issues with Mozilla. -The release notes can be found at the preceding URL along -with the milestone releases themselves. - -Note: Please use Talkback builds whenever possible. These -builds allow transmission of crash data back to Mozilla -developers, improved crash analysis, and posting of crash -information to our crash-data newsgroup. - - -============================================================== - - System Requirements - -============================================================== - -*All Platforms - - To view and use the new streamlined "Modern" theme, - your display monitor should be set to display - thousands of colors. For users who cannot set their - displays to use more than 256 colors, Mozilla.org - recommends using the "Classic" theme for Mozilla. - - To select the Modern theme after you have installed - Mozilla, from the Navigator browser, open the View - menu, and then open then open the Apply Theme submenu - and choose Modern. - -*Mac OS - - -Mac OS X or later - -PowerPC processor (266 MHz or faster recommended) - -64 MB RAM - -36 MB of free hard disk space - -*Windows - - -Windows 95, 98, Me, NT4, 2000 or XP - -Intel Pentium class processor (233 MHz or faster - recommended) - -64 MB RAM - -26 MB free hard disk space - -*Linux - - -The following library versions (or compatible) are - required: glibc 2.1, XFree86 3.3.x, GTK 1.2.x, Glib - 1.2.x, Libstdc++ 2.9.0. Red Hat Linux 6.0, - Debian 2.1, and SuSE 6.2 (or later) installations - should work. - -Red Hat 6.x users who want to install the Mozilla - RPM must have at least version 4.0.2 of rpm - installed. - -Intel Pentium class processor (233 MHz or faster - recommended) - -64MB RAM - -26MB free hard disk space - - -============================================================== - - Installation Instructions - -============================================================== - -For Mac OS and Windows users, it is strongly recommended that -you exit all programs before running the setup program. Also, -you should temporarily disable virus-detection software. - -For Linux users, note that the installation instructions use -the bash shell. If you're not using bash, adjust the commands -accordingly. - -For all platforms, install into a clean (new) directory. -Installing on top of previously released builds may cause -problems. - -Note: These instructions do not tell you how to build Mozilla. -For info on building the Mozilla source, see - - http://www.mozilla.org/source.html - - -Windows Installation Instructions ---------------------------------- - -Note: For Windows NT/2000/XP systems, you need Administrator -privileges to install Mozilla. If you see an "Error 5" message -during installation, make sure you're running the installation -with Administrator privileges. - - - To install Mozilla by downloading the Mozilla installer, - follow these steps: - - 1. Click the the mozilla-win32-installer.exe link on - the site you're downloading Mozilla from to download - the installer file to your machine. - - 2. Navigate to where you downloaded the file and - double-click the Mozilla program icon on your machine - to begin the Setup program. - - 3. Follow the on-screen instructions in the setup - program. The program starts automatically the first - time. - - - To install Mozilla by downloading the .zip file and - installing manually, follow these steps: - - 1. Click the mozilla-win32-talkback.zip link or the - mozilla-win32.zip link on the site you're down- - loading Mozilla from to download the .zip file to - your machine. - - 2. Navigate to where you downloaded the file and - double-click the compressed file. - - Note: This step assumes you already have a recent - version of WinZip installed, and that you know how to - use it. If not, you can get WinZip and information - about the program at www.winzip.com. - - 3. Extract the .zip file to a directory such as - C:\Program Files\mozilla.org\Mozilla. - - 4. To start Mozilla, navigate to the directory you - extracted Mozilla to and double-click the Mozilla.exe - icon. - - -Mac OS X Installation Instructions ----------------------------------- - - To install Mozilla by downloading the Mozilla disk image, - follow these steps: - - 1. Click the mozilla-mac-MachO.dmg.gz link to download - it to your machine. By default, the download file is - downloaded to your desktop. - - 2. Once you have downloaded the .dmg.gz file, drag it - onto Stuffit Expander to decompress it. If the disk - image doesn't mount automatically, double-click on the - .dmg file to mount it. If that fails, and the file - does not look like a disk image file, do a "Show Info" - on the file, and, in the "Open with application" - category, choose Disk Copy. In Mac OS 10.2, you can - use "Open with" from the context menu. - - 3. Once the disk image mounts, open it, and drag the - Mozilla icon onto your hard disk. - - 4. We recommend that you copy it to the Applications - folder. - - 5. Now Eject the disk image. - - 6. If you like, you can drag Mozilla to your dock to - have it easily accessible at all times. You might also - wish to select Mozilla as your default browser in the - Internet system preferences pane (under the Web tab). - - -Linux Installation Instructions -------------------------------- - -Note: If you install in the default directory (which is -usually /usr/local/mozilla), or any other directory where -only the root user normally has write-access, you must -start Mozilla first as root before other users can start -the program. Doing so generates a set of files required -for later use by other users. - - - To install Mozilla by downloading the Mozilla installer, - follow these steps: - - 1. Create a directory named mozilla (mkdir mozilla) - and change to that directory (cd mozilla). - - 2. Click the link on the site you're downloading - Mozilla from to download the installer file - (called mozilla-1686-pc-linux-gnu-installer.tar.gz) - to your machine. - - 3. Change to the mozilla directory (cd mozilla) and - decompress the archive with the following command: - - tar zxvf moz*.tar.gz - - The installer is now located in a subdirectory of - Mozilla named mozilla-installer. - - 4. Change to the mozilla-installer directory - (cd mozilla-installer) and run the installer with the - ./mozilla-installer command. - - 5. Follow the instructions in the install wizard for - installing Mozilla. - - Note: If you have a slower machine, be aware that the - installation may take some time. In this case, the - installation progress may appear to hang indefinitely, - even though the installation is still in process. - - 6. To start Mozilla, change to the directory where you - installed it and run the ./mozilla command. - - - To install Mozilla by downloading the tar.gz file: - - 1. Create a directory named "mozilla" (mkdir mozilla) - and change to that directory (cd mozilla). - - 2. Click the link on the site you're downloading - Mozilla from to download the non-installer - (mozilla*.tar.gz) file into the mozilla directory. - - 3. Change to the mozilla directory (cd mozilla) and - decompress the file with the following command: - - tar zxvf moz*.tar.gz - - This creates a "mozilla" directory under your mozilla - directory. - - 4. Change to the mozilla directory (cd mozilla). - - 5. Run Mozilla with the following run script: - - ./mozilla - - - To hook up Mozilla complete with icon to the GNOME Panel, - follow these steps: - - 1. Click the GNOME Main Menu button, open the Panel menu, - and then open the Add to Panel submenu and choose Launcher. - - 2. Right-click the icon for Mozilla on the Panel and - enter the following command: - directory_name./mozilla - - where directory_name is the name of the directory - you downloaded mozilla to. For example, the default - directory that Mozilla suggests is /usr/local/mozilla. - - 3. Type in a name for the icon, and type in a comment - if you wish. - - 4. Click the icon button and type in the following as - the icon's location: - - directory_name/icons/mozicon50.xpm - - where directory name is the directory where you - installed Mozilla. For example, the default directory - is /usr/local/mozilla/icons/mozicon50.xpm. + ftp://ftp.mozilla.org/pub/firefox/nightly/latest-trunk/ diff --git a/accessible/public/nsIAccessibleEvent.idl b/accessible/public/nsIAccessibleEvent.idl index 8d7d21293461..d813eaedfb0f 100755 --- a/accessible/public/nsIAccessibleEvent.idl +++ b/accessible/public/nsIAccessibleEvent.idl @@ -569,3 +569,17 @@ interface nsIAccessibleCaretMoveEvent: nsIAccessibleEvent readonly attribute long caretOffset; }; +[scriptable, uuid(a9485c7b-5861-4695-8441-fab0235b205d)] +interface nsIAccessibleTableChangeEvent: nsIAccessibleEvent +{ + /** + * Return the row or column index. + */ + readonly attribute long rowOrColIndex; + + /** + * Return the number of rows or cols + */ + readonly attribute long numRowsOrCols; +}; + diff --git a/accessible/public/nsIAccessibleProvider.idl b/accessible/public/nsIAccessibleProvider.idl index 9e6db44fc81d..3f7b22774b1d 100644 --- a/accessible/public/nsIAccessibleProvider.idl +++ b/accessible/public/nsIAccessibleProvider.idl @@ -52,6 +52,12 @@ interface nsIAccessibleProvider : nsISupports * Constants set of common use. */ + /** Do not create an accessible for this object + * This is useful if an ancestor binding already implements nsIAccessibleProvider, + * but no accessible is desired for the inheriting binding + */ + const long NoAccessible = 0; + /** For elements that spawn a new document. For example now it is used by , and . */ const long OuterDoc = 0x00000001; @@ -78,32 +84,33 @@ interface nsIAccessibleProvider : nsISupports const long XULMenuitem = 0x0000100E; const long XULMenupopup = 0x0000100F; const long XULMenuSeparator = 0x00001010; - const long XULProgressMeter = 0x00001011; - const long XULScale = 0x00001012; - const long XULStatusBar = 0x00001013; - const long XULRadioButton = 0x00001014; - const long XULRadioGroup = 0x00001015; + const long XULPane = 0x00001011; + const long XULProgressMeter = 0x00001012; + const long XULScale = 0x00001013; + const long XULStatusBar = 0x00001014; + const long XULRadioButton = 0x00001015; + const long XULRadioGroup = 0x00001016; /** The single tab in a dialog or tabbrowser/editor interface */ - const long XULTab = 0x00001016; + const long XULTab = 0x00001017; /** A combination of a tabs object and a tabpanels object */ - const long XULTabBox = 0x00001017; + const long XULTabBox = 0x00001018; /** The collection of tab objects, useable in the TabBox and independant of as well */ - const long XULTabs = 0x00001018; + const long XULTabs = 0x00001019; - const long XULText = 0x00001019; - const long XULTextBox = 0x0000101A; - const long XULThumb = 0x0000101B; - const long XULTree = 0x0000101C; - const long XULTreeColumns = 0x0000101D; - const long XULTreeColumnItem = 0x0000101E; - const long XULToolbar = 0x0000101F; - const long XULToolbarSeparator = 0x00001020; - const long XULTooltip = 0x00001021; - const long XULToolbarButton = 0x00001022; + const long XULText = 0x0000101A; + const long XULTextBox = 0x0000101B; + const long XULThumb = 0x0000101C; + const long XULTree = 0x0000101D; + const long XULTreeColumns = 0x0000101E; + const long XULTreeColumnItem = 0x0000101F; + const long XULToolbar = 0x00001020; + const long XULToolbarSeparator = 0x00001021; + const long XULTooltip = 0x00001022; + const long XULToolbarButton = 0x00001023; /** diff --git a/accessible/public/nsIAccessibleRole.idl b/accessible/public/nsIAccessibleRole.idl index 8ccbdf191b69..dc43574512c3 100755 --- a/accessible/public/nsIAccessibleRole.idl +++ b/accessible/public/nsIAccessibleRole.idl @@ -110,9 +110,9 @@ interface nsIAccessibleRole : nsISupports const unsigned long ROLE_WINDOW = 9; /** - * XXX: document this. + * A sub-document ( or + + + diff --git a/content/base/test/test_bug326337.html b/content/base/test/test_bug326337.html index dfaf8c082db9..b0c4f897d368 100644 --- a/content/base/test/test_bug326337.html +++ b/content/base/test/test_bug326337.html @@ -1,38 +1,36 @@ - - - - - Test for Bug 326337 - - - - - -Mozilla Bug 326337 -

- - -
-
-
- - - + + + + + Test for Bug 326337 + + + + + +Mozilla Bug 326337 +

+ +
+
+
+ + + diff --git a/content/base/test/test_bug414190.html b/content/base/test/test_bug414190.html new file mode 100644 index 000000000000..13cd5caff1f7 --- /dev/null +++ b/content/base/test/test_bug414190.html @@ -0,0 +1,87 @@ + + + + + Test for Bug 414190 + + + + + + +Mozilla Bug 414190 +

+ + + + +
+ + +
+
+
+ + + diff --git a/content/canvas/Makefile.in b/content/canvas/Makefile.in index f607d85e10eb..cd71f556bdbc 100644 --- a/content/canvas/Makefile.in +++ b/content/canvas/Makefile.in @@ -16,6 +16,7 @@ # # The Initial Developer of the Original Code is # Vladimir Vukicevic +# # Portions created by the Initial Developer are Copyright (C) 2005 # the Initial Developer. All Rights Reserved. # diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index 550f31cd6d01..d9236f080546 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -2609,9 +2609,10 @@ nsCanvasRenderingContext2D::PutImageData() if (mImageSurfaceData) { int stride = mWidth*4; PRUint8 *dest = mImageSurfaceData + stride*y + x*4; + PRUint8 *src = imageBuffer.get(); - for (int32 i = 0; i < y; i++) { - memcpy(dest, imgPtr + (w*4)*i, w*4); + for (int32 i = 0; i < h; i++) { + memcpy(dest, src + (w*4)*i, w*4); dest += stride; } } else { diff --git a/content/canvas/test/Makefile.in b/content/canvas/test/Makefile.in index ea421067b184..a15559d3d2ab 100644 --- a/content/canvas/test/Makefile.in +++ b/content/canvas/test/Makefile.in @@ -177,12 +177,8 @@ _TEST_FILES_B = \ test_2d.composite.transparent.lighter.html \ test_2d.composite.image.source-over.html \ test_2d.composite.image.destination-over.html \ - test_2d.composite.image.source-in.html \ - test_2d.composite.image.destination-in.html \ - test_2d.composite.image.source-out.html \ test_2d.composite.image.destination-out.html \ test_2d.composite.image.source-atop.html \ - test_2d.composite.image.destination-atop.html \ test_2d.composite.image.xor.html \ test_2d.composite.image.copy.html \ test_2d.composite.image.lighter.html \ @@ -514,10 +510,20 @@ endif # Tests that fail on Mac (possibly because spec is underdefined?). Bug 407105 ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa) _TEST_FILES_E += \ - test_2d.line.cap.zerobezier.round.html \ test_2d.line.join.parallel.html \ test_2d.strokeRect.zero.5.html \ $(NULL) + +# test_2d.line.cap.zerobezier.round.html disabled for now, from above + +# These are failing due to different quartz implementations of these operators when +# images are in play. Bug 413026. +_TEST_FILES_E += \ + test_2d.composite.image.destination-in.html \ + test_2d.composite.image.destination-atop.html \ + test_2d.composite.image.source-in.html \ + test_2d.composite.image.source-out.html \ + $(NULL) endif # Tests that fail on non-Mac (bug 401791) diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index e9cb325c543b..c007bd2199ba 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2859,6 +2859,9 @@ nsEventStateManager::SetCursor(PRInt32 aCursor, imgIContainer* aContainer, case NS_STYLE_CURSOR_EW_RESIZE: c = eCursor_ew_resize; break; + case NS_STYLE_CURSOR_NONE: + c = eCursor_none; + break; } // First, try the imgIContainer, if non-null diff --git a/content/html/content/public/nsIFrameSetElement.h b/content/html/content/public/nsIFrameSetElement.h index 9a90820b7877..5050a4c3a582 100644 --- a/content/html/content/public/nsIFrameSetElement.h +++ b/content/html/content/public/nsIFrameSetElement.h @@ -40,6 +40,7 @@ #define nsIFramesetElement_h___ #include "nsISupports.h" +#include "nsCoord.h" // IID for the nsIFramesetElement interface #define NS_IFRAMESETELEMENT_IID \ diff --git a/content/html/content/src/Makefile.in b/content/html/content/src/Makefile.in index 8bae404ce80b..0050f232ba9b 100644 --- a/content/html/content/src/Makefile.in +++ b/content/html/content/src/Makefile.in @@ -133,6 +133,8 @@ CPPSRCS = \ nsTextRectangle.cpp \ $(NULL) +GQI_SRCS = htmlcontent.gqi + # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 diff --git a/content/html/content/src/htmlcontent.gqi b/content/html/content/src/htmlcontent.gqi new file mode 100644 index 000000000000..01a3b354e790 --- /dev/null +++ b/content/html/content/src/htmlcontent.gqi @@ -0,0 +1,55 @@ +%import "htmlgenericelement.gqi" + +%import-idl "nsIDOMHTMLAnchorElement.idl" +%import-idl "nsIDOMNSHTMLAnchorElement2.idl" +%import-idl "nsIDOMHTMLDivElement.idl" +%import-idl "nsIDOMHTMLFrameElement.idl" +%import-idl "nsIDOMHTMLFrameSetElement.idl" +%import-idl "nsIDOMHTMLIFrameElement.idl" + +%{C++ +#include "nsHTMLAnchorElement.h" +#include "nsHTMLDivElement.h" +#include "nsHTMLSpanElement.h" +#include "nsHTMLFrameElement.h" +#include "nsHTMLFrameSetElement.h" +#include "nsHTMLIFrameElement.h" +%} + +%pseudo-iid nsILink 0c212bc4-fcd7-479d-8c3f-3be8e6787450 +%pseudo-iid nsIFrameSetElement eefe0fe5-44ac-4d7f-a751-f4aa5f22b0bf + +NS_INTERFACE_MAP_BEGIN(nsHTMLAnchorElement, nsGenericHTMLElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLAnchorElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLAnchorElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLAnchorElement2) + NS_INTERFACE_MAP_ENTRY(nsILink) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLAnchorElement) +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN(nsHTMLDivElement, nsGenericHTMLElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLDivElement) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLDivElement) +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN(nsHTMLSpanElement, nsGenericHTMLElement) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLSpanElement) +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN(nsHTMLFrameElement, nsGenericHTMLFrameElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLFrameElement) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLFrameElement) +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN(nsHTMLFrameSetElement, nsGenericHTMLElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLFrameSetElement) + NS_INTERFACE_MAP_ENTRY(nsIFrameSetElement) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLFrameSetElement) +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN(nsHTMLIFrameElement, nsGenericHTMLFrameElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLIFrameElement) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLIFrameElement) +NS_INTERFACE_MAP_END + + diff --git a/content/html/content/src/htmlgenericelement.gqi b/content/html/content/src/htmlgenericelement.gqi new file mode 100644 index 000000000000..415da8610578 --- /dev/null +++ b/content/html/content/src/htmlgenericelement.gqi @@ -0,0 +1,35 @@ +// Note: nsGenericHTMLElement does not implement QI directly... this declaration is here only +// so that subclasses have the correct list + +%import "contentbase.gqi" + +%import-idl "nsIDOMNSHTMLElement.idl" +%import-idl "nsIDOMElementCSSInlineStyle.idl" +%import-idl "nsIDOMHTMLElement.idl" +%import-idl "nsIDOMNSHTMLFrameElement.idl" +%import-idl "nsIFrameLoader.idl" + +%{C++ +#include "nsGenericHTMLElement.h" +%} + +NS_INTERFACE_MAP_BEGIN(nsGenericHTMLElement, nsGenericElement) + // nsGenericHTMLElement doesn't implement nsIDOMHTMLElement, but all + // subclasses do, and we only use this declaration for subclasses + NS_FUTURE_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement) + NS_FUTURE_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_FUTURE_INTERFACE_MAP_ENTRY(nsIDOMElement) + + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSHTMLElement, + new nsGenericHTMLElementTearoff(this)) + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMElementCSSInlineStyle, + new nsGenericHTMLElementTearoff(this)) + NS_INTERFACE_MAP_UNFOUND + return PostQueryInterface(aIID, aResult); + END +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN(nsGenericHTMLFrameElement, nsGenericHTMLElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLFrameElement) + NS_INTERFACE_MAP_ENTRY(nsIFrameLoaderOwner) +NS_INTERFACE_MAP_END diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index e2bacb4d0c20..69c339508c79 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -179,30 +179,6 @@ nsGenericHTMLElement::Init(nsINodeInfo *aNodeInfo) #endif -class nsGenericHTMLElementTearoff : public nsIDOMNSHTMLElement, - public nsIDOMElementCSSInlineStyle -{ - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - - nsGenericHTMLElementTearoff(nsGenericHTMLElement *aElement) - : mElement(aElement) - { - } - - virtual ~nsGenericHTMLElementTearoff() - { - } - - NS_FORWARD_NSIDOMNSHTMLELEMENT(mElement->) - NS_FORWARD_NSIDOMELEMENTCSSINLINESTYLE(mElement->) - - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGenericHTMLElementTearoff, - nsIDOMNSHTMLElement) - -private: - nsCOMPtr mElement; -}; - NS_IMPL_CYCLE_COLLECTION_1(nsGenericHTMLElementTearoff, mElement) NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericHTMLElementTearoff, @@ -2879,13 +2855,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameLoader) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_INTERFACE_TABLE_HEAD(nsGenericHTMLFrameElement) - NS_INTERFACE_TABLE_INHERITED2(nsGenericHTMLFrameElement, - nsIDOMNSHTMLFrameElement, - nsIFrameLoaderOwner) - NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLFrameElement) -NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) - nsresult nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument) { @@ -3752,7 +3721,7 @@ nsGenericHTMLElement::IsEditableRoot() const } if (document->HasFlag(NODE_IS_EDITABLE)) { - return this == document->GetRootContent(); + return PR_FALSE; } if (GetContentEditableValue() != eTrue) { diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 15befa464f6c..5bec70702a20 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -45,6 +45,8 @@ #include "nsIDOMNSHTMLFrameElement.h" #include "nsFrameLoader.h" #include "nsGkAtoms.h" +#include "nsIDOMElementCSSInlineStyle.h" +#include "nsIDOMNSHTMLElement.h" class nsIDOMAttr; class nsIDOMEventListener; @@ -897,9 +899,6 @@ public: } virtual ~nsGenericHTMLFrameElement(); - // nsISupports - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - // nsIDOMNSHTMLFrameElement NS_DECL_NSIDOMNSHTMLFRAMEELEMENT @@ -940,6 +939,30 @@ protected: nsCOMPtr mFrameLoader; }; +class nsGenericHTMLElementTearoff : public nsIDOMNSHTMLElement, + public nsIDOMElementCSSInlineStyle +{ + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + + nsGenericHTMLElementTearoff(nsGenericHTMLElement *aElement) + : mElement(aElement) + { + } + + virtual ~nsGenericHTMLElementTearoff() + { + } + + NS_FORWARD_NSIDOMNSHTMLELEMENT(mElement->) + NS_FORWARD_NSIDOMELEMENTCSSINLINESTYLE(mElement->) + + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGenericHTMLElementTearoff, + nsIDOMNSHTMLElement) + +private: + nsCOMPtr mElement; +}; + //---------------------------------------------------------------------- /** diff --git a/content/html/content/src/nsHTMLAnchorElement.cpp b/content/html/content/src/nsHTMLAnchorElement.cpp index 84ade688e5ee..7702e5ef387a 100644 --- a/content/html/content/src/nsHTMLAnchorElement.cpp +++ b/content/html/content/src/nsHTMLAnchorElement.cpp @@ -36,6 +36,8 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ + +#include "nsHTMLAnchorElement.h" #include "nsCOMPtr.h" #include "nsReadableUtils.h" #include "nsUnicharUtils.h" @@ -63,78 +65,10 @@ #include "nsCOMPtr.h" #include "nsIPresShell.h" #include "nsIDocument.h" +#include "nsHTMLAnchorElement.h" nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); -class nsHTMLAnchorElement : public nsGenericHTMLElement, - public nsIDOMHTMLAnchorElement, - public nsIDOMNSHTMLAnchorElement2, - public nsILink -{ -public: - nsHTMLAnchorElement(nsINodeInfo *aNodeInfo); - virtual ~nsHTMLAnchorElement(); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - // nsIDOMNode - NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) - - // nsIDOMElement - NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLElement - NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLAnchorElement - NS_DECL_NSIDOMHTMLANCHORELEMENT - - // nsIDOMNSHTMLAnchorElement - NS_DECL_NSIDOMNSHTMLANCHORELEMENT - - // nsIDOMNSHTMLAnchorElement2 - NS_DECL_NSIDOMNSHTMLANCHORELEMENT2 - - // nsILink - NS_IMETHOD GetLinkState(nsLinkState &aState); - NS_IMETHOD SetLinkState(nsLinkState aState); - NS_IMETHOD GetHrefURI(nsIURI** aURI); - NS_IMETHOD LinkAdded() { return NS_OK; } - NS_IMETHOD LinkRemoved() { return NS_OK; } - - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - PRBool aCompileEventHandlers); - virtual void UnbindFromTree(PRBool aDeep = PR_TRUE, - PRBool aNullParent = PR_TRUE); - virtual void SetFocus(nsPresContext* aPresContext); - virtual PRBool IsFocusable(PRBool *aTabIndex = nsnull); - - virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); - virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); - virtual PRBool IsLink(nsIURI** aURI) const; - virtual void GetLinkTarget(nsAString& aTarget); - - nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, PRBool aNotify) - { - return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify); - } - virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - PRBool aNotify); - virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, - PRBool aNotify); - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - -protected: - // The cached visited state - nsLinkState mLinkState; -}; - - NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor) @@ -153,19 +87,8 @@ NS_IMPL_ADDREF_INHERITED(nsHTMLAnchorElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLAnchorElement, nsGenericElement) -// QueryInterface implementation for nsHTMLAnchorElement -NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLAnchorElement, nsGenericHTMLElement) - NS_INTERFACE_TABLE_INHERITED4(nsHTMLAnchorElement, - nsIDOMHTMLAnchorElement, - nsIDOMNSHTMLAnchorElement, - nsIDOMNSHTMLAnchorElement2, - nsILink) -NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLAnchorElement) - - NS_IMPL_ELEMENT_CLONE(nsHTMLAnchorElement) - NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Charset, charset) NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Coords, coords) NS_IMPL_URI_ATTR(nsHTMLAnchorElement, Href, href) diff --git a/content/html/content/src/nsHTMLAnchorElement.h b/content/html/content/src/nsHTMLAnchorElement.h new file mode 100644 index 000000000000..593bdf8cf745 --- /dev/null +++ b/content/html/content/src/nsHTMLAnchorElement.h @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=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 Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Daniel Glazman + * + * 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 ***** */ + +#ifndef nsHTMLAnchorElement_h__ +#define nsHTMLAnchorElement_h__ + +#include "nsGenericHTMLElement.h" +#include "nsIDOMHTMLAnchorElement.h" +#include "nsIDOMNSHTMLAnchorElement2.h" +#include "nsILink.h" + +class nsHTMLAnchorElement : public nsGenericHTMLElement, + public nsIDOMHTMLAnchorElement, + public nsIDOMNSHTMLAnchorElement2, + public nsILink +{ +public: + nsHTMLAnchorElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLAnchorElement(); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) + + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) + + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) + + // nsIDOMHTMLAnchorElement + NS_DECL_NSIDOMHTMLANCHORELEMENT + + // nsIDOMNSHTMLAnchorElement + NS_DECL_NSIDOMNSHTMLANCHORELEMENT + + // nsIDOMNSHTMLAnchorElement2 + NS_DECL_NSIDOMNSHTMLANCHORELEMENT2 + + // nsILink + NS_IMETHOD GetLinkState(nsLinkState &aState); + NS_IMETHOD SetLinkState(nsLinkState aState); + NS_IMETHOD GetHrefURI(nsIURI** aURI); + NS_IMETHOD LinkAdded() { return NS_OK; } + NS_IMETHOD LinkRemoved() { return NS_OK; } + + virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + PRBool aCompileEventHandlers); + virtual void UnbindFromTree(PRBool aDeep = PR_TRUE, + PRBool aNullParent = PR_TRUE); + virtual void SetFocus(nsPresContext* aPresContext); + virtual PRBool IsFocusable(PRBool *aTabIndex = nsnull); + + virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); + virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); + virtual PRBool IsLink(nsIURI** aURI) const; + virtual void GetLinkTarget(nsAString& aTarget); + + nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + const nsAString& aValue, PRBool aNotify) + { + return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify); + } + virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify); + virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, + PRBool aNotify); + + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + +protected: + // The cached visited state + nsLinkState mLinkState; +}; + +#endif diff --git a/content/html/content/src/nsHTMLDivElement.cpp b/content/html/content/src/nsHTMLDivElement.cpp index c4e2bfebd8d1..57e6acd6068c 100644 --- a/content/html/content/src/nsHTMLDivElement.cpp +++ b/content/html/content/src/nsHTMLDivElement.cpp @@ -34,46 +34,14 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsIDOMHTMLDivElement.h" + +#include "nsHTMLDivElement.h" #include "nsIDOMEventTarget.h" -#include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" #include "nsMappedAttributes.h" -class nsHTMLDivElement : public nsGenericHTMLElement, - public nsIDOMHTMLDivElement -{ -public: - nsHTMLDivElement(nsINodeInfo *aNodeInfo); - virtual ~nsHTMLDivElement(); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - // nsIDOMNode - NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) - - // nsIDOMElement - NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLElement - NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLDivElement - NS_DECL_NSIDOMHTMLDIVELEMENT - - virtual PRBool ParseAttribute(PRInt32 aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult); - NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; - virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; -}; - - NS_IMPL_NS_NEW_HTML_ELEMENT(Div) @@ -90,13 +58,6 @@ nsHTMLDivElement::~nsHTMLDivElement() NS_IMPL_ADDREF_INHERITED(nsHTMLDivElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLDivElement, nsGenericElement) - - -// QueryInterface implementation for nsHTMLDivElement -NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLDivElement, nsGenericHTMLElement) - NS_INTERFACE_TABLE_INHERITED1(nsHTMLDivElement, nsIDOMHTMLDivElement) -NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLDivElement) - NS_IMPL_ELEMENT_CLONE(nsHTMLDivElement) diff --git a/intl/unicharutil/src/nsCharsOrderIdFormater.h b/content/html/content/src/nsHTMLDivElement.h similarity index 60% rename from intl/unicharutil/src/nsCharsOrderIdFormater.h rename to content/html/content/src/nsHTMLDivElement.h index 4040d0cf2d35..c6b1541f7e49 100644 --- a/intl/unicharutil/src/nsCharsOrderIdFormater.h +++ b/content/html/content/src/nsHTMLDivElement.h @@ -12,7 +12,7 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. @@ -34,30 +34,42 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#ifndef nsCharsOrderIdFormater_h__ -#define nsCharsOrderIdFormater_h__ +#ifndef nsHTMLDivElement_h__ +#define nsHTMLDivElement_h__ -#include "nsIOrderIdFormater.h" -#include "nsCharsList.h" +#include "nsIDOMHTMLDivElement.h" +#include "nsGenericHTMLElement.h" -class nsCharsOrderIdFormater : public nsIOrderIdFormater { - NS_DECL_ISUPPORTS +class nsHTMLDivElement : public nsGenericHTMLElement, + public nsIDOMHTMLDivElement +{ +public: + nsHTMLDivElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLDivElement(); -public: - - nsCharsOrderIdFormater( nsCharsList* aList); + // nsISupports + NS_DECL_ISUPPORTS_INHERITED - virtual nsCharsOrderIdFormater(); - + // nsIDOMNode + NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) - // Convert one Unicode character into upper case - NS_IMETHOD ToString( PRUint32 aOrder, nsString& aResult) = 0; + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) -private: + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) - nsCharsList *mList; - PRUint32 mBase; + // nsIDOMHTMLDivElement + NS_DECL_NSIDOMHTMLDIVELEMENT + + virtual PRBool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); + NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; + virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; }; -#endif /* nsCharsOrderIdFormater_h__ */ +#endif diff --git a/content/html/content/src/nsHTMLFrameElement.cpp b/content/html/content/src/nsHTMLFrameElement.cpp index d13dcf3bd170..d8f01162b3f5 100644 --- a/content/html/content/src/nsHTMLFrameElement.cpp +++ b/content/html/content/src/nsHTMLFrameElement.cpp @@ -34,48 +34,14 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsIDOMHTMLFrameElement.h" -#include "nsGenericHTMLElement.h" + +#include "nsHTMLFrameElement.h" #include "nsGkAtoms.h" #include "nsIPresShell.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsDOMError.h" - -class nsHTMLFrameElement : public nsGenericHTMLFrameElement, - public nsIDOMHTMLFrameElement -{ -public: - nsHTMLFrameElement(nsINodeInfo *aNodeInfo); - virtual ~nsHTMLFrameElement(); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - // nsIDOMNode - NS_FORWARD_NSIDOMNODE(nsGenericHTMLFrameElement::) - - // nsIDOMElement - NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFrameElement::) - - // nsIDOMHTMLElement - NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFrameElement::) - - // nsIDOMHTMLFrameElement - NS_DECL_NSIDOMHTMLFRAMEELEMENT - - // nsIContent - virtual PRBool ParseAttribute(PRInt32 aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult); - NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; - nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; -}; - - NS_IMPL_NS_NEW_HTML_ELEMENT(Frame) @@ -92,14 +58,6 @@ nsHTMLFrameElement::~nsHTMLFrameElement() NS_IMPL_ADDREF_INHERITED(nsHTMLFrameElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLFrameElement, nsGenericElement) - -// QueryInterface implementation for nsHTMLFrameElement -NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLFrameElement, - nsGenericHTMLFrameElement) - NS_INTERFACE_TABLE_INHERITED1(nsHTMLFrameElement, nsIDOMHTMLFrameElement) -NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFrameElement) - - NS_IMPL_ELEMENT_CLONE(nsHTMLFrameElement) diff --git a/intl/unicharutil/src/nsRangeCharsList.h b/content/html/content/src/nsHTMLFrameElement.h similarity index 59% rename from intl/unicharutil/src/nsRangeCharsList.h rename to content/html/content/src/nsHTMLFrameElement.h index 406457f467a6..1b687a29b07f 100644 --- a/intl/unicharutil/src/nsRangeCharsList.h +++ b/content/html/content/src/nsHTMLFrameElement.h @@ -12,7 +12,7 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. @@ -34,25 +34,43 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#ifndef nsRangeCharsList_h__ -#define nsRangeCharsList_h__ +#ifndef nsHTMLFrameElement_h__ +#define nsHTMLFrameElement_h__ -#include "nsCharsList.h" +#include "nsIDOMHTMLFrameElement.h" +#include "nsGenericHTMLElement.h" -class nsRangeCharsList : public nsCharsList { - -public: - nsRangeCharsList(PRUnichar aStart, PRUnichar aEnd); - virtual ~nsRangeCharsList(); +class nsHTMLFrameElement : public nsGenericHTMLFrameElement, + public nsIDOMHTMLFrameElement +{ +public: + nsHTMLFrameElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLFrameElement(); - virtual PRUnichar Get( PRUint32 aIdx) ; - - virtual PRUint32 Length() ; + // nsISupports + NS_DECL_ISUPPORTS_INHERITED -private: - PRUnichar mStart; - PRUnichar mEnd; + // nsIDOMNode + NS_FORWARD_NSIDOMNODE(nsGenericHTMLFrameElement::) + + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFrameElement::) + + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFrameElement::) + + // nsIDOMHTMLFrameElement + NS_DECL_NSIDOMHTMLFRAMEELEMENT + + // nsIContent + virtual PRBool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); + NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; + nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; }; -#endif /* nsRangeCharsList_h__ */ +#endif diff --git a/content/html/content/src/nsHTMLFrameSetElement.cpp b/content/html/content/src/nsHTMLFrameSetElement.cpp index 9b119680a99a..7d41e2e31dab 100644 --- a/content/html/content/src/nsHTMLFrameSetElement.cpp +++ b/content/html/content/src/nsHTMLFrameSetElement.cpp @@ -34,91 +34,15 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsIDOMHTMLFrameSetElement.h" + +#include "nsHTMLFrameSetElement.h" #include "nsIDOMEventTarget.h" -#include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" -#include "nsIFrameSetElement.h" #include "nsIHTMLDocument.h" #include "nsIDocument.h" -class nsHTMLFrameSetElement : public nsGenericHTMLElement, - public nsIDOMHTMLFrameSetElement, - public nsIFrameSetElement -{ -public: - nsHTMLFrameSetElement(nsINodeInfo *aNodeInfo); - virtual ~nsHTMLFrameSetElement(); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - // nsIDOMNode - NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) - - // nsIDOMElement - NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLElement - NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLFrameSetElement - NS_DECL_NSIDOMHTMLFRAMESETELEMENT - - // These override the SetAttr methods in nsGenericHTMLElement (need - // both here to silence compiler warnings). - nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, PRBool aNotify) - { - return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify); - } - virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - PRBool aNotify); - - // nsIFramesetElement - NS_IMETHOD GetRowSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs); - NS_IMETHOD GetColSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs); - - virtual PRBool ParseAttribute(PRInt32 aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult); - virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, - PRInt32 aModType) const; - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - -private: - nsresult ParseRowCol(const nsAString& aValue, - PRInt32& aNumSpecs, - nsFramesetSpec** aSpecs); - - /** - * The number of size specs in our "rows" attr - */ - PRInt32 mNumRows; - /** - * The number of size specs in our "cols" attr - */ - PRInt32 mNumCols; - /** - * The style hint to return for the rows/cols attrs in - * GetAttributeChangeHint - */ - nsChangeHint mCurrentRowColHint; - /** - * The parsed representation of the "rows" attribute - */ - nsAutoArrayPtr mRowSpecs; // parsed, non-computed dimensions - /** - * The parsed representation of the "cols" attribute - */ - nsAutoArrayPtr mColSpecs; // parsed, non-computed dimensions -}; - NS_IMPL_NS_NEW_HTML_ELEMENT(FrameSet) @@ -137,15 +61,6 @@ NS_IMPL_ADDREF_INHERITED(nsHTMLFrameSetElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLFrameSetElement, nsGenericElement) -// QueryInterface implementation for nsHTMLFrameSetElement -NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLFrameSetElement, - nsGenericHTMLElement) - NS_INTERFACE_TABLE_INHERITED2(nsHTMLFrameSetElement, - nsIDOMHTMLFrameSetElement, - nsIFrameSetElement) -NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFrameSetElement) - - NS_IMPL_ELEMENT_CLONE(nsHTMLFrameSetElement) diff --git a/content/html/content/src/nsHTMLFrameSetElement.h b/content/html/content/src/nsHTMLFrameSetElement.h new file mode 100644 index 000000000000..b02909c1fa1b --- /dev/null +++ b/content/html/content/src/nsHTMLFrameSetElement.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 Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 ***** */ + +#ifndef nsHTMLFrameSetElement_h__ +#define nsHTMLFrameSetElement_h__ + +#include "nsIDOMHTMLFrameSetElement.h" +#include "nsIFrameSetElement.h" +#include "nsGenericHTMLElement.h" + +class nsHTMLFrameSetElement : public nsGenericHTMLElement, + public nsIDOMHTMLFrameSetElement, + public nsIFrameSetElement +{ +public: + nsHTMLFrameSetElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLFrameSetElement(); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) + + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) + + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) + + // nsIDOMHTMLFrameSetElement + NS_DECL_NSIDOMHTMLFRAMESETELEMENT + + // These override the SetAttr methods in nsGenericHTMLElement (need + // both here to silence compiler warnings). + nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + const nsAString& aValue, PRBool aNotify) + { + return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify); + } + virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify); + + // nsIFramesetElement + NS_IMETHOD GetRowSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs); + NS_IMETHOD GetColSpec(PRInt32 *aNumValues, const nsFramesetSpec** aSpecs); + + virtual PRBool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); + virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, + PRInt32 aModType) const; + + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + +private: + nsresult ParseRowCol(const nsAString& aValue, + PRInt32& aNumSpecs, + nsFramesetSpec** aSpecs); + + /** + * The number of size specs in our "rows" attr + */ + PRInt32 mNumRows; + /** + * The number of size specs in our "cols" attr + */ + PRInt32 mNumCols; + /** + * The style hint to return for the rows/cols attrs in + * GetAttributeChangeHint + */ + nsChangeHint mCurrentRowColHint; + /** + * The parsed representation of the "rows" attribute + */ + nsAutoArrayPtr mRowSpecs; // parsed, non-computed dimensions + /** + * The parsed representation of the "cols" attribute + */ + nsAutoArrayPtr mColSpecs; // parsed, non-computed dimensions +}; + +#endif diff --git a/content/html/content/src/nsHTMLIFrameElement.cpp b/content/html/content/src/nsHTMLIFrameElement.cpp index f7cc484c507a..f5abfbdfb4f2 100644 --- a/content/html/content/src/nsHTMLIFrameElement.cpp +++ b/content/html/content/src/nsHTMLIFrameElement.cpp @@ -34,8 +34,8 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsIDOMHTMLIFrameElement.h" -#include "nsGenericHTMLElement.h" + +#include "nsHTMLIFrameElement.h" #include "nsGkAtoms.h" #include "nsPresContext.h" #include "nsIPresShell.h" @@ -45,43 +45,9 @@ #include "nsRuleData.h" #include "nsStyleConsts.h" -class nsHTMLIFrameElement : public nsGenericHTMLFrameElement, - public nsIDOMHTMLIFrameElement -{ -public: - nsHTMLIFrameElement(nsINodeInfo *aNodeInfo); - virtual ~nsHTMLIFrameElement(); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - // nsIDOMNode - NS_FORWARD_NSIDOMNODE(nsGenericHTMLFrameElement::) - - // nsIDOMElement - NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFrameElement::) - - // nsIDOMHTMLElement - NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFrameElement::) - - // nsIDOMHTMLIFrameElement - NS_DECL_NSIDOMHTMLIFRAMEELEMENT - - // nsIContent - virtual PRBool ParseAttribute(PRInt32 aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult); - NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; - virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; -}; - NS_IMPL_NS_NEW_HTML_ELEMENT(IFrame) - nsHTMLIFrameElement::nsHTMLIFrameElement(nsINodeInfo *aNodeInfo) : nsGenericHTMLFrameElement(aNodeInfo) { @@ -95,13 +61,6 @@ nsHTMLIFrameElement::~nsHTMLIFrameElement() NS_IMPL_ADDREF_INHERITED(nsHTMLIFrameElement,nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLIFrameElement,nsGenericElement) -// QueryInterface implementation for nsHTMLIFrameElement -NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLIFrameElement, - nsGenericHTMLFrameElement) - NS_INTERFACE_TABLE_INHERITED1(nsHTMLIFrameElement, nsIDOMHTMLIFrameElement) -NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLIFrameElement) - - NS_IMPL_ELEMENT_CLONE(nsHTMLIFrameElement) diff --git a/content/html/content/src/nsHTMLIFrameElement.h b/content/html/content/src/nsHTMLIFrameElement.h new file mode 100644 index 000000000000..3051ba0ec9e0 --- /dev/null +++ b/content/html/content/src/nsHTMLIFrameElement.h @@ -0,0 +1,78 @@ +/* -*- 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 Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 ***** */ + +#ifndef nsHTMLIFrameElement_h__ +#define nsHTMLIFrameElement_h__ + +#include "nsIFrameSetElement.h" +#include "nsGenericHTMLElement.h" +#include "nsIDOMHTMLIFrameElement.h" + +class nsHTMLIFrameElement : public nsGenericHTMLFrameElement, + public nsIDOMHTMLIFrameElement +{ +public: + nsHTMLIFrameElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLIFrameElement(); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE(nsGenericHTMLFrameElement::) + + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFrameElement::) + + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFrameElement::) + + // nsIDOMHTMLIFrameElement + NS_DECL_NSIDOMHTMLIFRAMEELEMENT + + // nsIContent + virtual PRBool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); + NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; + virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; + + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; +}; + +#endif diff --git a/content/html/content/src/nsHTMLSpanElement.cpp b/content/html/content/src/nsHTMLSpanElement.cpp index 7b02961358f5..6c7c646b4e71 100644 --- a/content/html/content/src/nsHTMLSpanElement.cpp +++ b/content/html/content/src/nsHTMLSpanElement.cpp @@ -34,44 +34,17 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsIDOMHTMLElement.h" + +#include "nsHTMLSpanElement.h" #include "nsIDOMEventTarget.h" -#include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" #include "nsIAtom.h" #include "nsRuleData.h" -class nsHTMLSpanElement : public nsGenericHTMLElement, - public nsIDOMHTMLElement -{ -public: - nsHTMLSpanElement(nsINodeInfo *aNodeInfo); - virtual ~nsHTMLSpanElement(); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - // nsIDOMNode - NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) - - // nsIDOMElement - NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) - - // nsIDOMHTMLElement - NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) - - virtual nsresult GetInnerHTML(nsAString& aInnerHTML); - virtual nsresult SetInnerHTML(const nsAString& aInnerHTML); - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; -}; - - NS_IMPL_NS_NEW_HTML_ELEMENT(Span) - nsHTMLSpanElement::nsHTMLSpanElement(nsINodeInfo *aNodeInfo) : nsGenericHTMLElement(aNodeInfo) { @@ -85,12 +58,6 @@ nsHTMLSpanElement::~nsHTMLSpanElement() NS_IMPL_ADDREF_INHERITED(nsHTMLSpanElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLSpanElement, nsGenericElement) - -// QueryInterface implementation for nsHTMLSpanElement -NS_HTML_CONTENT_INTERFACE_TABLE_HEAD(nsHTMLSpanElement, nsGenericHTMLElement) -NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSpanElement) - - NS_IMPL_ELEMENT_CLONE(nsHTMLSpanElement) diff --git a/intl/unicharutil/public/nsIOrderIdFormater.h b/content/html/content/src/nsHTMLSpanElement.h similarity index 67% rename from intl/unicharutil/public/nsIOrderIdFormater.h rename to content/html/content/src/nsHTMLSpanElement.h index aeeabf5823c8..8d5c6bc74897 100644 --- a/intl/unicharutil/public/nsIOrderIdFormater.h +++ b/content/html/content/src/nsHTMLSpanElement.h @@ -12,7 +12,7 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. @@ -34,32 +34,36 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#ifndef nsIOrderIdFormater_h__ -#define nsIOrderIdFormater_h__ +#ifndef nsHTMLSpanElement_h__ +#define nsHTMLSpanElement_h__ -#include "nsISupports.h" -#include "nsString.h" -#include "nscore.h" +#include "nsIDOMHTMLElement.h" +#include "nsGenericHTMLElement.h" -// {CCD4D372-CCDC-11d2-B3B1-00805F8A6670} -#define NS_IORDERIDFORMATER_IID \ -{ 0xccd4d372, 0xccdc, 0x11d2, \ - { 0xb3, 0xb1, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } }; +class nsHTMLSpanElement : public nsGenericHTMLElement, + public nsIDOMHTMLElement +{ +public: + nsHTMLSpanElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLSpanElement(); + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + // nsIDOMNode + NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) -class nsIOrderIdFormater : public nsISupports { + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) -public: + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IORDERIDFORMATER_IID) - - // Convert one Unicode character into upper case - NS_IMETHOD ToString( PRUint32 aOrder, nsString& aResult) = 0; + virtual nsresult GetInnerHTML(nsAString& aInnerHTML); + virtual nsresult SetInnerHTML(const nsAString& aInnerHTML); + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsIOrderIdFormater, NS_IORDERIDFORMATER_IID) - -#endif /* nsIOrderIdFormater_h__ */ +#endif diff --git a/content/html/document/src/Makefile.in b/content/html/document/src/Makefile.in index 51dfe3013a08..a9b8b5923044 100644 --- a/content/html/document/src/Makefile.in +++ b/content/html/document/src/Makefile.in @@ -91,6 +91,8 @@ CPPSRCS = \ nsWyciwygProtocolHandler.cpp \ $(NULL) +GQI_SRCS = htmldocument.gqi + EXPORTS = \ nsIHTMLDocument.h \ $(NULL) diff --git a/content/html/document/src/htmldocument.gqi b/content/html/document/src/htmldocument.gqi new file mode 100644 index 000000000000..b08a1c0858f6 --- /dev/null +++ b/content/html/document/src/htmldocument.gqi @@ -0,0 +1,17 @@ +%import "contentbase.gqi" + +%import-idl "nsIDOMHTMLDocument.idl" +%import-idl "nsIDOMNSHTMLDocument.idl" + +%{C++ +#include "nsHTMLDocument.h" +%} + +%pseudo-iid nsIHTMLDocument 61e989a8-70cd-4582-845e-6e5e12559a83 + +NS_INTERFACE_MAP_BEGIN(nsHTMLDocument, nsDocument) + NS_INTERFACE_MAP_ENTRY(nsIHTMLDocument) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLDocument) + NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLDocument) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLDocument) +NS_INTERFACE_MAP_END diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 35482a9012c1..42b578bf7188 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -416,18 +416,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument) NS_IMPL_RELEASE_INHERITED(nsHTMLDocument, nsDocument) - -// QueryInterface implementation for nsHTMLDocument -NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLDocument) - NS_INTERFACE_TABLE_INHERITED3(nsHTMLDocument, - nsIHTMLDocument, - nsIDOMHTMLDocument, - nsIDOMNSHTMLDocument) - NS_INTERFACE_TABLE_TO_MAP_SEGUE - NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLDocument) -NS_INTERFACE_MAP_END_INHERITING(nsDocument) - - nsresult nsHTMLDocument::Init() { @@ -2095,17 +2083,39 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) } nsCOMPtr callerPrincipal; - nsContentUtils::GetSecurityManager()-> - GetSubjectPrincipal(getter_AddRefs(callerPrincipal)); + nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); + + secMan->GetSubjectPrincipal(getter_AddRefs(callerPrincipal)); + + if (!callerPrincipal) { + // If we're called from C++ we can't do a document.open w/o + // changing the principal of the document to something like + // about:blank (as that's the only sane thing to do when we don't + // know the origin of this call), and since we can't change the + // principals of a document for security reasons we'll have to + // refuse to go ahead with this call. + + return NS_ERROR_DOM_SECURITY_ERR; + } + + // We're called from script. Make sure the script is from the same + // origin, not just that the caller can access the document. This is + // needed to keep document principals from ever changing, which is + // needed because of the way we use our XOW code, and is a sane + // thing to do anyways. + + PRBool equals = PR_FALSE; + if (NS_FAILED(callerPrincipal->Equals(NodePrincipal(), &equals)) || + !equals) { + return NS_ERROR_DOM_SECURITY_ERR; + } // The URI for the document after this call. Get it from the calling // principal (if available), or set it to "about:blank" if no // principal is reachable. nsCOMPtr uri; + callerPrincipal->GetURI(getter_AddRefs(uri)); - if (callerPrincipal) { - callerPrincipal->GetURI(getter_AddRefs(uri)); - } if (!uri) { rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")); @@ -2163,15 +2173,6 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace) // Remember the old scope in case the call to SetNewDocument changes it. nsCOMPtr oldScope(do_QueryReferent(mScopeObject)); - // If callerPrincipal doesn't match our principal. make sure that - // SetNewDocument gives us a new inner window and clears our scope. - PRBool samePrincipal; - if (!callerPrincipal || - NS_FAILED(callerPrincipal->Equals(NodePrincipal(), &samePrincipal)) || - !samePrincipal) { - SetIsInitialDocument(PR_FALSE); - } - rv = window->SetNewDocument(this, nsnull, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); diff --git a/content/html/document/src/nsMediaDocument.cpp b/content/html/document/src/nsMediaDocument.cpp index 6bf66039d5d7..20df54534d53 100644 --- a/content/html/document/src/nsMediaDocument.cpp +++ b/content/html/document/src/nsMediaDocument.cpp @@ -265,13 +265,10 @@ nsMediaDocument::CreateSyntheticDocument() nsresult nsMediaDocument::StartLayout() { + mMayStartLayout = PR_TRUE; nsPresShellIterator iter(this); nsCOMPtr shell; while ((shell = iter.GetNextShell())) { - // Make shell an observer for next time. - shell->BeginObservingDocument(); - - // Initial-reflow this time. nsRect visibleArea = shell->GetPresContext()->GetVisibleArea(); nsCOMPtr shellGrip = shell; nsresult rv = shell->InitialReflow(visibleArea.width, visibleArea.height); diff --git a/content/svg/content/src/nsSVGElement.h b/content/svg/content/src/nsSVGElement.h index 1701a0b769cc..2de3c3141050 100644 --- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -123,6 +123,9 @@ public: // nsISupportsWeakReference // implementation inherited from nsSupportsWeakReference + // Gets the element that establishes the rectangular viewport against which + // we should resolve percentage lengths (our "coordinate context"). Returns + // nsnull for outer or SVG without an parent (invalid SVG). nsSVGSVGElement* GetCtx(); virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr); diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp index 2c11fb204640..28174f075f3f 100644 --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -2927,6 +2927,9 @@ nsSVGFETileElement::Filter(nsSVGFilterInstance *instance) #endif nsRect tile = fr.GetSourceRegion(); + if (tile.width == 0 || tile.height == 0) + return NS_OK; + for (PRInt32 y = rect.y; y < rect.YMost(); y++) { PRUint32 tileY = tile.y + (y - tile.y + tile.height) % tile.height; for (PRInt32 x = rect.x; x < rect.XMost(); x++) { diff --git a/content/svg/content/src/nsSVGGraphicElement.cpp b/content/svg/content/src/nsSVGGraphicElement.cpp index 886dc94be28e..14d07232c0c5 100644 --- a/content/svg/content/src/nsSVGGraphicElement.cpp +++ b/content/svg/content/src/nsSVGGraphicElement.cpp @@ -99,10 +99,12 @@ NS_IMETHODIMP nsSVGGraphicElement::GetBBox(nsIDOMSVGRect **_retval) NS_ASSERTION(svgframe, "wrong frame type"); if (svgframe) { svgframe->SetMatrixPropagation(PR_FALSE); - svgframe->NotifyCanvasTMChanged(PR_TRUE); + svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); nsresult rv = svgframe->GetBBox(_retval); svgframe->SetMatrixPropagation(PR_TRUE); - svgframe->NotifyCanvasTMChanged(PR_TRUE); + svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); return rv; } return NS_ERROR_FAILURE; diff --git a/content/svg/content/src/nsSVGLength.cpp b/content/svg/content/src/nsSVGLength.cpp index e99c194df932..56942eb2a2bf 100644 --- a/content/svg/content/src/nsSVGLength.cpp +++ b/content/svg/content/src/nsSVGLength.cpp @@ -530,8 +530,11 @@ float nsSVGLength::mmPerPixel() return 1.0f; } - nsSVGSVGElement *ctx = - static_cast(element.get())->GetCtx(); + nsSVGSVGElement *ctx = static_cast(element.get())->GetCtx(); + if (!ctx) { + return 1e-4f; // some small value + } + float mmPerPx = ctx->GetMMPerPx(mCtxType); if (mmPerPx == 0.0f) { @@ -550,8 +553,11 @@ float nsSVGLength::AxisLength() return 1.0f; } - nsSVGSVGElement *ctx = - static_cast(element.get())->GetCtx(); + nsSVGSVGElement *ctx = static_cast(element.get())->GetCtx(); + if (!ctx) { + return 1e-20f; // some small value + } + float d = ctx->GetLength(mCtxType); if (d == 0.0f) { diff --git a/content/svg/content/src/nsSVGLength2.h b/content/svg/content/src/nsSVGLength2.h index e464b55b7821..02ce8da32070 100644 --- a/content/svg/content/src/nsSVGLength2.h +++ b/content/svg/content/src/nsSVGLength2.h @@ -71,6 +71,8 @@ public: PRUint8 GetCtxType() const { return mCtxType; } PRUint8 GetSpecifiedUnitType() const { return mSpecifiedUnitType; } + PRBool IsPercentage() const + { return mSpecifiedUnitType == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE; } float GetAnimValInSpecifiedUnits() const { return mAnimVal; } float GetBaseValInSpecifiedUnits() const { return mBaseVal; } diff --git a/content/svg/content/src/nsSVGSVGElement.cpp b/content/svg/content/src/nsSVGSVGElement.cpp index 0747e5fa1e01..804b81792224 100644 --- a/content/svg/content/src/nsSVGSVGElement.cpp +++ b/content/svg/content/src/nsSVGSVGElement.cpp @@ -681,10 +681,12 @@ nsSVGSVGElement::GetBBox(nsIDOMSVGRect **_retval) CallQueryInterface(frame, &svgframe); if (svgframe) { svgframe->SetMatrixPropagation(PR_FALSE); - svgframe->NotifyCanvasTMChanged(PR_TRUE); + svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); nsresult rv = svgframe->GetBBox(_retval); svgframe->SetMatrixPropagation(PR_TRUE); - svgframe->NotifyCanvasTMChanged(PR_TRUE); + svgframe->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); return rv; } else { // XXX: outer svg diff --git a/content/xbl/crashtests/342954-1.xhtml b/content/xbl/crashtests/342954-1.xhtml new file mode 100644 index 000000000000..dbaa153840ef --- /dev/null +++ b/content/xbl/crashtests/342954-1.xhtml @@ -0,0 +1,46 @@ + + + + + + + + + + +
+ +
+
+
+
+ + + + + + +Span + +
Marquee
+ + + + + diff --git a/content/xbl/crashtests/342954-2-xbl.xml b/content/xbl/crashtests/342954-2-xbl.xml new file mode 100644 index 000000000000..3e73f1355ad2 --- /dev/null +++ b/content/xbl/crashtests/342954-2-xbl.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/content/xbl/crashtests/342954-2.xhtml b/content/xbl/crashtests/342954-2.xhtml new file mode 100644 index 000000000000..4a250e31c2c7 --- /dev/null +++ b/content/xbl/crashtests/342954-2.xhtml @@ -0,0 +1,29 @@ + + + + + + + +Span + +
Marquee
+ + + diff --git a/content/xbl/crashtests/crashtests.list b/content/xbl/crashtests/crashtests.list index f5353646de7d..fbee34eef18a 100644 --- a/content/xbl/crashtests/crashtests.list +++ b/content/xbl/crashtests/crashtests.list @@ -2,3 +2,5 @@ load 368276-1.xhtml load 368641-1.xhtml load 382376-1.xhtml load 382376-2.xhtml +load 342954-1.xhtml +load 342954-2.xhtml diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp index a23a4c869962..cadf843133e8 100644 --- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -1384,8 +1384,7 @@ nsBindingManager::ContentAppended(nsIDocument* aDocument, &isAnonymousContentList); if (nodeList && isAnonymousContentList) { - // Find a non-pseudo-insertion point and just jam ourselves in. - // This is not 100% correct. Hack city, baby. + // Find the one non-pseudo-insertion point and just add ourselves. nsAnonymousContentList* contentList = static_cast(nodeList.get()); @@ -1424,13 +1423,33 @@ nsBindingManager::ContentInserted(nsIDocument* aDocument, } } +static void +RemoveChildFromInsertionPoint(nsAnonymousContentList* aInsertionPointList, + nsIContent* aChild, + PRBool aRemoveFromPseudoPoints) +{ + // We need to find the insertion point that contains aChild and remove it + // from that insertion point. Sadly, we don't know which point it is, or + // when we've hit it, but just trying to remove from all the pseudo or + // non-pseudo insertion points, depending on the value of + // aRemoveFromPseudoPoints, should work. + PRInt32 count = aInsertionPointList->GetInsertionPointCount(); + for (PRInt32 i = 0; i < count; i++) { + nsXBLInsertionPoint* point = + aInsertionPointList->GetInsertionPointAt(i); + if ((point->GetInsertionIndex() == -1) == aRemoveFromPseudoPoints) { + point->RemoveChild(aChild); + } + } +} + void nsBindingManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { - if (aIndexInContainer != -1 && + if (aContainer && aIndexInContainer != -1 && (mContentListTable.ops || mAnonymousNodesTable.ops)) { // It's not anonymous nsCOMPtr point = GetNestedInsertionPoint(aContainer, aChild); @@ -1443,17 +1462,26 @@ nsBindingManager::ContentRemoved(nsIDocument* aDocument, if (nodeList && isAnonymousContentList) { // Find a non-pseudo-insertion point and remove ourselves. - nsAnonymousContentList* contentList = static_cast(static_cast(nodeList)); - PRInt32 count = contentList->GetInsertionPointCount(); - for (PRInt32 i =0; i < count; i++) { - nsXBLInsertionPoint* point = contentList->GetInsertionPointAt(i); - if (point->GetInsertionIndex() != -1) { - point->RemoveChild(aChild); - } - } + RemoveChildFromInsertionPoint(static_cast + (static_cast + (nodeList)), + aChild, + PR_FALSE); SetInsertionParent(aChild, nsnull); } - } + } + + // Whether the child has a nested insertion point or not, aContainer might + // have insertion points under it. If that's the case, we need to remove + // aChild from the pseudo insertion point it's in. + if (mContentListTable.ops) { + nsAnonymousContentList* insertionPointList = + static_cast(LookupObject(mContentListTable, + aContainer)); + if (insertionPointList) { + RemoveChildFromInsertionPoint(insertionPointList, aChild, PR_TRUE); + } + } } } @@ -1534,7 +1562,7 @@ nsBindingManager::HandleChildInsertion(nsIContent* aContainer, { NS_PRECONDITION(aChild, "Must have child"); NS_PRECONDITION(!aContainer || - aContainer->IndexOf(aChild) == aIndexInContainer, + PRUint32(aContainer->IndexOf(aChild)) == aIndexInContainer, "Child not at the right index?"); nsIContent* ins = GetNestedInsertionPoint(aContainer, aChild); @@ -1546,8 +1574,10 @@ nsBindingManager::HandleChildInsertion(nsIContent* aContainer, &isAnonymousContentList); if (nodeList && isAnonymousContentList) { - // Find a non-pseudo-insertion point and just jam ourselves in. - // This is not 100% correct. Hack city, baby. + // Find a non-pseudo-insertion point and just jam ourselves in. This is + // not 100% correct, since there might be multiple insertion points under + // this insertion parent, and we should really be using the one that + // matches our content... Hack city, baby. nsAnonymousContentList* contentList = static_cast(nodeList.get()); diff --git a/content/xbl/src/nsBindingManager.h b/content/xbl/src/nsBindingManager.h index 689ba3de10f5..8651f0e42f37 100755 --- a/content/xbl/src/nsBindingManager.h +++ b/content/xbl/src/nsBindingManager.h @@ -241,7 +241,9 @@ protected: // A mapping from nsIContent* to an nsIDOMNodeList* // (nsAnonymousContentList*). This list contains an accurate // reflection of our *explicit* children (once intermingled with - // insertion points) in the altered DOM. + // insertion points) in the altered DOM. There is an entry for a + // content node in this table only if that content node has some + // kids. PLDHashTable mContentListTable; // A mapping from nsIContent* to an nsIDOMNodeList* @@ -250,7 +252,10 @@ protected: // intermingled with insertion points) in the altered DOM. This // table is not used if no insertion points were defined directly // underneath a tag in a binding. The NodeList from the - // is used instead as a performance optimization. + // is used instead as a performance optimization. There + // is an entry for a content node in this table only if that content + // node has a binding with a attached and this + // contains elements directly. PLDHashTable mAnonymousNodesTable; // A mapping from nsIContent* to nsIContent*. The insertion parent diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp index f5c263d1ea13..267543188ec6 100644 --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -193,14 +193,8 @@ nsXMLDocument::~nsXMLDocument() mLoopingForSyncLoad = PR_FALSE; } -NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLDocument) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLDocument, nsDocument) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - // QueryInterface implementation for nsXMLDocument -NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXMLDocument) +NS_INTERFACE_TABLE_HEAD(nsXMLDocument) NS_INTERFACE_TABLE_INHERITED3(nsXMLDocument, nsIInterfaceRequestor, nsIChannelEventSink, @@ -227,8 +221,6 @@ void nsXMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) { nsDocument::Reset(aChannel, aLoadGroup); - - mScriptContext = nsnull; } void @@ -240,7 +232,7 @@ nsXMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, mChannel->Cancel(NS_BINDING_ABORTED); mChannelIsPending = nsnull; } - + nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal); } @@ -289,27 +281,19 @@ nsXMLDocument::OnChannelRedirect(nsIChannel *aOldChannel, nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); - if (mScriptContext && !mCrossSiteAccessEnabled) { - nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", & rv)); - if (NS_FAILED(rv)) - return rv; + nsCOMPtr oldURI; + rv = aOldChannel->GetURI(getter_AddRefs(oldURI)); + NS_ENSURE_SUCCESS(rv, rv); - JSContext *cx = (JSContext *)mScriptContext->GetNativeContext(); - if (!cx) - return NS_ERROR_UNEXPECTED; + nsCOMPtr newURI; + rv = aNewChannel->GetURI(getter_AddRefs(newURI)); + NS_ENSURE_SUCCESS(rv, rv); - stack->Push(cx); + rv = nsContentUtils::GetSecurityManager()-> + CheckSameOriginURI(oldURI, newURI, PR_TRUE); - rv = secMan->CheckSameOrigin(nsnull, newLocation); - - stack->Pop(&cx); - - if (NS_FAILED(rv)) { - // The security manager set a pending exception. Since we're - // running under the event loop, we need to report it. - ::JS_ReportPendingException(cx); - return rv; - } + if (NS_FAILED(rv)) { + return rv; } // XXXbz Shouldn't we look at the owner on the new channel at some point? @@ -360,64 +344,21 @@ nsXMLDocument::SetAsync(PRBool aAsync) return NS_OK; } -nsresult -nsXMLDocument::GetLoadGroup(nsILoadGroup **aLoadGroup) -{ - NS_ENSURE_ARG_POINTER(aLoadGroup); - *aLoadGroup = nsnull; - - if (mScriptContext) { - nsCOMPtr window = - do_QueryInterface(mScriptContext->GetGlobalObject()); - - if (window) { - nsCOMPtr domdoc; - window->GetDocument(getter_AddRefs(domdoc)); - nsCOMPtr doc = do_QueryInterface(domdoc); - if (doc) { - *aLoadGroup = doc->GetDocumentLoadGroup().get(); // already_AddRefed - } - } - } - - return NS_OK; -} - - NS_IMETHODIMP nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) { NS_ENSURE_ARG_POINTER(aReturn); *aReturn = PR_FALSE; - nsIScriptContext *callingContext = nsnull; - - nsCOMPtr stack = - do_GetService("@mozilla.org/js/xpc/ContextStack;1"); - if (stack) { - JSContext *cx; - if (NS_SUCCEEDED(stack->Peek(&cx)) && cx) { - callingContext = nsJSUtils::GetDynamicScriptContext(cx); - } - } + nsCOMPtr callingDoc = + do_QueryInterface(nsContentUtils::GetDocumentFromContext()); nsIURI *baseURI = mDocumentURI; nsCAutoString charset; - if (callingContext) { - nsCOMPtr window = - do_QueryInterface(callingContext->GetGlobalObject()); - - if (window) { - nsCOMPtr dom_doc; - window->GetDocument(getter_AddRefs(dom_doc)); - nsCOMPtr doc(do_QueryInterface(dom_doc)); - - if (doc) { - baseURI = doc->GetBaseURI(); - charset = doc->GetDocumentCharacterSet(); - } - } + if (callingDoc) { + baseURI = callingDoc->GetBaseURI(); + charset = callingDoc->GetDocumentCharacterSet(); } // Create a new URI @@ -427,6 +368,41 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) return rv; } + nsCOMPtr codebase; + NodePrincipal()->GetURI(getter_AddRefs(codebase)); + + // Get security manager, check to see whether the current document + // is allowed to load this URI. It's important to use the current + // document's principal for this check so that we don't end up in a + // case where code with elevated privileges is calling us and + // changing the principal of this document. + nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); + + if (codebase) { + rv = secMan->CheckSameOriginURI(codebase, uri, PR_FALSE); + + if (NS_FAILED(rv)) { + return rv; + } + } else { + // We're called from chrome, check to make sure the URI we're + // about to load is also chrome. + + PRBool isChrome = PR_FALSE; + if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) { + return NS_ERROR_DOM_SECURITY_ERR; + } + } + + rv = secMan->CheckConnect(nsnull, uri, "XMLDocument", "load"); + if (NS_FAILED(rv)) { + // We need to return success here so that JS will get a proper + // exception thrown later. Native calls should always result in + // CheckConnect() succeeding, but in case JS calls C++ which calls + // this code the exception might be lost. + return NS_OK; + } + // Partial Reset, need to restore principal for security reasons and // event listener manager so that load listeners etc. will // remain. This should be done before the security check is done to @@ -438,48 +414,20 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn) nsCOMPtr elm(mListenerManager); mListenerManager = nsnull; - ResetToURI(uri, nsnull, principal); - - mListenerManager = elm; - - // Get security manager, check to see if we're allowed to load this URI - nsCOMPtr secMan = - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - return rv; - } - - rv = secMan->CheckConnect(nsnull, uri, "XMLDocument", "load"); - if (NS_FAILED(rv)) { - // We need to return success here so that JS will get a proper - // exception thrown later. Native calls should always result in - // CheckConnect() succeeding, but in case JS calls C++ which calls - // this code the exception might be lost. - return NS_OK; - } - - // Store script context, if any, in case we encounter redirect - // (because we need it there) - - mScriptContext = callingContext; - - // Find out if UniversalBrowserRead privileges are enabled - we will - // need this in case of a redirect - PRBool crossSiteAccessEnabled; - rv = secMan->IsCapabilityEnabled("UniversalBrowserRead", - &crossSiteAccessEnabled); - if (NS_FAILED(rv)) { - return rv; - } - - mCrossSiteAccessEnabled = crossSiteAccessEnabled; - - // Create a channel // When we are called from JS we can find the load group for the page, // and add ourselves to it. This way any pending requests // will be automatically aborted if the user leaves the page. + nsCOMPtr loadGroup; - GetLoadGroup(getter_AddRefs(loadGroup)); + if (callingDoc) { + loadGroup = callingDoc->GetDocumentLoadGroup(); + } + + ResetToURI(uri, loadGroup, principal); + + mListenerManager = elm; + + // Create a channel nsCOMPtr channel; // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, diff --git a/content/xml/document/src/nsXMLDocument.h b/content/xml/document/src/nsXMLDocument.h index cffd484c07fe..0491903abd67 100644 --- a/content/xml/document/src/nsXMLDocument.h +++ b/content/xml/document/src/nsXMLDocument.h @@ -95,14 +95,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLDocument, nsDocument) - void SetLoadedAsData(PRBool aLoadedAsData) { mLoadedAsData = aLoadedAsData; } protected: - virtual nsresult GetLoadGroup(nsILoadGroup **aLoadGroup); - - nsCOMPtr mScriptContext; - // mChannelIsPending indicates whether we're currently asynchronously loading // data from mChannel (via document.load() or normal load). It's set to true // when we first find out about the channel (StartDocumentLoad) and set to @@ -110,7 +104,6 @@ protected: // mChannel is also cancelled. Note that if this member is true, mChannel // cannot be null. PRPackedBool mChannelIsPending; - PRPackedBool mCrossSiteAccessEnabled; PRPackedBool mLoadedAsInteractiveData; PRPackedBool mAsync; PRPackedBool mLoopingForSyncLoad; diff --git a/content/xslt/public/txDouble.h b/content/xslt/public/txDouble.h index 90647714565a..422eeff2090a 100644 --- a/content/xslt/public/txDouble.h +++ b/content/xslt/public/txDouble.h @@ -68,14 +68,7 @@ static fp_except_t oldmask = fpsetmask(~allmask); #endif #endif -#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2 -/** - * This version of the macros is safe for the alias optimizations - * that gcc does, but uses gcc-specific extensions. - */ - typedef union txdpun { - PRFloat64 d; struct { #if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA) PRUint32 lo, hi; @@ -83,8 +76,14 @@ typedef union txdpun { PRUint32 hi, lo; #endif } s; + PRFloat64 d; } txdpun; +#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2 +/** + * This version of the macros is safe for the alias optimizations + * that gcc does, but uses gcc-specific extensions. + */ #define TX_DOUBLE_HI32(x) (__extension__ ({ txdpun u; u.d = (x); u.s.hi; })) #define TX_DOUBLE_LO32(x) (__extension__ ({ txdpun u; u.d = (x); u.s.lo; })) @@ -113,11 +112,11 @@ typedef union txdpun { (TX_DOUBLE_LO32(x) || (TX_DOUBLE_HI32(x) & TX_DOUBLE_HI32_MANTMASK))) #ifdef IS_BIG_ENDIAN -#define TX_DOUBLE_NaN {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK, \ - 0xffffffff} +#define TX_DOUBLE_NaN {{TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK, \ + 0xffffffff}} #else -#define TX_DOUBLE_NaN {0xffffffff, \ - TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK} +#define TX_DOUBLE_NaN {{0xffffffff, \ + TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_MANTMASK}} #endif #if defined(XP_WIN) diff --git a/content/xslt/src/base/txDouble.cpp b/content/xslt/src/base/txDouble.cpp index c1a7d2f33b32..06a3b59690d5 100644 --- a/content/xslt/src/base/txDouble.cpp +++ b/content/xslt/src/base/txDouble.cpp @@ -50,18 +50,18 @@ */ //-- Initialize Double related constants -const PRUint32 nanMask[2] = TX_DOUBLE_NaN; +const txdpun nanMask = TX_DOUBLE_NaN; #ifdef IS_BIG_ENDIAN -const PRUint32 infMask[2] = {TX_DOUBLE_HI32_EXPMASK, 0}; -const PRUint32 negInfMask[2] = {TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT, 0}; +const txdpun infMask = {{TX_DOUBLE_HI32_EXPMASK, 0}}; +const txdpun negInfMask = {{TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT, 0}}; #else -const PRUint32 infMask[2] = {0, TX_DOUBLE_HI32_EXPMASK}; -const PRUint32 negInfMask[2] = {0, TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT}; +const txdpun infMask = {{0, TX_DOUBLE_HI32_EXPMASK}}; +const txdpun negInfMask = {{0, TX_DOUBLE_HI32_EXPMASK | TX_DOUBLE_HI32_SIGNBIT}}; #endif -const double Double::NaN = *((double*)nanMask); -const double Double::POSITIVE_INFINITY = *((double*)infMask); -const double Double::NEGATIVE_INFINITY = *((double*)negInfMask); +const double Double::NaN = nanMask.d; +const double Double::POSITIVE_INFINITY = infMask.d; +const double Double::NEGATIVE_INFINITY = negInfMask.d; /* * Determines whether the given double represents positive or negative diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 968be892fb1f..0f26898c7c78 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -419,6 +419,7 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, // NOTE: If this ever starts calling nsDocument::StartDocumentLoad // we'll possibly need to reset our content type afterwards. mStillWalking = PR_TRUE; + mMayStartLayout = PR_FALSE; mDocumentLoadGroup = do_GetWeakReference(aLoadGroup); mDocumentTitle.SetIsVoid(PR_TRUE); @@ -1932,19 +1933,13 @@ nsXULDocument::StartLayout(void) } } + mMayStartLayout = PR_TRUE; + // Make sure we're holding a strong ref to |shell| before we call // InitialReflow() nsCOMPtr shellGrip = shell; rv = shell->InitialReflow(r.width, r.height); NS_ENSURE_SUCCESS(rv, rv); - - // Start observing the document _after_ we do the initial - // reflow. Otherwise, we'll get into an trouble trying to - // create kids before the root frame is established. - // XXXbz why is that an issue here and not in nsContentSink or - // nsDocumentViewer? Perhaps we should just flush the way - // nsDocumentViewer does? - shell->BeginObservingDocument(); } return NS_OK; diff --git a/db/sqlite3/README.MOZILLA b/db/sqlite3/README.MOZILLA index 6d1cc2ce6ead..e91609a82d4c 100644 --- a/db/sqlite3/README.MOZILLA +++ b/db/sqlite3/README.MOZILLA @@ -1,4 +1,4 @@ -This is sqlite 3.5.4 +This is sqlite 3.5.4.1 -- Shawn Wilsher 01/2008 diff --git a/db/sqlite3/src/sqlite3.c b/db/sqlite3/src/sqlite3.c index 146efa6ececf..8a288afc1d35 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.5.4. By combining all the individual C code files into this +** version 3.5.4.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 @@ -17,7 +17,7 @@ ** is also in a separate file. This file contains only code for the core ** SQLite library. ** -** This amalgamation was generated on 2007-12-14 17:40:56 UTC. +** This amalgamation was generated on 2008-01-20 20:21:55 UTC. */ #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE @@ -40,7 +40,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -104,7 +104,7 @@ ** ** This file defines various limits of what SQLite can process. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -141,10 +141,10 @@ /* ** The maximum length of a single SQL statement in bytes. -** The hard limit is 1 million. +** A value of zero means there is no limit. */ #ifndef SQLITE_MAX_SQL_LENGTH -# define SQLITE_MAX_SQL_LENGTH 1000000 +# define SQLITE_MAX_SQL_LENGTH 0 #endif /* @@ -395,7 +395,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -453,7 +453,7 @@ extern "C" { ** ** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. */ -#define SQLITE_VERSION "3.5.4" +#define SQLITE_VERSION "3.5.4.1" #define SQLITE_VERSION_NUMBER 3005004 /* @@ -4222,7 +4222,7 @@ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ @@ -4655,7 +4655,7 @@ struct BusyHandler { ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -4865,7 +4865,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -4960,161 +4960,161 @@ typedef struct VdbeOpList VdbeOpList; /************** Begin file opcodes.h *****************************************/ /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ -#define OP_MemLoad 1 -#define OP_VNext 2 -#define OP_HexBlob 126 /* same as TK_BLOB */ -#define OP_Column 3 -#define OP_SetCookie 4 -#define OP_IfMemPos 5 -#define OP_Real 125 /* same as TK_FLOAT */ -#define OP_Sequence 6 -#define OP_MoveGt 7 -#define OP_Ge 72 /* same as TK_GE */ -#define OP_RowKey 8 -#define OP_Eq 68 /* same as TK_EQ */ -#define OP_OpenWrite 9 -#define OP_NotNull 66 /* same as TK_NOTNULL */ -#define OP_If 10 -#define OP_ToInt 141 /* same as TK_TO_INT */ -#define OP_String8 88 /* same as TK_STRING */ -#define OP_Pop 11 -#define OP_VRowid 12 -#define OP_CollSeq 13 -#define OP_OpenRead 14 -#define OP_Expire 15 -#define OP_AutoCommit 17 -#define OP_Gt 69 /* same as TK_GT */ -#define OP_IntegrityCk 18 -#define OP_Sort 19 -#define OP_Function 20 -#define OP_And 61 /* same as TK_AND */ -#define OP_Subtract 79 /* same as TK_MINUS */ -#define OP_Noop 21 -#define OP_Return 22 -#define OP_Remainder 82 /* same as TK_REM */ -#define OP_NewRowid 23 -#define OP_Multiply 80 /* same as TK_STAR */ -#define OP_IfMemNeg 24 -#define OP_Variable 25 -#define OP_String 26 -#define OP_RealAffinity 27 -#define OP_VRename 28 -#define OP_ParseSchema 29 -#define OP_VOpen 30 -#define OP_Close 31 -#define OP_CreateIndex 32 -#define OP_IsUnique 33 -#define OP_NotFound 34 -#define OP_Int64 35 -#define OP_MustBeInt 36 -#define OP_Halt 37 -#define OP_Rowid 38 -#define OP_IdxLT 39 -#define OP_AddImm 40 -#define OP_Statement 41 -#define OP_RowData 42 -#define OP_MemMax 43 -#define OP_Push 44 -#define OP_Or 60 /* same as TK_OR */ -#define OP_NotExists 45 -#define OP_MemIncr 46 -#define OP_Gosub 47 -#define OP_Divide 81 /* same as TK_SLASH */ -#define OP_Integer 48 -#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/ -#define OP_MemInt 49 -#define OP_Prev 50 -#define OP_Concat 83 /* same as TK_CONCAT */ -#define OP_BitAnd 74 /* same as TK_BITAND */ -#define OP_VColumn 51 -#define OP_CreateTable 52 -#define OP_Last 53 -#define OP_IsNull 65 /* same as TK_ISNULL */ -#define OP_IncrVacuum 54 -#define OP_IdxRowid 55 -#define OP_MakeIdxRec 56 -#define OP_ShiftRight 77 /* same as TK_RSHIFT */ -#define OP_ResetCount 57 -#define OP_FifoWrite 58 -#define OP_Callback 59 -#define OP_ContextPush 62 -#define OP_DropTrigger 63 -#define OP_DropIndex 64 -#define OP_IdxGE 73 -#define OP_IdxDelete 84 -#define OP_Vacuum 86 -#define OP_MoveLe 89 -#define OP_IfNot 90 -#define OP_DropTable 91 -#define OP_MakeRecord 92 -#define OP_ToBlob 139 /* same as TK_TO_BLOB */ -#define OP_Delete 93 -#define OP_StackDepth 94 -#define OP_AggFinal 95 -#define OP_ShiftLeft 76 /* same as TK_LSHIFT */ -#define OP_Dup 96 -#define OP_Goto 97 -#define OP_TableLock 98 -#define OP_FifoRead 99 -#define OP_Clear 100 -#define OP_IdxGT 101 -#define OP_MoveLt 102 -#define OP_Le 70 /* same as TK_LE */ -#define OP_VerifyCookie 103 -#define OP_AggStep 104 -#define OP_Pull 105 -#define OP_ToText 138 /* same as TK_TO_TEXT */ -#define OP_Not 16 /* same as TK_NOT */ -#define OP_ToReal 142 /* same as TK_TO_REAL */ -#define OP_SetNumColumns 106 -#define OP_AbsValue 107 -#define OP_Transaction 108 -#define OP_VFilter 109 -#define OP_Negative 85 /* same as TK_UMINUS */ -#define OP_Ne 67 /* same as TK_NE */ -#define OP_VDestroy 110 -#define OP_ContextPop 111 -#define OP_BitOr 75 /* same as TK_BITOR */ -#define OP_Next 112 -#define OP_IdxInsert 113 -#define OP_Distinct 114 +#define OP_ReadCookie 1 +#define OP_AutoCommit 2 +#define OP_Found 3 +#define OP_NullRow 4 #define OP_Lt 71 /* same as TK_LT */ -#define OP_Insert 115 -#define OP_Destroy 116 -#define OP_ReadCookie 117 -#define OP_ForceInt 118 -#define OP_LoadAnalysis 119 -#define OP_Explain 120 -#define OP_IfMemZero 121 -#define OP_OpenPseudo 122 -#define OP_OpenEphemeral 123 -#define OP_Null 124 -#define OP_Blob 127 +#define OP_MoveLe 5 +#define OP_Variable 6 +#define OP_Pull 7 +#define OP_RealAffinity 8 +#define OP_Sort 9 +#define OP_IfNot 10 +#define OP_Gosub 11 #define OP_Add 78 /* same as TK_PLUS */ -#define OP_MemStore 128 -#define OP_Rewind 129 -#define OP_MoveGe 130 -#define OP_VBegin 131 -#define OP_VUpdate 132 +#define OP_NotFound 12 +#define OP_IsNull 65 /* same as TK_ISNULL */ +#define OP_MoveLt 13 +#define OP_Rowid 14 +#define OP_CreateIndex 15 +#define OP_Push 17 +#define OP_Explain 18 +#define OP_Statement 19 +#define OP_Callback 20 +#define OP_MemLoad 21 +#define OP_DropIndex 22 +#define OP_Null 23 +#define OP_ToInt 141 /* same as TK_TO_INT */ +#define OP_Int64 24 +#define OP_LoadAnalysis 25 +#define OP_IdxInsert 26 +#define OP_VUpdate 27 +#define OP_Next 28 +#define OP_SetNumColumns 29 +#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/ +#define OP_Ge 72 /* same as TK_GE */ #define OP_BitNot 87 /* same as TK_BITNOT */ -#define OP_VCreate 133 -#define OP_MemMove 134 -#define OP_MemNull 135 -#define OP_Found 136 -#define OP_NullRow 137 +#define OP_MemInt 30 +#define OP_Dup 31 +#define OP_Rewind 32 +#define OP_Multiply 80 /* same as TK_STAR */ +#define OP_ToReal 142 /* same as TK_TO_REAL */ +#define OP_Gt 69 /* same as TK_GT */ +#define OP_Last 33 +#define OP_MustBeInt 34 +#define OP_Ne 67 /* same as TK_NE */ +#define OP_MoveGe 35 +#define OP_IncrVacuum 36 +#define OP_String 37 +#define OP_VFilter 38 +#define OP_ForceInt 39 +#define OP_Close 40 +#define OP_AggFinal 41 +#define OP_AbsValue 42 +#define OP_RowData 43 +#define OP_IdxRowid 44 +#define OP_BitOr 75 /* same as TK_BITOR */ +#define OP_NotNull 66 /* same as TK_NOTNULL */ +#define OP_MoveGt 45 +#define OP_Not 16 /* same as TK_NOT */ +#define OP_OpenPseudo 46 +#define OP_Halt 47 +#define OP_MemMove 48 +#define OP_NewRowid 49 +#define OP_Real 125 /* same as TK_FLOAT */ +#define OP_IdxLT 50 +#define OP_Distinct 51 +#define OP_MemMax 52 +#define OP_Function 53 +#define OP_IntegrityCk 54 +#define OP_Remainder 82 /* same as TK_REM */ +#define OP_HexBlob 126 /* same as TK_BLOB */ +#define OP_ShiftLeft 76 /* same as TK_LSHIFT */ +#define OP_FifoWrite 55 +#define OP_BitAnd 74 /* same as TK_BITAND */ +#define OP_Or 60 /* same as TK_OR */ +#define OP_NotExists 56 +#define OP_VDestroy 57 +#define OP_MemStore 58 +#define OP_IdxDelete 59 +#define OP_Vacuum 62 +#define OP_If 63 +#define OP_Destroy 64 +#define OP_AggStep 73 +#define OP_Clear 84 +#define OP_Insert 86 +#define OP_VBegin 89 +#define OP_IdxGE 90 +#define OP_OpenEphemeral 91 +#define OP_Divide 81 /* same as TK_SLASH */ +#define OP_String8 88 /* same as TK_STRING */ +#define OP_IfMemZero 92 +#define OP_Concat 83 /* same as TK_CONCAT */ +#define OP_VRowid 93 +#define OP_MakeRecord 94 +#define OP_SetCookie 95 +#define OP_StackDepth 96 +#define OP_Prev 97 +#define OP_ContextPush 98 +#define OP_DropTrigger 99 +#define OP_IdxGT 100 +#define OP_MemNull 101 +#define OP_IfMemNeg 102 +#define OP_And 61 /* same as TK_AND */ +#define OP_VColumn 103 +#define OP_Return 104 +#define OP_OpenWrite 105 +#define OP_Integer 106 +#define OP_Transaction 107 +#define OP_CollSeq 108 +#define OP_VRename 109 +#define OP_ToBlob 139 /* same as TK_TO_BLOB */ +#define OP_Sequence 110 +#define OP_ContextPop 111 +#define OP_ShiftRight 77 /* same as TK_RSHIFT */ +#define OP_VCreate 112 +#define OP_CreateTable 113 +#define OP_AddImm 114 +#define OP_ToText 138 /* same as TK_TO_TEXT */ +#define OP_DropTable 115 +#define OP_IsUnique 116 +#define OP_VOpen 117 +#define OP_Noop 118 +#define OP_RowKey 119 +#define OP_Expire 120 +#define OP_FifoRead 121 +#define OP_Delete 122 +#define OP_IfMemPos 123 +#define OP_Subtract 79 /* same as TK_MINUS */ +#define OP_MemIncr 124 +#define OP_Blob 127 +#define OP_MakeIdxRec 128 +#define OP_Goto 129 +#define OP_Negative 85 /* same as TK_UMINUS */ +#define OP_ParseSchema 130 +#define OP_Eq 68 /* same as TK_EQ */ +#define OP_VNext 131 +#define OP_Pop 132 +#define OP_Le 70 /* same as TK_LE */ +#define OP_TableLock 133 +#define OP_VerifyCookie 134 +#define OP_Column 135 +#define OP_OpenRead 136 +#define OP_ResetCount 137 /* Opcodes that are guaranteed to never push a value onto the stack ** contain a 1 their corresponding position of the following mask ** set. See the opcodeNoPush() function in vdbeaux.c */ -#define NOPUSH_MASK_0 0xeeb4 -#define NOPUSH_MASK_1 0xf96b -#define NOPUSH_MASK_2 0xfbb6 -#define NOPUSH_MASK_3 0xfe64 -#define NOPUSH_MASK_4 0xffff -#define NOPUSH_MASK_5 0xeef7 -#define NOPUSH_MASK_6 0xf7f6 -#define NOPUSH_MASK_7 0x0ecf -#define NOPUSH_MASK_8 0x7f3f +#define NOPUSH_MASK_0 0x3fbc +#define NOPUSH_MASK_1 0x3e5b +#define NOPUSH_MASK_2 0xe3df +#define NOPUSH_MASK_3 0xff9c +#define NOPUSH_MASK_4 0xfffe +#define NOPUSH_MASK_5 0x9ef7 +#define NOPUSH_MASK_6 0xbb5f +#define NOPUSH_MASK_7 0x1d7d +#define NOPUSH_MASK_8 0x7f7e #define NOPUSH_MASK_9 0x0000 /************** End of opcodes.h *********************************************/ @@ -5181,7 +5181,7 @@ SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _PAGER_H_ @@ -5656,7 +5656,7 @@ SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void); ** Source files should #include the sqliteInt.h file and let that file ** include this one indirectly. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -7389,7 +7389,7 @@ SQLITE_EXTERN void (*sqlite3_io_trace)(const char*,...); ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -8715,7 +8715,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -8949,7 +8949,7 @@ SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -9531,7 +9531,7 @@ SQLITE_PRIVATE void sqlite3MallocAllow(void){ ** This version of the memory allocation subsystem is used if ** and only if SQLITE_MEMORY_SIZE is defined. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -9561,11 +9561,16 @@ SQLITE_PRIVATE void sqlite3MallocAllow(void){ ** a header that is not returned to the user. ** ** A chunk is two or more blocks that is either checked out or -** free. The first block has format u.hdr. u.hdr.size is the +** free. The first block has format u.hdr. u.hdr.size4x is 4 times the ** size of the allocation in blocks if the allocation is free. -** If the allocation is checked out, u.hdr.size is the negative -** of the size. Similarly, u.hdr.prevSize is the size of the -** immediately previous allocation. +** The u.hdr.size4x&1 bit is true if the chunk is checked out and +** false if the chunk is on the freelist. The u.hdr.size4x&2 bit +** is true if the previous chunk is checked out and false if the +** previous chunk is free. The u.hdr.prevSize field is the size of +** the previous chunk in blocks if the previous chunk is on the +** freelist. If the previous chunk is checked out, then +** u.hdr.prevSize can be part of the data for that chunk and should +** not be read or written. ** ** We often identify a chunk by its index in mem.aPool[]. When ** this is done, the chunk index refers to the second block of @@ -9579,18 +9584,19 @@ SQLITE_PRIVATE void sqlite3MallocAllow(void){ ** for smaller chunks and mem.aiHash[] for larger chunks. ** ** The second block of a chunk is user data if the chunk is checked -** out. +** out. If a chunk is checked out, the user data may extend into +** the u.hdr.prevSize value of the following chunk. */ typedef struct Mem3Block Mem3Block; struct Mem3Block { union { struct { - int prevSize; /* Size of previous chunk in Mem3Block elements */ - int size; /* Size of current chunk in Mem3Block elements */ + u32 prevSize; /* Size of previous chunk in Mem3Block elements */ + u32 size4x; /* 4x the size of current chunk in Mem3Block elements */ } hdr; struct { - int next; /* Index in mem.aPool[] of next free chunk */ - int prev; /* Index in mem.aPool[] of previous free chunk */ + u32 next; /* Index in mem.aPool[] of next free chunk */ + u32 prev; /* Index in mem.aPool[] of previous free chunk */ } list; } u; }; @@ -9615,7 +9621,7 @@ static struct { /* ** The minimum amount of free space that we have seen. */ - int mnMaster; + u32 mnMaster; /* ** iMaster is the index of the master chunk. Most new allocations @@ -9623,16 +9629,16 @@ static struct { ** of the current master. iMaster is 0 if there is not master chunk. ** The master chunk is not in either the aiHash[] or aiSmall[]. */ - int iMaster; - int szMaster; + u32 iMaster; + u32 szMaster; /* ** Array of lists of free blocks according to the block size ** for smaller chunks, or a hash on the block size for larger ** chunks. */ - int aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */ - int aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */ + u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */ + u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */ /* ** Memory available for allocation @@ -9644,9 +9650,9 @@ static struct { ** Unlink the chunk at mem.aPool[i] from list it is currently ** on. *pRoot is the list that i is a member of. */ -static void memsys3UnlinkFromList(int i, int *pRoot){ - int next = mem.aPool[i].u.list.next; - int prev = mem.aPool[i].u.list.prev; +static void memsys3UnlinkFromList(u32 i, u32 *pRoot){ + u32 next = mem.aPool[i].u.list.next; + u32 prev = mem.aPool[i].u.list.prev; assert( sqlite3_mutex_held(mem.mutex) ); if( prev==0 ){ *pRoot = next; @@ -9664,10 +9670,12 @@ static void memsys3UnlinkFromList(int i, int *pRoot){ ** Unlink the chunk at index i from ** whatever list is currently a member of. */ -static void memsys3Unlink(int i){ - int size, hash; +static void memsys3Unlink(u32 i){ + u32 size, hash; assert( sqlite3_mutex_held(mem.mutex) ); - size = mem.aPool[i-1].u.hdr.size; + assert( (mem.aPool[i-1].u.hdr.size4x & 1)==0 ); + assert( i>=1 ); + size = mem.aPool[i-1].u.hdr.size4x/4; assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); assert( size>=2 ); if( size <= MX_SMALL ){ @@ -9682,7 +9690,7 @@ static void memsys3Unlink(int i){ ** Link the chunk at mem.aPool[i] so that is on the list rooted ** at *pRoot. */ -static void memsys3LinkIntoList(int i, int *pRoot){ +static void memsys3LinkIntoList(u32 i, u32 *pRoot){ assert( sqlite3_mutex_held(mem.mutex) ); mem.aPool[i].u.list.next = *pRoot; mem.aPool[i].u.list.prev = 0; @@ -9696,10 +9704,12 @@ static void memsys3LinkIntoList(int i, int *pRoot){ ** Link the chunk at index i into either the appropriate ** small chunk list, or into the large chunk hash table. */ -static void memsys3Link(int i){ - int size, hash; +static void memsys3Link(u32 i){ + u32 size, hash; assert( sqlite3_mutex_held(mem.mutex) ); - size = mem.aPool[i-1].u.hdr.size; + assert( i>=1 ); + assert( (mem.aPool[i-1].u.hdr.size4x & 1)==0 ); + size = mem.aPool[i-1].u.hdr.size4x/4; assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); assert( size>=2 ); if( size <= MX_SMALL ){ @@ -9719,8 +9729,9 @@ static void memsys3Link(int i){ static void memsys3Enter(void){ if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - mem.aPool[0].u.hdr.size = SQLITE_MEMORY_SIZE/8; + mem.aPool[0].u.hdr.size4x = SQLITE_MEMORY_SIZE/2 + 2; mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8; + mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.size4x = 1; mem.iMaster = 1; mem.szMaster = SQLITE_MEMORY_SIZE/8; mem.mnMaster = mem.szMaster; @@ -9792,8 +9803,8 @@ static void memsys3OutOfMemory(int nByte){ */ static int memsys3Size(void *p){ Mem3Block *pBlock = (Mem3Block*)p; - assert( pBlock[-1].u.hdr.size<0 ); - return (-1-pBlock[-1].u.hdr.size)*8; + assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); + return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; } /* @@ -9801,12 +9812,16 @@ static int memsys3Size(void *p){ ** size parameters for check-out and return a pointer to the ** user portion of the chunk. */ -static void *memsys3Checkout(int i, int nBlock){ +static void *memsys3Checkout(u32 i, int nBlock){ + u32 x; assert( sqlite3_mutex_held(mem.mutex) ); - assert( mem.aPool[i-1].u.hdr.size==nBlock ); + assert( i>=1 ); + assert( mem.aPool[i-1].u.hdr.size4x/4==nBlock ); assert( mem.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); - mem.aPool[i-1].u.hdr.size = -nBlock; - mem.aPool[i+nBlock-1].u.hdr.prevSize = -nBlock; + x = mem.aPool[i-1].u.hdr.size4x; + mem.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2); + mem.aPool[i+nBlock-1].u.hdr.prevSize = nBlock; + mem.aPool[i+nBlock-1].u.hdr.size4x |= 2; return &mem.aPool[i]; } @@ -9827,14 +9842,16 @@ static void *memsys3FromMaster(int nBlock){ return p; }else{ /* Split the master block. Return the tail. */ - int newi; + u32 newi, x; newi = mem.iMaster + mem.szMaster - nBlock; assert( newi > mem.iMaster+1 ); - mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = -nBlock; - mem.aPool[newi-1].u.hdr.size = -nBlock; + mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = nBlock; + mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x |= 2; + mem.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; mem.szMaster -= nBlock; mem.aPool[newi-1].u.hdr.prevSize = mem.szMaster; - mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster; + x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; + mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; if( mem.szMaster < mem.mnMaster ){ mem.mnMaster = mem.szMaster; } @@ -9858,27 +9875,30 @@ static void *memsys3FromMaster(int nBlock){ ** chunk before invoking this routine, then must unlink the (possibly ** changed) master chunk once this routine has finished. */ -static void memsys3Merge(int *pRoot){ - int iNext, prev, size, i; +static void memsys3Merge(u32 *pRoot){ + u32 iNext, prev, size, i, x; assert( sqlite3_mutex_held(mem.mutex) ); for(i=*pRoot; i>0; i=iNext){ iNext = mem.aPool[i].u.list.next; - size = mem.aPool[i-1].u.hdr.size; - assert( size>0 ); - if( mem.aPool[i-1].u.hdr.prevSize>0 ){ + size = mem.aPool[i-1].u.hdr.size4x; + assert( (size&1)==0 ); + if( (size&2)==0 ){ memsys3UnlinkFromList(i, pRoot); + assert( i > mem.aPool[i-1].u.hdr.prevSize ); prev = i - mem.aPool[i-1].u.hdr.prevSize; - assert( prev>=0 ); if( prev==iNext ){ iNext = mem.aPool[prev].u.list.next; } memsys3Unlink(prev); - size = i + size - prev; - mem.aPool[prev-1].u.hdr.size = size; + size = i + size/4 - prev; + x = mem.aPool[prev-1].u.hdr.size4x & 2; + mem.aPool[prev-1].u.hdr.size4x = size*4 | x; mem.aPool[prev+size-1].u.hdr.prevSize = size; memsys3Link(prev); i = prev; + }else{ + size /= 4; } if( size>mem.szMaster ){ mem.iMaster = i; @@ -9892,16 +9912,16 @@ static void memsys3Merge(int *pRoot){ ** Return NULL if unable. */ static void *memsys3Malloc(int nByte){ - int i; + u32 i; int nBlock; int toFree; assert( sqlite3_mutex_held(mem.mutex) ); assert( sizeof(Mem3Block)==8 ); - if( nByte<=0 ){ + if( nByte<=12 ){ nBlock = 2; }else{ - nBlock = (nByte + 15)/8; + nBlock = (nByte + 11)/8; } assert( nBlock >= 2 ); @@ -9919,7 +9939,7 @@ static void *memsys3Malloc(int nByte){ }else{ int hash = nBlock % N_HASH; for(i=mem.aiHash[hash]; i>0; i=mem.aPool[i].u.list.next){ - if( mem.aPool[i-1].u.hdr.size==nBlock ){ + if( mem.aPool[i-1].u.hdr.size4x/4==nBlock ){ memsys3UnlinkFromList(i, &mem.aiHash[hash]); return memsys3Checkout(i, nBlock); } @@ -9973,31 +9993,34 @@ static void *memsys3Malloc(int nByte){ void memsys3Free(void *pOld){ Mem3Block *p = (Mem3Block*)pOld; int i; - int size; + u32 size, x; assert( sqlite3_mutex_held(mem.mutex) ); assert( p>mem.aPool && p<&mem.aPool[SQLITE_MEMORY_SIZE/8] ); i = p - mem.aPool; - size = -mem.aPool[i-1].u.hdr.size; - assert( size>=2 ); - assert( mem.aPool[i+size-1].u.hdr.prevSize==-size ); - mem.aPool[i-1].u.hdr.size = size; + assert( (mem.aPool[i-1].u.hdr.size4x&1)==1 ); + size = mem.aPool[i-1].u.hdr.size4x/4; + assert( i+size<=SQLITE_MEMORY_SIZE/8+1 ); + mem.aPool[i-1].u.hdr.size4x &= ~1; mem.aPool[i+size-1].u.hdr.prevSize = size; + mem.aPool[i+size-1].u.hdr.size4x &= ~2; memsys3Link(i); /* Try to expand the master using the newly freed chunk */ if( mem.iMaster ){ - while( mem.aPool[mem.iMaster-1].u.hdr.prevSize>0 ){ + while( (mem.aPool[mem.iMaster-1].u.hdr.size4x&2)==0 ){ size = mem.aPool[mem.iMaster-1].u.hdr.prevSize; mem.iMaster -= size; mem.szMaster += size; memsys3Unlink(mem.iMaster); - mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster; + x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; + mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; } - while( mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size>0 ){ + x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; + while( (mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x&1)==0 ){ memsys3Unlink(mem.iMaster+mem.szMaster); - mem.szMaster += mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size; - mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster; + mem.szMaster += mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x/4; + mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; } } @@ -10068,7 +10091,8 @@ SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){ SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){ #ifdef SQLITE_DEBUG FILE *out; - int i, j, size; + int i, j; + u32 size; if( zFilename==0 || zFilename[0]==0 ){ out = stdout; }else{ @@ -10081,23 +10105,27 @@ SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){ } memsys3Enter(); fprintf(out, "CHUNKS:\n"); - for(i=1; i<=SQLITE_MEMORY_SIZE/8; i+=size){ - size = mem.aPool[i-1].u.hdr.size; - if( size>=-1 && size<=1 ){ + for(i=1; i<=SQLITE_MEMORY_SIZE/8; i+=size/4){ + size = mem.aPool[i-1].u.hdr.size4x; + if( size/4<=1 ){ fprintf(out, "%p size error\n", &mem.aPool[i]); assert( 0 ); break; } - if( mem.aPool[i+(size<0?-size:size)-1].u.hdr.prevSize!=size ){ + if( (size&1)==0 && mem.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){ fprintf(out, "%p tail size does not match\n", &mem.aPool[i]); assert( 0 ); break; } - if( size<0 ){ - size = -size; - fprintf(out, "%p %6d bytes checked out\n", &mem.aPool[i], size*8-8); + if( ((mem.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){ + fprintf(out, "%p tail checkout bit is incorrect\n", &mem.aPool[i]); + assert( 0 ); + break; + } + if( size&1 ){ + fprintf(out, "%p %6d bytes checked out\n", &mem.aPool[i], (size/4)*8-8); }else{ - fprintf(out, "%p %6d bytes free%s\n", &mem.aPool[i], size*8-8, + fprintf(out, "%p %6d bytes free%s\n", &mem.aPool[i], (size/4)*8-8, i==mem.iMaster ? " **master**" : ""); } } @@ -10105,7 +10133,8 @@ SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){ if( mem.aiSmall[i]==0 ) continue; fprintf(out, "small(%2d):", i); for(j = mem.aiSmall[i]; j>0; j=mem.aPool[j].u.list.next){ - fprintf(out, " %p(%d)", &mem.aPool[j], mem.aPool[j-1].u.hdr.size*8-8); + fprintf(out, " %p(%d)", &mem.aPool[j], + (mem.aPool[j-1].u.hdr.size4x/4)*8-8); } fprintf(out, "\n"); } @@ -10113,7 +10142,8 @@ SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){ if( mem.aiHash[i]==0 ) continue; fprintf(out, "hash(%2d):", i); for(j = mem.aiHash[i]; j>0; j=mem.aPool[j].u.list.next){ - fprintf(out, " %p(%d)", &mem.aPool[j], mem.aPool[j-1].u.hdr.size*8-8); + fprintf(out, " %p(%d)", &mem.aPool[j], + (mem.aPool[j-1].u.hdr.size4x/4)*8-8); } fprintf(out, "\n"); } @@ -10155,7 +10185,7 @@ SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){ ** implementation is suitable for testing. ** debugging purposes ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifdef SQLITE_MUTEX_NOOP_DEBUG @@ -10275,7 +10305,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ************************************************************************* ** This file contains the C functions that implement mutexes for OS/2 ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -10366,8 +10396,8 @@ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int iType){ DosEnterCritSec(); lock++; if( lock == 1 ) { - DosExitCritSec(); int i; + DosExitCritSec(); for(i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++) { staticMutexes[i].mutexName = (PSZ)malloc(mutex_name_len + 1); sqlite3_snprintf(mutex_name_len + 1, /* one more for the number */ @@ -10513,7 +10543,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -10813,7 +10843,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ************************************************************************* ** This file contains the C functions that implement mutexes for win32 ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -11035,7 +11065,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ** Memory allocation functions used throughout sqlite. ** ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -12183,7 +12213,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -12285,7 +12315,7 @@ SQLITE_PRIVATE void sqlite3Randomness(int N, void *pBuf){ ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ ** ** Notes on UTF-8: ** @@ -13264,7 +13294,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(){ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -13969,7 +13999,7 @@ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){ ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* Turn bulk memory into a hash table object by initializing the @@ -14379,70 +14409,70 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, voi #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ static const char *const azName[] = { "?", - /* 1 */ "MemLoad", - /* 2 */ "VNext", - /* 3 */ "Column", - /* 4 */ "SetCookie", - /* 5 */ "IfMemPos", - /* 6 */ "Sequence", - /* 7 */ "MoveGt", - /* 8 */ "RowKey", - /* 9 */ "OpenWrite", - /* 10 */ "If", - /* 11 */ "Pop", - /* 12 */ "VRowid", - /* 13 */ "CollSeq", - /* 14 */ "OpenRead", - /* 15 */ "Expire", + /* 1 */ "ReadCookie", + /* 2 */ "AutoCommit", + /* 3 */ "Found", + /* 4 */ "NullRow", + /* 5 */ "MoveLe", + /* 6 */ "Variable", + /* 7 */ "Pull", + /* 8 */ "RealAffinity", + /* 9 */ "Sort", + /* 10 */ "IfNot", + /* 11 */ "Gosub", + /* 12 */ "NotFound", + /* 13 */ "MoveLt", + /* 14 */ "Rowid", + /* 15 */ "CreateIndex", /* 16 */ "Not", - /* 17 */ "AutoCommit", - /* 18 */ "IntegrityCk", - /* 19 */ "Sort", - /* 20 */ "Function", - /* 21 */ "Noop", - /* 22 */ "Return", - /* 23 */ "NewRowid", - /* 24 */ "IfMemNeg", - /* 25 */ "Variable", - /* 26 */ "String", - /* 27 */ "RealAffinity", - /* 28 */ "VRename", - /* 29 */ "ParseSchema", - /* 30 */ "VOpen", - /* 31 */ "Close", - /* 32 */ "CreateIndex", - /* 33 */ "IsUnique", - /* 34 */ "NotFound", - /* 35 */ "Int64", - /* 36 */ "MustBeInt", - /* 37 */ "Halt", - /* 38 */ "Rowid", - /* 39 */ "IdxLT", - /* 40 */ "AddImm", - /* 41 */ "Statement", - /* 42 */ "RowData", - /* 43 */ "MemMax", - /* 44 */ "Push", - /* 45 */ "NotExists", - /* 46 */ "MemIncr", - /* 47 */ "Gosub", - /* 48 */ "Integer", - /* 49 */ "MemInt", - /* 50 */ "Prev", - /* 51 */ "VColumn", - /* 52 */ "CreateTable", - /* 53 */ "Last", - /* 54 */ "IncrVacuum", - /* 55 */ "IdxRowid", - /* 56 */ "MakeIdxRec", - /* 57 */ "ResetCount", - /* 58 */ "FifoWrite", - /* 59 */ "Callback", + /* 17 */ "Push", + /* 18 */ "Explain", + /* 19 */ "Statement", + /* 20 */ "Callback", + /* 21 */ "MemLoad", + /* 22 */ "DropIndex", + /* 23 */ "Null", + /* 24 */ "Int64", + /* 25 */ "LoadAnalysis", + /* 26 */ "IdxInsert", + /* 27 */ "VUpdate", + /* 28 */ "Next", + /* 29 */ "SetNumColumns", + /* 30 */ "MemInt", + /* 31 */ "Dup", + /* 32 */ "Rewind", + /* 33 */ "Last", + /* 34 */ "MustBeInt", + /* 35 */ "MoveGe", + /* 36 */ "IncrVacuum", + /* 37 */ "String", + /* 38 */ "VFilter", + /* 39 */ "ForceInt", + /* 40 */ "Close", + /* 41 */ "AggFinal", + /* 42 */ "AbsValue", + /* 43 */ "RowData", + /* 44 */ "IdxRowid", + /* 45 */ "MoveGt", + /* 46 */ "OpenPseudo", + /* 47 */ "Halt", + /* 48 */ "MemMove", + /* 49 */ "NewRowid", + /* 50 */ "IdxLT", + /* 51 */ "Distinct", + /* 52 */ "MemMax", + /* 53 */ "Function", + /* 54 */ "IntegrityCk", + /* 55 */ "FifoWrite", + /* 56 */ "NotExists", + /* 57 */ "VDestroy", + /* 58 */ "MemStore", + /* 59 */ "IdxDelete", /* 60 */ "Or", /* 61 */ "And", - /* 62 */ "ContextPush", - /* 63 */ "DropTrigger", - /* 64 */ "DropIndex", + /* 62 */ "Vacuum", + /* 63 */ "If", + /* 64 */ "Destroy", /* 65 */ "IsNull", /* 66 */ "NotNull", /* 67 */ "Ne", @@ -14451,7 +14481,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 70 */ "Le", /* 71 */ "Lt", /* 72 */ "Ge", - /* 73 */ "IdxGE", + /* 73 */ "AggStep", /* 74 */ "BitAnd", /* 75 */ "BitOr", /* 76 */ "ShiftLeft", @@ -14462,60 +14492,60 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 81 */ "Divide", /* 82 */ "Remainder", /* 83 */ "Concat", - /* 84 */ "IdxDelete", + /* 84 */ "Clear", /* 85 */ "Negative", - /* 86 */ "Vacuum", + /* 86 */ "Insert", /* 87 */ "BitNot", /* 88 */ "String8", - /* 89 */ "MoveLe", - /* 90 */ "IfNot", - /* 91 */ "DropTable", - /* 92 */ "MakeRecord", - /* 93 */ "Delete", - /* 94 */ "StackDepth", - /* 95 */ "AggFinal", - /* 96 */ "Dup", - /* 97 */ "Goto", - /* 98 */ "TableLock", - /* 99 */ "FifoRead", - /* 100 */ "Clear", - /* 101 */ "IdxGT", - /* 102 */ "MoveLt", - /* 103 */ "VerifyCookie", - /* 104 */ "AggStep", - /* 105 */ "Pull", - /* 106 */ "SetNumColumns", - /* 107 */ "AbsValue", - /* 108 */ "Transaction", - /* 109 */ "VFilter", - /* 110 */ "VDestroy", + /* 89 */ "VBegin", + /* 90 */ "IdxGE", + /* 91 */ "OpenEphemeral", + /* 92 */ "IfMemZero", + /* 93 */ "VRowid", + /* 94 */ "MakeRecord", + /* 95 */ "SetCookie", + /* 96 */ "StackDepth", + /* 97 */ "Prev", + /* 98 */ "ContextPush", + /* 99 */ "DropTrigger", + /* 100 */ "IdxGT", + /* 101 */ "MemNull", + /* 102 */ "IfMemNeg", + /* 103 */ "VColumn", + /* 104 */ "Return", + /* 105 */ "OpenWrite", + /* 106 */ "Integer", + /* 107 */ "Transaction", + /* 108 */ "CollSeq", + /* 109 */ "VRename", + /* 110 */ "Sequence", /* 111 */ "ContextPop", - /* 112 */ "Next", - /* 113 */ "IdxInsert", - /* 114 */ "Distinct", - /* 115 */ "Insert", - /* 116 */ "Destroy", - /* 117 */ "ReadCookie", - /* 118 */ "ForceInt", - /* 119 */ "LoadAnalysis", - /* 120 */ "Explain", - /* 121 */ "IfMemZero", - /* 122 */ "OpenPseudo", - /* 123 */ "OpenEphemeral", - /* 124 */ "Null", + /* 112 */ "VCreate", + /* 113 */ "CreateTable", + /* 114 */ "AddImm", + /* 115 */ "DropTable", + /* 116 */ "IsUnique", + /* 117 */ "VOpen", + /* 118 */ "Noop", + /* 119 */ "RowKey", + /* 120 */ "Expire", + /* 121 */ "FifoRead", + /* 122 */ "Delete", + /* 123 */ "IfMemPos", + /* 124 */ "MemIncr", /* 125 */ "Real", /* 126 */ "HexBlob", /* 127 */ "Blob", - /* 128 */ "MemStore", - /* 129 */ "Rewind", - /* 130 */ "MoveGe", - /* 131 */ "VBegin", - /* 132 */ "VUpdate", - /* 133 */ "VCreate", - /* 134 */ "MemMove", - /* 135 */ "MemNull", - /* 136 */ "Found", - /* 137 */ "NullRow", + /* 128 */ "MakeIdxRec", + /* 129 */ "Goto", + /* 130 */ "ParseSchema", + /* 131 */ "VNext", + /* 132 */ "Pop", + /* 133 */ "TableLock", + /* 134 */ "VerifyCookie", + /* 135 */ "Column", + /* 136 */ "OpenRead", + /* 137 */ "ResetCount", /* 138 */ "ToText", /* 139 */ "ToBlob", /* 140 */ "ToNumeric", @@ -15407,7 +15437,8 @@ static int os2GetTempname( sqlite3_vfs *pVfs, int nBuf, char *zBuf ){ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; - PSZ zTempPath = ""; + char zTempPathBuf[3]; + PSZ zTempPath = (PSZ)&zTempPathBuf; if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){ if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){ if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){ @@ -15450,21 +15481,19 @@ static int os2FullPathname( char *zFull /* Output buffer */ ){ if( strchr(zRelative, ':') ){ - sqlite3SetString( &zFull, zRelative, (char*)0 ); + sqlite3_snprintf( nFull, zFull, "%s", zRelative ); }else{ ULONG ulDriveNum = 0; ULONG ulDriveMap = 0; ULONG cbzBufLen = SQLITE_TEMPNAME_SIZE; - char zDrive[2]; char *zBuff = (char*)malloc( cbzBufLen ); if( zBuff == 0 ){ return SQLITE_NOMEM; } DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ); if( DosQueryCurrentDir( ulDriveNum, (PBYTE)zBuff, &cbzBufLen ) == NO_ERROR ){ - sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) ); - sqlite3SetString( &zFull, zDrive, ":\\", zBuff, - "\\", zRelative, (char*)0 ); + sqlite3_snprintf( nFull, zFull, "%c:\\%s\\%s", + (char)('A' + ulDriveNum - 1), zBuff, zRelative); } free( zBuff ); } @@ -20271,7 +20300,7 @@ SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void){ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef SQLITE_OMIT_DISKIO @@ -25386,7 +25415,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager *pPager){ ** ************************************************************************* ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too @@ -25406,7 +25435,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager *pPager){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -25787,6 +25816,7 @@ struct BtShared { int nRef; /* Number of references to this structure */ BtShared *pNext; /* Next on a list of sharable BtShared structs */ BtLock *pLock; /* List of locks held on this shared-btree struct */ + Btree *pExclusive; /* Btree with an EXCLUSIVE lock on the whole db */ #endif }; @@ -26351,7 +26381,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -26444,6 +26474,13 @@ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ return SQLITE_OK; } + /* If some other connection is holding an exclusive lock, the + ** requested lock may not be obtained. + */ + if( pBt->pExclusive && pBt->pExclusive!=p ){ + return SQLITE_LOCKED; + } + /* This (along with lockTable()) is where the ReadUncommitted flag is ** dealt with. If the caller is querying for a read-lock and the flag is ** set, it is unconditionally granted - even if there are write-locks @@ -26553,13 +26590,15 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ ** procedure) held by Btree handle p. */ static void unlockAllTables(Btree *p){ - BtLock **ppIter = &p->pBt->pLock; + BtShared *pBt = p->pBt; + BtLock **ppIter = &pBt->pLock; assert( sqlite3BtreeHoldsMutex(p) ); assert( p->sharable || 0==*ppIter ); while( *ppIter ){ BtLock *pLock = *ppIter; + assert( pBt->pExclusive==0 || pBt->pExclusive==pLock->pBtree ); if( pLock->pBtree==p ){ *ppIter = pLock->pNext; sqlite3_free(pLock); @@ -26567,6 +26606,10 @@ static void unlockAllTables(Btree *p){ ppIter = &pLock->pNext; } } + + if( pBt->pExclusive==p ){ + pBt->pExclusive = 0; + } } #endif /* SQLITE_OMIT_SHARED_CACHE */ @@ -28191,6 +28234,18 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ goto trans_begun; } +#ifndef SQLITE_OMIT_SHARED_CACHE + if( wrflag>1 ){ + BtLock *pIter; + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p ){ + rc = SQLITE_BUSY; + goto trans_begun; + } + } + } +#endif + do { if( pBt->pPage1==0 ){ rc = lockBtree(pBt); @@ -28223,6 +28278,12 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ if( p->inTrans>pBt->inTransaction ){ pBt->inTransaction = p->inTrans; } +#ifndef SQLITE_OMIT_SHARED_CACHE + if( wrflag>1 ){ + assert( !pBt->pExclusive ); + pBt->pExclusive = p; + } +#endif } @@ -37774,7 +37835,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -38488,8 +38549,6 @@ case OP_String8: { /* same as TK_STRING */ assert( pOp->p3!=0 ); pOp->opcode = OP_String; pOp->p1 = strlen(pOp->p3); - assert( SQLITE_MAX_SQL_LENGTH <= SQLITE_MAX_LENGTH ); - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ @@ -38505,11 +38564,16 @@ case OP_String8: { /* same as TK_STRING */ pOp->p3type = P3_DYNAMIC; pOp->p3 = pTos->z; pOp->p1 = pTos->n; - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ + if( pOp->p1>SQLITE_MAX_LENGTH ){ + goto too_big; + } break; } #endif - /* Otherwise fall through to the next case, OP_String */ + if( pOp->p1>SQLITE_MAX_LENGTH ){ + goto too_big; + } + /* Fall through to the next case, OP_String */ } /* Opcode: String P1 * P3 @@ -38517,7 +38581,6 @@ case OP_String8: { /* same as TK_STRING */ ** The string value P3 of length P1 (bytes) is pushed onto the stack. */ case OP_String: { - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ pTos++; assert( pOp->p3!=0 ); pTos->flags = MEM_Str|MEM_Static|MEM_Term; @@ -38551,8 +38614,9 @@ case OP_Null: { case OP_HexBlob: { /* same as TK_BLOB */ pOp->opcode = OP_Blob; pOp->p1 = strlen(pOp->p3)/2; - assert( SQLITE_MAX_SQL_LENGTH <= SQLITE_MAX_LENGTH ); - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); + if( pOp->p1>SQLITE_MAX_LENGTH ){ + goto too_big; + } if( pOp->p1 ){ char *zBlob = sqlite3HexToBlob(db, pOp->p3); if( !zBlob ) goto no_mem; @@ -38583,7 +38647,7 @@ case OP_HexBlob: { /* same as TK_BLOB */ */ case OP_Blob: { pTos++; - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ + assert( pOp->p1 <= SQLITE_MAX_LENGTH ); sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0); pTos->enc = encoding; break; @@ -43045,7 +43109,7 @@ abort_due_to_interrupt: ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -43384,7 +43448,7 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ ** ************************************************************************* ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE @@ -43626,7 +43690,7 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -46443,7 +46507,7 @@ SQLITE_PRIVATE int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -47072,7 +47136,7 @@ exit_begin_add_column: ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef SQLITE_OMIT_ANALYZE @@ -47494,7 +47558,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef SQLITE_OMIT_ATTACH @@ -47669,7 +47733,9 @@ static void attachFunc( */ if( rc==SQLITE_OK ){ sqlite3SafetyOn(db); + sqlite3BtreeEnterAll(db); rc = sqlite3Init(db, &zErrDyn); + sqlite3BtreeLeaveAll(db); sqlite3SafetyOff(db); } if( rc ){ @@ -48020,7 +48086,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -48264,7 +48330,7 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ ** COMMIT ** ROLLBACK ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -48643,17 +48709,22 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char */ SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ int i, j; - assert( iDb>=0 && iDbnDb ); + + if( iDb==0 ){ + sqlite3BtreeEnterAll(db); + } for(i=iDb; inDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ + assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); sqlite3SchemaFree(pDb->pSchema); } if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; + sqlite3BtreeLeaveAll(db); /* If one or more of the auxiliary database files has been closed, ** then remove them from the auxiliary database list. We take the @@ -51690,7 +51761,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -52069,7 +52140,7 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -52546,7 +52617,7 @@ SQLITE_PRIVATE void sqlite3GenerateIndexKey( ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -54115,7 +54186,7 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -55745,7 +55816,7 @@ static int xferOptimization( ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -55900,7 +55971,7 @@ exec_out: ** as extensions by SQLite should #include this file instead of ** sqlite3.h. ** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ @@ -56746,7 +56817,7 @@ SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* Ignore this whole file if pragmas are disabled @@ -57548,7 +57619,13 @@ SQLITE_PRIVATE void sqlite3Pragma( #endif #ifndef SQLITE_OMIT_INTEGRITY_CHECK - if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){ + /* Pragma "quick_check" is an experimental reduced version of + ** integrity_check designed to detect most database corruption + ** without most of the overhead of a full integrity-check. + */ + if( sqlite3StrICmp(zLeft, "integrity_check")==0 + || sqlite3StrICmp(zLeft, "quick_check")==0 + ){ int i, j, addr, mxErr; /* Code that appears at the end of the integrity check. If no error @@ -57563,6 +57640,8 @@ SQLITE_PRIVATE void sqlite3Pragma( { OP_Callback, 1, 0, 0}, }; + int isQuick = (zLeft[0]=='q'); + /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); @@ -57617,7 +57696,7 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Make sure all the indices are constructed correctly. */ - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; @@ -57943,7 +58022,7 @@ pragma_out: ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -58086,6 +58165,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite3_mutex_held(db->mutex) ); + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being @@ -58458,7 +58538,9 @@ SQLITE_PRIVATE int sqlite3Prepare( sParse.db = db; if( nBytes>=0 && zSql[nBytes]!=0 ){ char *zSqlCopy; - if( nBytes>SQLITE_MAX_SQL_LENGTH ){ + if( SQLITE_MAX_SQL_LENGTH>0 && nBytes>SQLITE_MAX_SQL_LENGTH ){ + sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); + sqlite3SafetyOff(db); return SQLITE_TOOBIG; } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); @@ -58529,7 +58611,6 @@ SQLITE_PRIVATE int sqlite3Prepare( } rc = sqlite3ApiExit(db, rc); - /* sqlite3ReleaseThreadData(); */ assert( (rc&db->errMask)==rc ); return rc; } @@ -58706,7 +58787,7 @@ SQLITE_API int sqlite3_prepare16_v2( ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ @@ -63423,7 +63504,7 @@ SQLITE_PRIVATE int sqlite3CodeRowTrigger( ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -64066,7 +64147,7 @@ static void updateVirtualTable( ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) @@ -64327,7 +64408,7 @@ end_of_vacuum: ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -65131,7 +65212,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -68080,443 +68161,416 @@ typedef union { ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 299, 901, 124, 587, 416, 174, 2, 425, 61, 61, - /* 10 */ 61, 61, 297, 63, 63, 63, 63, 64, 64, 65, - /* 20 */ 65, 65, 66, 212, 454, 214, 432, 438, 68, 63, - /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 212, - /* 40 */ 398, 395, 403, 458, 60, 59, 304, 442, 443, 439, - /* 50 */ 439, 62, 62, 61, 61, 61, 61, 265, 63, 63, - /* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 212, 299, - /* 70 */ 500, 501, 425, 496, 210, 82, 67, 427, 69, 156, - /* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, - /* 90 */ 212, 67, 469, 69, 156, 432, 438, 573, 266, 58, - /* 100 */ 64, 64, 65, 65, 65, 66, 212, 404, 405, 429, - /* 110 */ 429, 429, 299, 60, 59, 304, 442, 443, 439, 439, - /* 120 */ 62, 62, 61, 61, 61, 61, 324, 63, 63, 63, - /* 130 */ 63, 64, 64, 65, 65, 65, 66, 212, 432, 438, - /* 140 */ 94, 65, 65, 65, 66, 212, 403, 212, 421, 34, - /* 150 */ 56, 305, 449, 450, 417, 481, 60, 59, 304, 442, - /* 160 */ 443, 439, 439, 62, 62, 61, 61, 61, 61, 495, - /* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, - /* 180 */ 212, 299, 259, 524, 203, 571, 113, 415, 522, 458, - /* 190 */ 338, 324, 414, 20, 241, 347, 297, 403, 471, 531, - /* 200 */ 292, 454, 214, 570, 569, 472, 530, 432, 438, 151, - /* 210 */ 152, 404, 405, 421, 41, 213, 153, 533, 422, 496, - /* 220 */ 263, 568, 261, 427, 299, 60, 59, 304, 442, 443, - /* 230 */ 439, 439, 62, 62, 61, 61, 61, 61, 324, 63, - /* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 212, - /* 250 */ 432, 438, 454, 340, 217, 429, 429, 429, 219, 550, - /* 260 */ 421, 41, 404, 405, 490, 567, 213, 299, 60, 59, - /* 270 */ 304, 442, 443, 439, 439, 62, 62, 61, 61, 61, - /* 280 */ 61, 652, 63, 63, 63, 63, 64, 64, 65, 65, - /* 290 */ 65, 66, 212, 432, 438, 103, 652, 549, 524, 519, - /* 300 */ 652, 216, 652, 67, 231, 69, 156, 534, 20, 66, - /* 310 */ 212, 60, 59, 304, 442, 443, 439, 439, 62, 62, - /* 320 */ 61, 61, 61, 61, 265, 63, 63, 63, 63, 64, - /* 330 */ 64, 65, 65, 65, 66, 212, 654, 324, 288, 77, - /* 340 */ 299, 456, 523, 170, 491, 155, 232, 380, 271, 270, - /* 350 */ 327, 654, 445, 445, 485, 654, 485, 654, 210, 421, - /* 360 */ 27, 456, 330, 170, 652, 391, 432, 438, 497, 425, - /* 370 */ 652, 652, 652, 652, 652, 652, 652, 252, 654, 422, - /* 380 */ 581, 291, 80, 652, 60, 59, 304, 442, 443, 439, - /* 390 */ 439, 62, 62, 61, 61, 61, 61, 210, 63, 63, - /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 212, 299, - /* 410 */ 379, 585, 892, 494, 892, 306, 393, 368, 324, 654, - /* 420 */ 21, 324, 307, 324, 425, 654, 654, 654, 654, 654, - /* 430 */ 654, 654, 571, 654, 425, 432, 438, 532, 654, 654, - /* 440 */ 421, 49, 485, 421, 35, 421, 49, 329, 449, 450, - /* 450 */ 570, 582, 348, 60, 59, 304, 442, 443, 439, 439, - /* 460 */ 62, 62, 61, 61, 61, 61, 655, 63, 63, 63, - /* 470 */ 63, 64, 64, 65, 65, 65, 66, 212, 299, 420, - /* 480 */ 198, 655, 509, 419, 324, 655, 315, 655, 653, 425, - /* 490 */ 223, 316, 653, 525, 653, 238, 166, 118, 245, 350, - /* 500 */ 250, 351, 178, 314, 432, 438, 421, 34, 655, 254, - /* 510 */ 239, 213, 389, 213, 422, 653, 588, 398, 395, 406, - /* 520 */ 407, 408, 60, 59, 304, 442, 443, 439, 439, 62, - /* 530 */ 62, 61, 61, 61, 61, 335, 63, 63, 63, 63, - /* 540 */ 64, 64, 65, 65, 65, 66, 212, 299, 342, 655, - /* 550 */ 307, 257, 463, 547, 501, 655, 655, 655, 655, 655, - /* 560 */ 655, 655, 653, 655, 464, 653, 653, 653, 655, 655, - /* 570 */ 653, 161, 498, 432, 438, 653, 653, 465, 1, 502, - /* 580 */ 544, 418, 403, 585, 891, 176, 891, 343, 174, 503, - /* 590 */ 425, 60, 59, 304, 442, 443, 439, 439, 62, 62, - /* 600 */ 61, 61, 61, 61, 240, 63, 63, 63, 63, 64, - /* 610 */ 64, 65, 65, 65, 66, 212, 299, 381, 223, 422, - /* 620 */ 9, 93, 377, 582, 403, 118, 245, 350, 250, 351, - /* 630 */ 178, 177, 162, 325, 403, 183, 345, 254, 352, 355, - /* 640 */ 356, 227, 432, 438, 446, 320, 399, 404, 405, 357, - /* 650 */ 459, 209, 540, 367, 540, 425, 546, 302, 202, 299, - /* 660 */ 60, 59, 304, 442, 443, 439, 439, 62, 62, 61, - /* 670 */ 61, 61, 61, 402, 63, 63, 63, 63, 64, 64, - /* 680 */ 65, 65, 65, 66, 212, 432, 438, 225, 524, 404, - /* 690 */ 405, 489, 422, 397, 18, 824, 2, 578, 20, 404, - /* 700 */ 405, 194, 299, 60, 59, 304, 442, 443, 439, 439, - /* 710 */ 62, 62, 61, 61, 61, 61, 386, 63, 63, 63, - /* 720 */ 63, 64, 64, 65, 65, 65, 66, 212, 432, 438, - /* 730 */ 327, 370, 445, 445, 481, 422, 327, 373, 445, 445, - /* 740 */ 275, 519, 519, 8, 394, 299, 60, 70, 304, 442, - /* 750 */ 443, 439, 439, 62, 62, 61, 61, 61, 61, 378, - /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, - /* 770 */ 212, 432, 438, 243, 211, 167, 310, 224, 278, 196, - /* 780 */ 276, 55, 374, 519, 180, 181, 182, 519, 299, 119, - /* 790 */ 59, 304, 442, 443, 439, 439, 62, 62, 61, 61, - /* 800 */ 61, 61, 646, 63, 63, 63, 63, 64, 64, 65, - /* 810 */ 65, 65, 66, 212, 432, 438, 403, 646, 311, 253, - /* 820 */ 253, 646, 312, 646, 327, 5, 445, 445, 481, 542, - /* 830 */ 154, 519, 474, 541, 304, 442, 443, 439, 439, 62, - /* 840 */ 62, 61, 61, 61, 61, 369, 63, 63, 63, 63, - /* 850 */ 64, 64, 65, 65, 65, 66, 212, 72, 331, 277, - /* 860 */ 4, 253, 377, 428, 303, 253, 313, 487, 622, 173, - /* 870 */ 162, 455, 328, 72, 331, 265, 4, 265, 84, 158, - /* 880 */ 303, 404, 405, 265, 67, 646, 69, 156, 328, 333, - /* 890 */ 360, 646, 646, 646, 646, 646, 646, 646, 183, 458, - /* 900 */ 185, 352, 355, 356, 646, 333, 388, 477, 188, 253, - /* 910 */ 433, 434, 357, 422, 463, 458, 557, 179, 559, 75, - /* 920 */ 74, 336, 403, 147, 560, 210, 464, 226, 73, 322, - /* 930 */ 323, 436, 437, 427, 422, 75, 74, 488, 387, 465, - /* 940 */ 475, 334, 422, 512, 73, 322, 323, 72, 331, 427, - /* 950 */ 4, 210, 467, 324, 303, 318, 123, 19, 480, 144, - /* 960 */ 435, 157, 328, 513, 484, 429, 429, 429, 430, 431, - /* 970 */ 11, 346, 301, 452, 452, 421, 34, 254, 324, 333, - /* 980 */ 251, 429, 429, 429, 430, 431, 11, 404, 405, 458, - /* 990 */ 265, 164, 293, 421, 3, 422, 228, 229, 230, 104, - /* 1000 */ 421, 28, 324, 403, 294, 324, 265, 265, 265, 75, - /* 1010 */ 74, 656, 207, 478, 283, 309, 179, 338, 73, 322, - /* 1020 */ 323, 284, 337, 427, 421, 23, 656, 421, 32, 324, - /* 1030 */ 656, 561, 656, 205, 420, 549, 326, 526, 419, 204, - /* 1040 */ 324, 128, 206, 324, 476, 511, 510, 279, 385, 281, - /* 1050 */ 514, 421, 53, 656, 515, 429, 429, 429, 430, 431, - /* 1060 */ 11, 649, 421, 52, 258, 421, 98, 324, 404, 405, - /* 1070 */ 183, 301, 260, 352, 355, 356, 649, 76, 650, 78, - /* 1080 */ 649, 246, 649, 262, 357, 384, 280, 270, 264, 421, - /* 1090 */ 96, 300, 247, 650, 656, 324, 210, 650, 191, 650, - /* 1100 */ 656, 656, 656, 656, 656, 656, 656, 653, 656, 324, - /* 1110 */ 364, 160, 440, 656, 656, 324, 295, 421, 101, 324, - /* 1120 */ 390, 583, 653, 324, 269, 324, 653, 447, 653, 22, - /* 1130 */ 372, 421, 102, 412, 375, 324, 476, 421, 112, 376, - /* 1140 */ 272, 421, 114, 324, 649, 421, 16, 421, 99, 653, - /* 1150 */ 649, 649, 649, 649, 649, 649, 649, 421, 33, 324, - /* 1160 */ 584, 650, 324, 649, 273, 421, 97, 650, 650, 650, - /* 1170 */ 650, 650, 650, 650, 483, 274, 175, 506, 507, 556, - /* 1180 */ 650, 421, 24, 324, 421, 54, 566, 516, 324, 128, - /* 1190 */ 653, 324, 256, 359, 128, 128, 653, 653, 653, 653, - /* 1200 */ 653, 653, 653, 324, 653, 421, 115, 146, 324, 653, - /* 1210 */ 421, 116, 282, 421, 117, 324, 545, 324, 128, 285, - /* 1220 */ 553, 324, 175, 324, 233, 421, 25, 554, 324, 91, - /* 1230 */ 421, 36, 324, 286, 324, 577, 426, 421, 37, 421, - /* 1240 */ 26, 324, 451, 421, 38, 421, 39, 324, 332, 324, - /* 1250 */ 421, 40, 324, 453, 421, 42, 421, 43, 564, 292, - /* 1260 */ 91, 324, 470, 421, 44, 324, 580, 324, 290, 421, - /* 1270 */ 29, 421, 30, 324, 421, 45, 324, 518, 298, 324, - /* 1280 */ 473, 248, 517, 421, 46, 324, 354, 421, 47, 421, - /* 1290 */ 48, 520, 552, 563, 165, 421, 31, 401, 421, 10, - /* 1300 */ 7, 421, 50, 409, 410, 411, 321, 421, 51, 84, - /* 1310 */ 423, 341, 237, 83, 339, 57, 234, 79, 235, 215, - /* 1320 */ 236, 172, 85, 424, 349, 344, 468, 125, 505, 308, - /* 1330 */ 295, 242, 499, 482, 244, 504, 486, 249, 508, 296, - /* 1340 */ 105, 221, 521, 149, 361, 150, 365, 527, 528, 529, - /* 1350 */ 186, 88, 121, 535, 187, 132, 363, 189, 142, 220, - /* 1360 */ 222, 383, 141, 190, 537, 192, 548, 371, 195, 267, - /* 1370 */ 382, 538, 133, 555, 562, 317, 134, 135, 136, 92, - /* 1380 */ 574, 138, 95, 575, 576, 579, 111, 100, 400, 319, - /* 1390 */ 122, 17, 413, 623, 624, 168, 169, 441, 444, 71, - /* 1400 */ 460, 448, 457, 143, 159, 171, 461, 6, 462, 479, - /* 1410 */ 466, 13, 126, 81, 12, 127, 163, 492, 493, 218, - /* 1420 */ 86, 353, 106, 358, 255, 107, 120, 87, 108, 184, - /* 1430 */ 247, 362, 145, 536, 175, 129, 366, 193, 109, 268, - /* 1440 */ 289, 551, 131, 14, 130, 197, 89, 539, 199, 201, - /* 1450 */ 543, 200, 139, 558, 137, 565, 110, 15, 287, 572, - /* 1460 */ 140, 208, 148, 396, 392, 586, 902, 902, 902, 902, - /* 1470 */ 90, + /* 0 */ 292, 89, 397, 93, 158, 164, 350, 511, 82, 82, + /* 10 */ 82, 82, 215, 84, 84, 84, 84, 85, 85, 86, + /* 20 */ 86, 86, 87, 210, 437, 310, 497, 482, 90, 84, + /* 30 */ 84, 84, 84, 85, 85, 86, 86, 86, 87, 210, + /* 40 */ 432, 420, 349, 420, 81, 77, 301, 472, 471, 481, + /* 50 */ 481, 83, 83, 82, 82, 82, 82, 210, 84, 84, + /* 60 */ 84, 84, 85, 85, 86, 86, 86, 87, 210, 292, + /* 70 */ 469, 310, 511, 400, 508, 76, 492, 491, 577, 564, + /* 80 */ 84, 84, 84, 84, 85, 85, 86, 86, 86, 87, + /* 90 */ 210, 395, 394, 219, 581, 497, 482, 486, 485, 75, + /* 100 */ 118, 283, 314, 282, 316, 175, 502, 502, 502, 361, + /* 110 */ 455, 453, 276, 81, 77, 301, 472, 471, 481, 481, + /* 120 */ 83, 83, 82, 82, 82, 82, 488, 84, 84, 84, + /* 130 */ 84, 85, 85, 86, 86, 86, 87, 210, 292, 219, + /* 140 */ 375, 520, 524, 428, 511, 194, 118, 283, 314, 282, + /* 150 */ 316, 175, 9, 391, 222, 375, 450, 89, 276, 93, + /* 160 */ 158, 521, 530, 36, 497, 482, 85, 85, 86, 86, + /* 170 */ 86, 87, 210, 222, 305, 455, 453, 530, 45, 549, + /* 180 */ 370, 292, 81, 77, 301, 472, 471, 481, 481, 83, + /* 190 */ 83, 82, 82, 82, 82, 475, 84, 84, 84, 84, + /* 200 */ 85, 85, 86, 86, 86, 87, 210, 497, 482, 511, + /* 210 */ 388, 505, 155, 296, 258, 449, 224, 335, 213, 439, + /* 220 */ 294, 440, 435, 179, 292, 81, 77, 301, 472, 471, + /* 230 */ 481, 481, 83, 83, 82, 82, 82, 82, 222, 84, + /* 240 */ 84, 84, 84, 85, 85, 86, 86, 86, 87, 210, + /* 250 */ 497, 482, 450, 448, 226, 250, 287, 522, 824, 441, + /* 260 */ 545, 188, 95, 1, 169, 260, 578, 450, 81, 77, + /* 270 */ 301, 472, 471, 481, 481, 83, 83, 82, 82, 82, + /* 280 */ 82, 377, 84, 84, 84, 84, 85, 85, 86, 86, + /* 290 */ 86, 87, 210, 247, 353, 249, 88, 292, 522, 174, + /* 300 */ 358, 432, 113, 369, 254, 255, 450, 443, 221, 389, + /* 310 */ 170, 161, 152, 430, 215, 321, 344, 440, 435, 526, + /* 320 */ 546, 149, 151, 497, 482, 450, 235, 392, 327, 583, + /* 330 */ 20, 469, 440, 435, 373, 508, 173, 172, 171, 65, + /* 340 */ 239, 81, 77, 301, 472, 471, 481, 481, 83, 83, + /* 350 */ 82, 82, 82, 82, 295, 84, 84, 84, 84, 85, + /* 360 */ 85, 86, 86, 86, 87, 210, 292, 502, 502, 502, + /* 370 */ 460, 440, 435, 167, 248, 375, 323, 326, 313, 490, + /* 380 */ 167, 375, 529, 323, 326, 313, 546, 328, 576, 157, + /* 390 */ 440, 435, 497, 482, 328, 484, 20, 530, 42, 366, + /* 400 */ 18, 466, 466, 530, 42, 366, 124, 466, 466, 292, + /* 410 */ 81, 77, 301, 472, 471, 481, 481, 83, 83, 82, + /* 420 */ 82, 82, 82, 522, 84, 84, 84, 84, 85, 85, + /* 430 */ 86, 86, 86, 87, 210, 497, 482, 80, 167, 340, + /* 440 */ 555, 323, 326, 313, 319, 340, 901, 139, 552, 8, + /* 450 */ 341, 2, 328, 81, 77, 301, 472, 471, 481, 481, + /* 460 */ 83, 83, 82, 82, 82, 82, 205, 84, 84, 84, + /* 470 */ 84, 85, 85, 86, 86, 86, 87, 210, 292, 533, + /* 480 */ 375, 496, 406, 57, 86, 86, 86, 87, 210, 375, + /* 490 */ 79, 375, 63, 375, 405, 547, 89, 168, 93, 158, + /* 500 */ 400, 159, 530, 32, 497, 482, 528, 404, 124, 480, + /* 510 */ 450, 530, 32, 530, 45, 530, 24, 450, 395, 463, + /* 520 */ 268, 264, 81, 77, 301, 472, 471, 481, 481, 83, + /* 530 */ 83, 82, 82, 82, 82, 522, 84, 84, 84, 84, + /* 540 */ 85, 85, 86, 86, 86, 87, 210, 292, 300, 375, + /* 550 */ 462, 390, 546, 2, 208, 375, 450, 303, 263, 622, + /* 560 */ 266, 410, 20, 425, 450, 443, 89, 424, 93, 158, + /* 570 */ 191, 530, 25, 497, 482, 440, 435, 530, 42, 352, + /* 580 */ 382, 222, 440, 435, 272, 150, 582, 418, 441, 357, + /* 590 */ 188, 81, 77, 301, 472, 471, 481, 481, 83, 83, + /* 600 */ 82, 82, 82, 82, 522, 84, 84, 84, 84, 85, + /* 610 */ 85, 86, 86, 86, 87, 210, 292, 401, 320, 331, + /* 620 */ 270, 440, 435, 406, 366, 539, 466, 466, 365, 440, + /* 630 */ 435, 580, 561, 457, 892, 405, 892, 559, 579, 91, + /* 640 */ 530, 3, 497, 482, 464, 87, 210, 565, 404, 261, + /* 650 */ 345, 359, 403, 457, 891, 566, 891, 535, 573, 292, + /* 660 */ 81, 77, 301, 472, 471, 481, 481, 83, 83, 82, + /* 670 */ 82, 82, 82, 550, 84, 84, 84, 84, 85, 85, + /* 680 */ 86, 86, 86, 87, 210, 497, 482, 409, 544, 574, + /* 690 */ 385, 415, 211, 550, 519, 518, 539, 368, 571, 535, + /* 700 */ 562, 506, 292, 81, 77, 301, 472, 471, 481, 481, + /* 710 */ 83, 83, 82, 82, 82, 82, 375, 84, 84, 84, + /* 720 */ 84, 85, 85, 86, 86, 86, 87, 210, 497, 482, + /* 730 */ 366, 557, 466, 466, 306, 279, 443, 221, 530, 41, + /* 740 */ 535, 387, 229, 535, 535, 292, 81, 94, 301, 472, + /* 750 */ 471, 481, 481, 83, 83, 82, 82, 82, 82, 375, + /* 760 */ 84, 84, 84, 84, 85, 85, 86, 86, 86, 87, + /* 770 */ 210, 497, 482, 477, 551, 309, 189, 279, 308, 312, + /* 780 */ 147, 530, 10, 588, 516, 317, 445, 445, 292, 318, + /* 790 */ 77, 301, 472, 471, 481, 481, 83, 83, 82, 82, + /* 800 */ 82, 82, 375, 84, 84, 84, 84, 85, 85, 86, + /* 810 */ 86, 86, 87, 210, 497, 482, 553, 478, 279, 91, + /* 820 */ 570, 279, 279, 542, 530, 39, 433, 431, 429, 567, + /* 830 */ 19, 164, 145, 511, 301, 472, 471, 481, 481, 83, + /* 840 */ 83, 82, 82, 82, 82, 186, 84, 84, 84, 84, + /* 850 */ 85, 85, 86, 86, 86, 87, 210, 69, 354, 375, + /* 860 */ 4, 375, 21, 375, 299, 470, 511, 168, 375, 363, + /* 870 */ 334, 375, 364, 69, 354, 62, 4, 525, 375, 522, + /* 880 */ 299, 530, 26, 530, 34, 530, 117, 375, 364, 346, + /* 890 */ 530, 49, 228, 530, 51, 375, 153, 174, 511, 432, + /* 900 */ 530, 27, 375, 553, 375, 346, 459, 570, 22, 530, + /* 910 */ 40, 438, 330, 124, 124, 432, 375, 530, 116, 61, + /* 920 */ 66, 567, 516, 317, 530, 35, 530, 115, 68, 379, + /* 930 */ 378, 511, 540, 508, 223, 61, 66, 531, 530, 54, + /* 940 */ 523, 375, 381, 215, 68, 379, 378, 69, 354, 508, + /* 950 */ 4, 215, 295, 375, 299, 375, 367, 276, 199, 261, + /* 960 */ 517, 215, 364, 530, 48, 502, 502, 502, 500, 499, + /* 970 */ 12, 548, 375, 586, 380, 530, 28, 530, 31, 346, + /* 980 */ 585, 502, 502, 502, 500, 499, 12, 307, 123, 432, + /* 990 */ 442, 177, 522, 304, 530, 38, 231, 233, 234, 103, + /* 1000 */ 238, 555, 375, 281, 160, 375, 363, 375, 230, 61, + /* 1010 */ 66, 503, 166, 271, 236, 124, 196, 204, 68, 379, + /* 1020 */ 378, 232, 375, 508, 530, 23, 375, 530, 43, 530, + /* 1030 */ 33, 375, 468, 203, 489, 448, 261, 261, 522, 163, + /* 1040 */ 277, 375, 176, 375, 530, 53, 251, 375, 530, 29, + /* 1050 */ 375, 522, 375, 530, 37, 502, 502, 502, 500, 499, + /* 1060 */ 12, 214, 458, 530, 52, 530, 98, 375, 55, 530, + /* 1070 */ 96, 217, 530, 101, 530, 102, 375, 493, 498, 540, + /* 1080 */ 261, 375, 540, 375, 535, 374, 245, 255, 555, 530, + /* 1090 */ 112, 293, 375, 507, 375, 290, 215, 261, 530, 114, + /* 1100 */ 375, 261, 375, 530, 46, 530, 16, 162, 161, 261, + /* 1110 */ 375, 165, 375, 261, 530, 99, 530, 44, 537, 291, + /* 1120 */ 384, 501, 530, 50, 530, 47, 252, 274, 446, 564, + /* 1130 */ 253, 362, 530, 97, 530, 30, 360, 356, 504, 256, + /* 1140 */ 311, 119, 246, 351, 343, 522, 342, 262, 399, 265, + /* 1150 */ 376, 267, 237, 269, 225, 6, 534, 587, 148, 538, + /* 1160 */ 510, 325, 280, 285, 240, 417, 515, 444, 584, 541, + /* 1170 */ 452, 461, 347, 259, 315, 561, 487, 184, 465, 532, + /* 1180 */ 494, 200, 108, 454, 426, 436, 423, 422, 73, 421, + /* 1190 */ 7, 383, 297, 137, 71, 128, 62, 241, 333, 514, + /* 1200 */ 70, 336, 74, 120, 130, 372, 242, 371, 243, 509, + /* 1210 */ 244, 133, 513, 134, 135, 136, 483, 355, 190, 447, + /* 1220 */ 337, 193, 64, 56, 298, 473, 411, 111, 289, 197, + /* 1230 */ 198, 142, 568, 563, 558, 398, 339, 201, 92, 393, + /* 1240 */ 220, 202, 322, 127, 207, 543, 275, 209, 496, 554, + /* 1250 */ 536, 278, 288, 78, 414, 218, 17, 100, 212, 479, + /* 1260 */ 575, 121, 72, 332, 572, 527, 284, 556, 156, 302, + /* 1270 */ 140, 216, 104, 122, 132, 324, 105, 560, 273, 329, + /* 1280 */ 110, 109, 206, 512, 11, 67, 260, 13, 338, 5, + /* 1290 */ 396, 143, 126, 195, 402, 407, 412, 154, 419, 125, + /* 1300 */ 348, 416, 168, 257, 427, 144, 107, 192, 434, 286, + /* 1310 */ 451, 456, 138, 59, 60, 187, 58, 15, 467, 474, + /* 1320 */ 185, 183, 495, 129, 141, 180, 569, 182, 131, 178, + /* 1330 */ 624, 623, 14, 106, 408, 413, 181, 476, 386, 146, + /* 1340 */ 227, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70, - /* 10 */ 71, 72, 176, 74, 75, 76, 77, 78, 79, 80, - /* 20 */ 81, 82, 83, 84, 78, 79, 42, 43, 73, 74, + /* 0 */ 16, 217, 218, 219, 220, 21, 223, 23, 69, 70, + /* 10 */ 71, 72, 110, 74, 75, 76, 77, 78, 79, 80, + /* 20 */ 81, 82, 83, 84, 169, 16, 42, 43, 73, 74, /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - /* 40 */ 1, 2, 23, 58, 60, 61, 62, 63, 64, 65, - /* 50 */ 66, 67, 68, 69, 70, 71, 72, 147, 74, 75, + /* 40 */ 58, 99, 100, 101, 60, 61, 62, 63, 64, 65, + /* 50 */ 66, 67, 68, 69, 70, 71, 72, 84, 74, 75, /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, - /* 70 */ 185, 186, 88, 88, 110, 22, 217, 92, 219, 220, + /* 70 */ 88, 16, 88, 147, 92, 22, 42, 43, 185, 186, /* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 90 */ 84, 217, 218, 219, 220, 42, 43, 238, 188, 46, - /* 100 */ 78, 79, 80, 81, 82, 83, 84, 88, 89, 124, - /* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66, - /* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76, - /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, - /* 140 */ 44, 80, 81, 82, 83, 84, 23, 84, 169, 170, - /* 150 */ 19, 164, 165, 166, 23, 161, 60, 61, 62, 63, - /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 169, - /* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 180 */ 84, 16, 14, 147, 155, 147, 21, 167, 168, 58, - /* 190 */ 211, 147, 156, 157, 200, 216, 176, 23, 27, 176, - /* 200 */ 177, 78, 79, 165, 166, 34, 183, 42, 43, 78, - /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 189, 88, - /* 220 */ 52, 98, 54, 92, 16, 60, 61, 62, 63, 64, - /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74, + /* 90 */ 84, 165, 166, 84, 181, 42, 43, 63, 64, 46, + /* 100 */ 91, 92, 93, 94, 95, 96, 124, 125, 126, 164, + /* 110 */ 165, 166, 103, 60, 61, 62, 63, 64, 65, 66, + /* 120 */ 67, 68, 69, 70, 71, 72, 92, 74, 75, 76, + /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 84, + /* 140 */ 147, 30, 20, 18, 23, 90, 91, 92, 93, 94, + /* 150 */ 95, 96, 19, 227, 228, 147, 23, 217, 103, 219, + /* 160 */ 220, 50, 169, 170, 42, 43, 78, 79, 80, 81, + /* 170 */ 82, 83, 84, 228, 164, 165, 166, 169, 170, 181, + /* 180 */ 55, 16, 60, 61, 62, 63, 64, 65, 66, 67, + /* 190 */ 68, 69, 70, 71, 72, 169, 74, 75, 76, 77, + /* 200 */ 78, 79, 80, 81, 82, 83, 84, 42, 43, 88, + /* 210 */ 142, 143, 147, 102, 221, 11, 148, 209, 210, 94, + /* 220 */ 150, 88, 89, 155, 16, 60, 61, 62, 63, 64, + /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 228, 74, /* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 175, 11, - /* 260 */ 169, 170, 88, 89, 20, 227, 228, 16, 60, 61, + /* 250 */ 42, 43, 23, 49, 92, 14, 158, 189, 133, 161, + /* 260 */ 162, 163, 19, 19, 155, 103, 23, 23, 60, 61, /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 280 */ 72, 1, 74, 75, 76, 77, 78, 79, 80, 81, - /* 290 */ 82, 83, 84, 42, 43, 175, 16, 49, 147, 147, - /* 300 */ 20, 210, 22, 217, 153, 219, 220, 156, 157, 83, - /* 310 */ 84, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 320 */ 69, 70, 71, 72, 147, 74, 75, 76, 77, 78, - /* 330 */ 79, 80, 81, 82, 83, 84, 1, 147, 158, 131, - /* 340 */ 16, 161, 162, 163, 20, 155, 190, 99, 100, 101, - /* 350 */ 106, 16, 108, 109, 147, 20, 147, 22, 110, 169, - /* 360 */ 170, 161, 162, 163, 84, 188, 42, 43, 169, 23, - /* 370 */ 90, 91, 92, 93, 94, 95, 96, 225, 43, 189, - /* 380 */ 244, 245, 131, 103, 60, 61, 62, 63, 64, 65, - /* 390 */ 66, 67, 68, 69, 70, 71, 72, 110, 74, 75, - /* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, - /* 410 */ 123, 19, 20, 20, 22, 208, 239, 208, 147, 84, - /* 420 */ 19, 147, 16, 147, 23, 90, 91, 92, 93, 94, - /* 430 */ 95, 96, 147, 98, 88, 42, 43, 181, 103, 104, - /* 440 */ 169, 170, 147, 169, 170, 169, 170, 164, 165, 166, - /* 450 */ 165, 59, 80, 60, 61, 62, 63, 64, 65, 66, - /* 460 */ 67, 68, 69, 70, 71, 72, 1, 74, 75, 76, - /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 107, - /* 480 */ 155, 16, 20, 111, 147, 20, 215, 22, 16, 88, - /* 490 */ 84, 215, 20, 181, 22, 221, 90, 91, 92, 93, - /* 500 */ 94, 95, 96, 208, 42, 43, 169, 170, 43, 103, - /* 510 */ 147, 228, 227, 228, 189, 43, 0, 1, 2, 7, - /* 520 */ 8, 9, 60, 61, 62, 63, 64, 65, 66, 67, - /* 530 */ 68, 69, 70, 71, 72, 186, 74, 75, 76, 77, - /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 211, 84, - /* 550 */ 16, 20, 12, 185, 186, 90, 91, 92, 93, 94, - /* 560 */ 95, 96, 90, 98, 24, 93, 94, 95, 103, 104, - /* 570 */ 98, 147, 160, 42, 43, 103, 104, 37, 19, 39, - /* 580 */ 18, 169, 23, 19, 20, 155, 22, 147, 21, 49, - /* 590 */ 23, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 600 */ 69, 70, 71, 72, 147, 74, 75, 76, 77, 78, - /* 610 */ 79, 80, 81, 82, 83, 84, 16, 55, 84, 189, - /* 620 */ 19, 21, 147, 59, 23, 91, 92, 93, 94, 95, - /* 630 */ 96, 201, 202, 147, 23, 90, 206, 103, 93, 94, - /* 640 */ 95, 145, 42, 43, 20, 142, 143, 88, 89, 104, - /* 650 */ 20, 148, 99, 100, 101, 88, 94, 150, 155, 16, + /* 280 */ 72, 213, 74, 75, 76, 77, 78, 79, 80, 81, + /* 290 */ 82, 83, 84, 52, 224, 54, 131, 16, 189, 43, + /* 300 */ 230, 58, 21, 99, 100, 101, 23, 78, 79, 241, + /* 310 */ 201, 202, 22, 20, 110, 206, 186, 88, 89, 20, + /* 320 */ 147, 78, 79, 42, 43, 23, 153, 98, 147, 156, + /* 330 */ 157, 88, 88, 89, 147, 92, 99, 100, 101, 131, + /* 340 */ 190, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 350 */ 69, 70, 71, 72, 98, 74, 75, 76, 77, 78, + /* 360 */ 79, 80, 81, 82, 83, 84, 16, 124, 125, 126, + /* 370 */ 20, 88, 89, 90, 133, 147, 93, 94, 95, 160, + /* 380 */ 90, 147, 80, 93, 94, 95, 147, 104, 169, 155, + /* 390 */ 88, 89, 42, 43, 104, 156, 157, 169, 170, 106, + /* 400 */ 19, 108, 109, 169, 170, 106, 22, 108, 109, 16, + /* 410 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 420 */ 70, 71, 72, 189, 74, 75, 76, 77, 78, 79, + /* 430 */ 80, 81, 82, 83, 84, 42, 43, 44, 90, 211, + /* 440 */ 161, 93, 94, 95, 216, 211, 139, 140, 141, 68, + /* 450 */ 216, 144, 104, 60, 61, 62, 63, 64, 65, 66, + /* 460 */ 67, 68, 69, 70, 71, 72, 19, 74, 75, 76, + /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 200, + /* 480 */ 147, 97, 12, 21, 80, 81, 82, 83, 84, 147, + /* 490 */ 130, 147, 132, 147, 24, 20, 217, 22, 219, 220, + /* 500 */ 147, 155, 169, 170, 42, 43, 20, 37, 22, 39, + /* 510 */ 23, 169, 170, 169, 170, 169, 170, 23, 165, 49, + /* 520 */ 14, 147, 60, 61, 62, 63, 64, 65, 66, 67, + /* 530 */ 68, 69, 70, 71, 72, 189, 74, 75, 76, 77, + /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 215, 147, + /* 550 */ 141, 20, 147, 144, 210, 147, 23, 215, 52, 112, + /* 560 */ 54, 156, 157, 25, 23, 78, 217, 29, 219, 220, + /* 570 */ 155, 169, 170, 42, 43, 88, 89, 169, 170, 41, + /* 580 */ 227, 228, 88, 89, 147, 180, 181, 238, 161, 162, + /* 590 */ 163, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 600 */ 69, 70, 71, 72, 189, 74, 75, 76, 77, 78, + /* 610 */ 79, 80, 81, 82, 83, 84, 16, 168, 147, 211, + /* 620 */ 20, 88, 89, 12, 106, 176, 108, 109, 213, 88, + /* 630 */ 89, 176, 177, 19, 20, 24, 22, 20, 183, 22, + /* 640 */ 169, 170, 42, 43, 20, 83, 84, 114, 37, 147, + /* 650 */ 39, 236, 20, 19, 20, 114, 22, 147, 147, 16, /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - /* 670 */ 70, 71, 72, 147, 74, 75, 76, 77, 78, 79, - /* 680 */ 80, 81, 82, 83, 84, 42, 43, 212, 147, 88, - /* 690 */ 89, 80, 189, 141, 19, 133, 144, 156, 157, 88, - /* 700 */ 89, 155, 16, 60, 61, 62, 63, 64, 65, 66, - /* 710 */ 67, 68, 69, 70, 71, 72, 213, 74, 75, 76, + /* 670 */ 70, 71, 72, 59, 74, 75, 76, 77, 78, 79, + /* 680 */ 80, 81, 82, 83, 84, 42, 43, 167, 168, 22, + /* 690 */ 188, 59, 182, 59, 91, 92, 176, 16, 203, 147, + /* 700 */ 7, 8, 16, 60, 61, 62, 63, 64, 65, 66, + /* 710 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76, /* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, - /* 730 */ 106, 224, 108, 109, 161, 189, 106, 230, 108, 109, - /* 740 */ 14, 147, 147, 68, 241, 16, 60, 61, 62, 63, - /* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 213, + /* 730 */ 106, 147, 108, 109, 182, 225, 78, 79, 169, 170, + /* 740 */ 147, 239, 147, 147, 147, 16, 60, 61, 62, 63, + /* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 147, /* 760 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 770 */ 84, 42, 43, 200, 192, 19, 182, 182, 52, 22, - /* 780 */ 54, 199, 236, 147, 99, 100, 101, 147, 16, 147, + /* 770 */ 84, 42, 43, 92, 147, 182, 22, 225, 182, 182, + /* 780 */ 113, 169, 170, 0, 1, 2, 124, 125, 16, 80, /* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 800 */ 71, 72, 1, 74, 75, 76, 77, 78, 79, 80, - /* 810 */ 81, 82, 83, 84, 42, 43, 23, 16, 182, 225, - /* 820 */ 225, 20, 182, 22, 106, 191, 108, 109, 161, 25, - /* 830 */ 22, 147, 22, 29, 62, 63, 64, 65, 66, 67, - /* 840 */ 68, 69, 70, 71, 72, 41, 74, 75, 76, 77, - /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 133, - /* 860 */ 19, 225, 147, 147, 23, 225, 182, 200, 112, 201, - /* 870 */ 202, 161, 31, 16, 17, 147, 19, 147, 121, 155, - /* 880 */ 23, 88, 89, 147, 217, 84, 219, 220, 31, 48, - /* 890 */ 16, 90, 91, 92, 93, 94, 95, 96, 90, 58, - /* 900 */ 155, 93, 94, 95, 103, 48, 91, 114, 155, 225, - /* 910 */ 42, 43, 104, 189, 12, 58, 188, 43, 188, 78, - /* 920 */ 79, 147, 23, 113, 188, 110, 24, 212, 87, 88, - /* 930 */ 89, 63, 64, 92, 189, 78, 79, 80, 123, 37, - /* 940 */ 203, 39, 189, 30, 87, 88, 89, 16, 17, 92, - /* 950 */ 19, 110, 147, 147, 23, 242, 243, 19, 147, 21, - /* 960 */ 92, 155, 31, 50, 147, 124, 125, 126, 127, 128, - /* 970 */ 129, 147, 98, 124, 125, 169, 170, 103, 147, 48, - /* 980 */ 147, 124, 125, 126, 127, 128, 129, 88, 89, 58, - /* 990 */ 147, 5, 147, 169, 170, 189, 10, 11, 12, 13, - /* 1000 */ 169, 170, 147, 23, 178, 147, 147, 147, 147, 78, - /* 1010 */ 79, 1, 26, 114, 28, 102, 43, 211, 87, 88, - /* 1020 */ 89, 35, 216, 92, 169, 170, 16, 169, 170, 147, - /* 1030 */ 20, 188, 22, 47, 107, 49, 16, 147, 111, 53, - /* 1040 */ 147, 22, 56, 147, 22, 91, 92, 188, 188, 188, - /* 1050 */ 178, 169, 170, 43, 178, 124, 125, 126, 127, 128, - /* 1060 */ 129, 1, 169, 170, 147, 169, 170, 147, 88, 89, - /* 1070 */ 90, 98, 147, 93, 94, 95, 16, 130, 1, 132, - /* 1080 */ 20, 92, 22, 147, 104, 99, 100, 101, 147, 169, - /* 1090 */ 170, 105, 103, 16, 84, 147, 110, 20, 232, 22, - /* 1100 */ 90, 91, 92, 93, 94, 95, 96, 1, 98, 147, - /* 1110 */ 233, 89, 92, 103, 104, 147, 97, 169, 170, 147, - /* 1120 */ 134, 20, 16, 147, 147, 147, 20, 20, 22, 22, - /* 1130 */ 147, 169, 170, 149, 147, 147, 114, 169, 170, 147, - /* 1140 */ 147, 169, 170, 147, 84, 169, 170, 169, 170, 43, - /* 1150 */ 90, 91, 92, 93, 94, 95, 96, 169, 170, 147, - /* 1160 */ 59, 84, 147, 103, 147, 169, 170, 90, 91, 92, - /* 1170 */ 93, 94, 95, 96, 20, 147, 22, 7, 8, 147, - /* 1180 */ 103, 169, 170, 147, 169, 170, 147, 20, 147, 22, - /* 1190 */ 84, 147, 20, 20, 22, 22, 90, 91, 92, 93, - /* 1200 */ 94, 95, 96, 147, 98, 169, 170, 191, 147, 103, - /* 1210 */ 169, 170, 147, 169, 170, 147, 20, 147, 22, 147, - /* 1220 */ 20, 147, 22, 147, 193, 169, 170, 20, 147, 22, - /* 1230 */ 169, 170, 147, 147, 147, 147, 161, 169, 170, 169, - /* 1240 */ 170, 147, 229, 169, 170, 169, 170, 147, 223, 147, - /* 1250 */ 169, 170, 147, 229, 169, 170, 169, 170, 20, 177, - /* 1260 */ 22, 147, 172, 169, 170, 147, 20, 147, 22, 169, - /* 1270 */ 170, 169, 170, 147, 169, 170, 147, 161, 161, 147, - /* 1280 */ 172, 172, 172, 169, 170, 147, 173, 169, 170, 169, - /* 1290 */ 170, 172, 194, 194, 6, 169, 170, 146, 169, 170, - /* 1300 */ 22, 169, 170, 146, 146, 146, 154, 169, 170, 121, - /* 1310 */ 189, 118, 197, 119, 116, 120, 194, 130, 195, 222, - /* 1320 */ 196, 112, 98, 198, 98, 115, 152, 152, 179, 40, - /* 1330 */ 97, 204, 171, 205, 204, 171, 205, 171, 173, 171, - /* 1340 */ 19, 84, 179, 174, 15, 174, 38, 171, 171, 171, - /* 1350 */ 151, 130, 60, 152, 151, 19, 152, 151, 214, 226, - /* 1360 */ 226, 15, 214, 152, 152, 151, 184, 152, 184, 234, - /* 1370 */ 152, 235, 187, 194, 194, 152, 187, 187, 187, 237, - /* 1380 */ 33, 184, 237, 152, 152, 137, 240, 159, 1, 246, - /* 1390 */ 243, 231, 20, 112, 112, 112, 112, 92, 107, 19, - /* 1400 */ 11, 20, 20, 19, 19, 22, 20, 117, 20, 114, - /* 1410 */ 20, 117, 19, 22, 22, 20, 112, 20, 20, 44, - /* 1420 */ 19, 44, 19, 44, 20, 19, 32, 19, 19, 96, - /* 1430 */ 103, 16, 21, 17, 22, 98, 36, 98, 19, 133, - /* 1440 */ 5, 1, 102, 19, 45, 122, 68, 51, 113, 115, - /* 1450 */ 45, 14, 102, 17, 113, 123, 14, 19, 136, 20, - /* 1460 */ 122, 135, 19, 3, 57, 4, 247, 247, 247, 247, - /* 1470 */ 68, + /* 800 */ 71, 72, 147, 74, 75, 76, 77, 78, 79, 80, + /* 810 */ 81, 82, 83, 84, 42, 43, 107, 20, 225, 22, + /* 820 */ 111, 225, 225, 147, 169, 170, 7, 8, 9, 22, + /* 830 */ 19, 21, 21, 23, 62, 63, 64, 65, 66, 67, + /* 840 */ 68, 69, 70, 71, 72, 155, 74, 75, 76, 77, + /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 147, + /* 860 */ 19, 147, 19, 147, 23, 20, 23, 22, 147, 147, + /* 870 */ 16, 147, 31, 16, 17, 121, 19, 178, 147, 189, + /* 880 */ 23, 169, 170, 169, 170, 169, 170, 147, 31, 48, + /* 890 */ 169, 170, 145, 169, 170, 147, 89, 43, 88, 58, + /* 900 */ 169, 170, 147, 107, 147, 48, 20, 111, 22, 169, + /* 910 */ 170, 20, 20, 22, 22, 58, 147, 169, 170, 78, + /* 920 */ 79, 114, 1, 2, 169, 170, 169, 170, 87, 88, + /* 930 */ 89, 88, 147, 92, 212, 78, 79, 80, 169, 170, + /* 940 */ 178, 147, 91, 110, 87, 88, 89, 16, 17, 92, + /* 950 */ 19, 110, 98, 147, 23, 147, 123, 103, 155, 147, + /* 960 */ 178, 110, 31, 169, 170, 124, 125, 126, 127, 128, + /* 970 */ 129, 147, 147, 27, 123, 169, 170, 169, 170, 48, + /* 980 */ 34, 124, 125, 126, 127, 128, 129, 242, 243, 58, + /* 990 */ 161, 5, 189, 208, 169, 170, 10, 11, 12, 13, + /* 1000 */ 188, 161, 147, 147, 155, 147, 147, 147, 147, 78, + /* 1010 */ 79, 147, 26, 20, 28, 22, 232, 155, 87, 88, + /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 169, + /* 1030 */ 170, 147, 147, 47, 147, 49, 147, 147, 189, 53, + /* 1040 */ 200, 147, 56, 147, 169, 170, 147, 147, 169, 170, + /* 1050 */ 147, 189, 147, 169, 170, 124, 125, 126, 127, 128, + /* 1060 */ 129, 192, 147, 169, 170, 169, 170, 147, 199, 169, + /* 1070 */ 170, 212, 169, 170, 169, 170, 147, 188, 188, 147, + /* 1080 */ 147, 147, 147, 147, 147, 99, 100, 101, 161, 169, + /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 147, 169, 170, + /* 1100 */ 147, 147, 147, 169, 170, 169, 170, 201, 202, 147, + /* 1110 */ 147, 155, 147, 147, 169, 170, 169, 170, 244, 245, + /* 1120 */ 134, 188, 169, 170, 169, 170, 147, 200, 185, 186, + /* 1130 */ 147, 147, 169, 170, 169, 170, 147, 147, 188, 147, + /* 1140 */ 208, 147, 188, 208, 147, 189, 233, 147, 147, 147, + /* 1150 */ 188, 147, 147, 147, 188, 191, 161, 172, 191, 172, + /* 1160 */ 161, 173, 225, 172, 193, 149, 194, 229, 172, 161, + /* 1170 */ 229, 194, 38, 234, 98, 177, 137, 6, 146, 172, + /* 1180 */ 171, 112, 240, 152, 146, 152, 33, 146, 237, 146, + /* 1190 */ 22, 154, 152, 19, 237, 214, 121, 194, 118, 189, + /* 1200 */ 119, 116, 120, 60, 184, 15, 195, 152, 196, 194, + /* 1210 */ 197, 187, 198, 187, 187, 187, 194, 152, 184, 184, + /* 1220 */ 15, 151, 130, 130, 40, 179, 152, 19, 174, 152, + /* 1230 */ 151, 214, 171, 171, 171, 152, 152, 151, 98, 152, + /* 1240 */ 222, 151, 115, 152, 84, 179, 204, 226, 97, 205, + /* 1250 */ 205, 204, 174, 19, 235, 226, 231, 159, 44, 171, + /* 1260 */ 171, 32, 19, 3, 20, 20, 171, 173, 112, 246, + /* 1270 */ 20, 175, 175, 243, 19, 44, 19, 114, 20, 44, + /* 1280 */ 19, 19, 96, 4, 117, 22, 103, 22, 16, 117, + /* 1290 */ 17, 21, 98, 22, 20, 20, 20, 19, 51, 45, + /* 1300 */ 36, 11, 22, 133, 45, 19, 19, 98, 20, 5, + /* 1310 */ 1, 20, 102, 19, 68, 122, 68, 19, 107, 92, + /* 1320 */ 113, 14, 17, 102, 122, 112, 123, 115, 113, 112, + /* 1330 */ 112, 112, 19, 14, 20, 20, 135, 1, 57, 19, + /* 1340 */ 136, }; -#define YY_SHIFT_USE_DFLT (-62) -#define YY_SHIFT_MAX 396 +#define YY_SHIFT_USE_DFLT (-99) +#define YY_SHIFT_MAX 389 static const short yy_shift_ofst[] = { - /* 0 */ 39, 841, 986, -16, 841, 931, 931, 980, 123, -36, - /* 10 */ 96, 931, 931, 931, 931, 931, -45, 248, 174, 19, - /* 20 */ 346, -54, -54, 53, 165, 208, 251, 324, 393, 462, - /* 30 */ 531, 600, 643, 686, 643, 643, 643, 643, 643, 643, - /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + /* 0 */ 921, 841, 986, -16, 841, 931, 931, 283, 229, -98, + /* 10 */ 393, 931, 931, 931, 931, 931, -45, 204, 487, 494, + /* 20 */ 121, 658, 658, 53, 122, 165, 281, 208, 462, 600, + /* 30 */ 531, 350, 643, 643, 643, 643, 643, 643, 643, 643, + /* 40 */ 643, 643, 643, 643, 643, 643, 643, 686, 643, 643, /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931, /* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, /* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, /* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, /* 90 */ 931, 931, 931, 931, 931, 931, -61, -61, 6, 6, - /* 100 */ 406, 22, 61, 874, 562, 19, 19, 19, 19, 19, - /* 110 */ 19, 19, 226, 346, 63, -62, -62, -62, 131, 534, - /* 120 */ 540, 540, 392, 564, 516, 567, 19, 567, 19, 19, - /* 130 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - /* 140 */ 19, 815, 287, -36, -36, -36, -62, -62, -62, 1106, - /* 150 */ 472, -15, -15, 808, 545, 244, 559, 624, 630, 902, - /* 160 */ 793, 899, 601, 611, 512, 19, 19, 372, 19, 19, - /* 170 */ 401, 19, 19, 1022, 19, 19, 718, 1022, 19, 19, - /* 180 */ 913, 913, 913, 19, 19, 718, 19, 19, 718, 19, - /* 190 */ 804, 553, 19, 19, 718, 19, 19, 19, 718, 19, - /* 200 */ 19, 19, 718, 718, 19, 19, 19, 19, 19, 938, - /* 210 */ 927, 810, 346, 849, 849, 947, 171, 171, 171, 973, - /* 220 */ 171, 346, 171, 346, 1019, 757, 757, 1288, 1288, 1288, - /* 230 */ 1288, 1278, -36, 1188, 1193, 1194, 1198, 1195, 1187, 1209, - /* 240 */ 1209, 1224, 1210, 1224, 1210, 1226, 1226, 1289, 1226, 1233, - /* 250 */ 1226, 1321, 1257, 1257, 1289, 1226, 1226, 1226, 1321, 1329, - /* 260 */ 1209, 1329, 1209, 1329, 1209, 1209, 1308, 1221, 1329, 1209, - /* 270 */ 1292, 1292, 1336, 1188, 1209, 1346, 1346, 1346, 1346, 1188, - /* 280 */ 1292, 1336, 1209, 1347, 1347, 1209, 1209, 1248, -62, -62, - /* 290 */ -62, -62, 335, 465, 1010, 280, 801, 1060, 1077, 868, - /* 300 */ 726, 685, 168, 756, 1020, 1107, 1154, 989, 1170, 954, - /* 310 */ 1167, 1172, 1173, 1196, 1200, 1207, 1238, 675, 1246, 1101, - /* 320 */ 1387, 1372, 1281, 1282, 1283, 1284, 1305, 1291, 1380, 1381, - /* 330 */ 1382, 1384, 1389, 1385, 1386, 1383, 1388, 1390, 1391, 1290, - /* 340 */ 1392, 1294, 1391, 1295, 1393, 1395, 1304, 1397, 1398, 1394, - /* 350 */ 1375, 1401, 1377, 1403, 1404, 1406, 1408, 1379, 1409, 1333, - /* 360 */ 1327, 1415, 1416, 1411, 1337, 1400, 1396, 1399, 1412, 1405, - /* 370 */ 1306, 1339, 1419, 1435, 1440, 1340, 1378, 1402, 1323, 1424, - /* 380 */ 1335, 1437, 1334, 1436, 1341, 1350, 1338, 1438, 1332, 1439, - /* 390 */ 1442, 1407, 1326, 1322, 1443, 1460, 1461, + /* 100 */ 55, 88, 404, 125, 854, 494, 494, 494, 494, 494, + /* 110 */ 494, 494, 562, 121, -27, -99, -99, -99, 243, 9, + /* 120 */ 470, 470, 614, 634, 494, 494, 494, 810, 851, 494, + /* 130 */ 494, 494, 494, 494, 494, 494, 494, 494, 494, 783, + /* 140 */ 810, 494, 833, -98, -98, -98, -99, -99, -99, -18, + /* 150 */ 290, -18, 348, 541, 611, 533, 302, 624, 244, 299, + /* 160 */ 293, 133, 807, 494, 494, 518, 494, 494, 494, 518, + /* 170 */ 807, 111, 111, 111, 494, 494, 494, 819, 494, 518, + /* 180 */ 494, 494, 494, 494, 494, 494, 518, 494, 843, 494, + /* 190 */ 494, 518, 494, 494, 494, 494, -58, 538, 494, 518, + /* 200 */ 494, 494, 494, 494, 518, 709, 494, 121, 946, 946, + /* 210 */ 121, 384, 946, 946, 667, 796, 256, 754, 946, 121, + /* 220 */ 360, 662, 662, 754, 811, 1134, 1076, 1039, 1171, 1069, + /* 230 */ 1069, 1171, 1153, 1171, 1171, 1168, 1153, 1069, 1174, -98, + /* 240 */ 1075, 1080, 1081, 1085, 1082, 1143, 1075, 1190, 1190, 1190, + /* 250 */ 1190, 1069, 1075, 1174, 1143, 1143, 1069, 1205, 1092, 1093, + /* 260 */ 1184, 1069, 1069, 1205, 1069, 1069, 1205, 1069, 1205, 1208, + /* 270 */ 1076, 1076, 1069, 1076, 1140, 1127, 1184, 1140, 1127, 1160, + /* 280 */ 1160, 1208, 1076, 1076, 1151, 1076, -99, -99, -99, -99, + /* 290 */ -99, -99, 34, 241, 506, 237, 603, 381, 693, 447, + /* 300 */ 617, 681, 632, 797, 845, 886, 891, 1073, 993, 892, + /* 310 */ 162, 475, 486, 1234, 1214, 1229, 1243, 1260, 1244, 1245, + /* 320 */ 1156, 1250, 1255, 1231, 1257, 1258, 1261, 1163, 1235, 1262, + /* 330 */ 1186, 1263, 1279, 1167, 1183, 1265, 1172, 1272, 1273, 1270, + /* 340 */ 1263, 1274, 1194, 1275, 1271, 1276, 1278, 1264, 1247, 1254, + /* 350 */ 1290, 1280, 1259, 1170, 1286, 1209, 1287, 1288, 1304, 1309, + /* 360 */ 1210, 1291, 1246, 1248, 1294, 1193, 1211, 1298, 1227, 1207, + /* 370 */ 1307, 1212, 1305, 1213, 1215, 1217, 1221, 1202, 1218, 1219, + /* 380 */ 1313, 1203, 1314, 1315, 1319, 1281, 1201, 1204, 1336, 1320, }; -#define YY_REDUCE_USE_DFLT (-165) +#define YY_REDUCE_USE_DFLT (-218) #define YY_REDUCE_MAX 291 static const short yy_reduce_ofst[] = { - /* 0 */ -138, 806, 503, 667, 190, -21, 44, 36, 38, 430, - /* 10 */ -141, 274, 91, 337, 271, 276, -126, 546, 285, 151, - /* 20 */ 180, -13, 283, 86, 86, 86, 86, 86, 86, 86, - /* 30 */ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - /* 40 */ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - /* 50 */ 86, 86, 86, 86, 86, 824, 831, 855, 858, 882, - /* 60 */ 893, 896, 920, 948, 962, 968, 972, 976, 978, 988, - /* 70 */ 996, 1012, 1015, 1036, 1041, 1044, 1056, 1061, 1068, 1070, - /* 80 */ 1074, 1076, 1081, 1085, 1087, 1094, 1100, 1102, 1105, 1114, - /* 90 */ 1118, 1120, 1126, 1129, 1132, 1138, 86, 86, 86, 86, - /* 100 */ 20, 86, 86, 23, 507, 594, 595, 636, 640, 684, - /* 110 */ 177, 541, 86, 200, 86, 86, 86, 86, 412, -164, - /* 120 */ -115, 368, 136, 136, 552, -6, 207, 573, 152, -90, - /* 130 */ 209, 475, 295, 728, 730, 736, 843, 859, 860, 715, - /* 140 */ 861, 29, 325, 724, 745, 753, 582, 668, 713, 83, - /* 150 */ 120, 0, 199, 256, 312, 156, 363, 156, 156, 349, - /* 160 */ 424, 440, 457, 486, 496, 526, 642, 634, 486, 716, - /* 170 */ 710, 774, 805, 737, 811, 817, 156, 737, 833, 845, - /* 180 */ 826, 872, 876, 890, 917, 156, 925, 936, 156, 941, - /* 190 */ 866, 877, 977, 983, 156, 987, 992, 993, 156, 1017, - /* 200 */ 1028, 1032, 156, 156, 1039, 1065, 1072, 1086, 1088, 984, - /* 210 */ 1016, 1031, 1075, 1013, 1024, 1025, 1090, 1108, 1109, 1082, - /* 220 */ 1110, 1116, 1119, 1117, 1113, 1098, 1099, 1151, 1157, 1158, - /* 230 */ 1159, 1152, 1121, 1122, 1123, 1124, 1115, 1125, 1097, 1174, - /* 240 */ 1175, 1127, 1128, 1130, 1131, 1161, 1164, 1149, 1166, 1165, - /* 250 */ 1168, 1169, 1133, 1134, 1163, 1176, 1177, 1178, 1171, 1199, - /* 260 */ 1201, 1203, 1204, 1206, 1211, 1212, 1135, 1136, 1214, 1215, - /* 270 */ 1182, 1184, 1144, 1179, 1218, 1185, 1189, 1190, 1191, 1180, - /* 280 */ 1197, 1148, 1223, 1142, 1145, 1231, 1232, 1146, 1228, 1160, - /* 290 */ 1147, 1143, + /* 0 */ 307, 234, 68, 279, 346, 8, 228, 405, -74, 109, + /* 10 */ 349, 408, -7, 344, 333, 342, -216, 415, 353, 173, + /* 20 */ 98, 10, -55, -60, -60, -60, -60, -60, -60, -60, + /* 30 */ -60, -60, -60, -60, -60, -60, -60, -60, -60, -60, + /* 40 */ -60, -60, -60, -60, -60, -60, -60, -60, -60, -60, + /* 50 */ -60, -60, -60, -60, -60, 471, 569, 612, 655, 712, + /* 60 */ 714, 716, 721, 724, 731, 740, 748, 755, 757, 769, + /* 70 */ 794, 806, 808, 825, 855, 858, 860, 875, 879, 402, + /* 80 */ 884, 894, 896, 900, 903, 905, 920, 929, 934, 936, + /* 90 */ 945, 947, 953, 955, 963, 965, -60, -60, -60, -60, + /* 100 */ 520, -60, -60, 70, 455, 510, 502, 552, 239, 593, + /* 110 */ 596, 597, -60, 427, -60, -60, -60, -60, 219, 449, + /* 120 */ 943, -107, 874, 874, 937, 935, 966, 927, 956, 859, + /* 130 */ 962, 954, 932, 950, 933, 890, 889, 785, 722, 409, + /* 140 */ 840, 812, 690, 803, 849, 862, 745, 906, 869, -145, + /* 150 */ -87, 26, -2, 65, 130, 181, 187, 150, 374, 150, + /* 160 */ 150, 437, 495, 511, 584, 150, 595, 627, 676, 150, + /* 170 */ 495, 699, 762, 782, 824, 856, 861, 747, 187, 150, + /* 180 */ 864, 885, 887, 899, 915, 979, 150, 983, 829, 984, + /* 190 */ 989, 150, 990, 992, 994, 997, 913, 784, 1000, 150, + /* 200 */ 1001, 1002, 1004, 1005, 150, 964, 1006, 995, 985, 987, + /* 210 */ 999, 988, 991, 996, 971, 967, 998, 972, 1007, 1008, + /* 220 */ -217, 938, 941, 977, 1016, 939, 1009, 942, 1032, 1031, + /* 230 */ 1033, 1038, 951, 1041, 1043, 1037, 957, 1040, 981, 1010, + /* 240 */ 1003, 1011, 1012, 1013, 1014, 1020, 1015, 1024, 1026, 1027, + /* 250 */ 1028, 1055, 1022, 1017, 1034, 1035, 1065, 1070, 1018, 1019, + /* 260 */ 1046, 1074, 1077, 1079, 1083, 1084, 1086, 1087, 1090, 1054, + /* 270 */ 1061, 1062, 1091, 1063, 1042, 1044, 1066, 1047, 1045, 1021, + /* 280 */ 1029, 1078, 1088, 1089, 1094, 1095, 1025, 1098, 1096, 1097, + /* 290 */ 1030, 1023, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 594, 819, 900, 709, 900, 819, 900, 900, 846, 713, - /* 10 */ 875, 817, 900, 900, 900, 900, 791, 900, 846, 900, + /* 0 */ 594, 819, 900, 709, 900, 900, 819, 900, 846, 713, + /* 10 */ 875, 900, 817, 900, 900, 900, 791, 900, 846, 900, /* 20 */ 625, 846, 846, 742, 900, 900, 900, 900, 900, 900, - /* 30 */ 900, 900, 743, 900, 821, 816, 812, 814, 813, 820, - /* 40 */ 744, 733, 740, 747, 725, 859, 749, 750, 756, 757, - /* 50 */ 876, 874, 779, 778, 797, 900, 900, 900, 900, 900, + /* 30 */ 900, 900, 757, 744, 749, 820, 816, 876, 874, 750, + /* 40 */ 813, 859, 821, 743, 756, 733, 812, 900, 740, 747, + /* 50 */ 725, 814, 779, 778, 797, 900, 900, 900, 900, 900, /* 60 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, /* 70 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, /* 80 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, /* 90 */ 900, 900, 900, 900, 900, 900, 781, 803, 780, 790, - /* 100 */ 618, 782, 783, 678, 613, 900, 900, 900, 900, 900, + /* 100 */ 618, 782, 783, 613, 678, 900, 900, 900, 900, 900, /* 110 */ 900, 900, 784, 900, 785, 798, 799, 800, 900, 900, - /* 120 */ 900, 900, 900, 900, 594, 709, 900, 709, 900, 900, - /* 130 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 140 */ 900, 900, 900, 900, 900, 900, 703, 713, 893, 900, - /* 150 */ 900, 900, 900, 669, 900, 900, 900, 900, 900, 900, - /* 160 */ 900, 900, 900, 900, 601, 599, 900, 701, 900, 900, - /* 170 */ 627, 900, 900, 711, 900, 900, 716, 717, 900, 900, - /* 180 */ 900, 900, 900, 900, 900, 615, 900, 900, 690, 900, - /* 190 */ 852, 900, 900, 900, 866, 900, 900, 900, 864, 900, - /* 200 */ 900, 900, 692, 752, 833, 900, 879, 881, 900, 900, - /* 210 */ 701, 710, 900, 900, 900, 815, 736, 736, 736, 648, - /* 220 */ 736, 900, 736, 900, 651, 746, 746, 598, 598, 598, - /* 230 */ 598, 668, 900, 746, 737, 739, 729, 741, 900, 718, - /* 240 */ 718, 726, 728, 726, 728, 680, 680, 665, 680, 651, - /* 250 */ 680, 825, 830, 830, 665, 680, 680, 680, 825, 610, - /* 260 */ 718, 610, 718, 610, 718, 718, 856, 858, 610, 718, - /* 270 */ 682, 682, 758, 746, 718, 689, 689, 689, 689, 746, - /* 280 */ 682, 758, 718, 878, 878, 718, 718, 886, 635, 861, - /* 290 */ 893, 898, 900, 900, 900, 900, 900, 900, 900, 900, - /* 300 */ 900, 900, 900, 765, 900, 900, 900, 900, 900, 900, - /* 310 */ 900, 900, 900, 900, 900, 900, 900, 839, 900, 900, - /* 320 */ 900, 900, 770, 766, 900, 767, 900, 695, 900, 900, - /* 330 */ 900, 900, 900, 900, 900, 900, 900, 900, 818, 900, - /* 340 */ 730, 900, 738, 900, 900, 900, 900, 900, 900, 900, - /* 350 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 360 */ 900, 900, 900, 900, 900, 900, 900, 854, 855, 900, - /* 370 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 380 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 390 */ 900, 885, 900, 900, 888, 595, 900, 589, 592, 591, - /* 400 */ 593, 597, 600, 622, 623, 624, 602, 603, 604, 605, - /* 410 */ 606, 607, 608, 614, 616, 634, 636, 620, 638, 699, - /* 420 */ 700, 762, 693, 694, 698, 621, 773, 764, 768, 769, - /* 430 */ 771, 772, 786, 787, 789, 795, 802, 805, 788, 793, - /* 440 */ 794, 796, 801, 804, 696, 697, 808, 628, 629, 632, - /* 450 */ 633, 842, 844, 843, 845, 631, 630, 774, 777, 810, - /* 460 */ 811, 867, 868, 869, 870, 871, 806, 719, 809, 792, - /* 470 */ 731, 734, 735, 732, 702, 712, 721, 722, 723, 724, - /* 480 */ 707, 708, 714, 727, 760, 761, 715, 704, 705, 706, - /* 490 */ 807, 763, 775, 776, 639, 640, 770, 641, 642, 643, - /* 500 */ 681, 684, 685, 686, 644, 663, 666, 667, 645, 647, - /* 510 */ 659, 660, 661, 662, 657, 658, 826, 827, 831, 829, - /* 520 */ 828, 664, 637, 626, 619, 670, 673, 674, 675, 676, - /* 530 */ 677, 679, 671, 672, 617, 609, 611, 720, 848, 857, - /* 540 */ 853, 849, 850, 851, 612, 822, 823, 683, 754, 755, - /* 550 */ 847, 860, 862, 759, 863, 865, 890, 687, 688, 691, - /* 560 */ 832, 872, 745, 748, 751, 753, 834, 835, 836, 837, - /* 570 */ 840, 841, 838, 873, 877, 880, 882, 883, 884, 887, - /* 580 */ 889, 894, 895, 896, 899, 897, 596, 590, + /* 120 */ 900, 900, 900, 900, 900, 900, 900, 709, 900, 900, + /* 130 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 594, + /* 140 */ 709, 900, 900, 900, 900, 900, 893, 713, 703, 900, + /* 150 */ 669, 900, 900, 900, 900, 900, 900, 900, 900, 900, + /* 160 */ 900, 900, 711, 833, 900, 752, 881, 900, 900, 716, + /* 170 */ 717, 900, 900, 900, 900, 900, 879, 601, 900, 692, + /* 180 */ 900, 900, 900, 900, 599, 900, 864, 900, 627, 900, + /* 190 */ 900, 866, 900, 900, 900, 900, 900, 852, 900, 690, + /* 200 */ 900, 900, 900, 900, 615, 701, 900, 900, 736, 736, + /* 210 */ 900, 651, 736, 736, 710, 701, 648, 746, 736, 900, + /* 220 */ 815, 900, 900, 746, 900, 856, 680, 886, 598, 718, + /* 230 */ 718, 598, 878, 598, 598, 668, 878, 718, 758, 900, + /* 240 */ 746, 737, 739, 729, 741, 682, 746, 689, 689, 689, + /* 250 */ 689, 718, 746, 758, 682, 682, 718, 610, 900, 858, + /* 260 */ 665, 718, 718, 610, 718, 718, 610, 718, 610, 825, + /* 270 */ 680, 680, 718, 680, 726, 728, 665, 726, 728, 830, + /* 280 */ 830, 825, 680, 680, 651, 680, 861, 635, 653, 653, + /* 290 */ 893, 898, 900, 900, 900, 900, 900, 839, 900, 765, + /* 300 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, + /* 310 */ 900, 900, 900, 900, 900, 900, 900, 595, 900, 900, + /* 320 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, + /* 330 */ 900, 738, 900, 900, 900, 730, 900, 900, 900, 900, + /* 340 */ 818, 900, 900, 900, 900, 900, 900, 900, 900, 854, + /* 350 */ 900, 855, 900, 900, 900, 900, 900, 900, 900, 900, + /* 360 */ 900, 900, 900, 900, 900, 900, 695, 900, 900, 900, + /* 370 */ 900, 900, 900, 767, 900, 900, 900, 900, 766, 770, + /* 380 */ 900, 900, 900, 900, 900, 885, 900, 900, 900, 888, + /* 390 */ 639, 835, 836, 609, 837, 840, 611, 792, 809, 719, + /* 400 */ 841, 636, 806, 896, 871, 870, 869, 868, 838, 634, + /* 410 */ 616, 720, 867, 614, 848, 899, 811, 608, 873, 857, + /* 420 */ 853, 607, 606, 877, 849, 850, 605, 851, 612, 604, + /* 430 */ 810, 603, 777, 602, 774, 624, 880, 640, 822, 823, + /* 440 */ 623, 630, 631, 845, 843, 844, 683, 754, 755, 847, + /* 450 */ 622, 860, 842, 633, 882, 632, 629, 897, 600, 628, + /* 460 */ 647, 862, 589, 686, 808, 597, 697, 696, 883, 770, + /* 470 */ 759, 804, 801, 663, 796, 641, 593, 794, 863, 646, + /* 480 */ 685, 793, 788, 865, 884, 805, 802, 887, 795, 890, + /* 490 */ 642, 789, 787, 687, 644, 688, 652, 786, 691, 772, + /* 500 */ 771, 832, 769, 768, 872, 591, 667, 889, 764, 745, + /* 510 */ 773, 621, 596, 698, 694, 748, 592, 656, 659, 660, + /* 520 */ 661, 662, 693, 657, 763, 658, 807, 775, 826, 706, + /* 530 */ 762, 705, 827, 704, 831, 829, 715, 894, 828, 649, + /* 540 */ 761, 650, 760, 664, 637, 626, 619, 727, 655, 670, + /* 550 */ 895, 673, 590, 700, 714, 708, 645, 707, 674, 751, + /* 560 */ 724, 654, 666, 675, 684, 723, 722, 721, 676, 753, + /* 570 */ 699, 712, 776, 834, 702, 643, 638, 681, 620, 677, + /* 580 */ 679, 671, 672, 617, 732, 735, 734, 731, }; #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) @@ -71061,7 +71115,7 @@ SQLITE_PRIVATE void sqlite3Parser( ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -71114,7 +71168,7 @@ const unsigned char ebcdicToAscii[] = { ** ** The code in this file has been automatically generated by ** -** $Header: /cvsroot/mozilla/db/sqlite3/src/sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Header: /cvsroot/mozilla/db/sqlite3/src/sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ ** ** The code in this file implements a function that determines whether ** or not a given identifier is really an SQL keyword. The same thing @@ -71137,8 +71191,8 @@ static int keywordCode(const char *z, int n){ "YIFINTOFFSETISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUM" "VIEWINITIALLY"; static const unsigned char aHash[127] = { - 63, 92, 109, 61, 0, 38, 0, 0, 69, 0, 64, 0, 0, - 102, 4, 65, 7, 0, 108, 72, 103, 99, 0, 22, 0, 0, + 63, 92, 109, 61, 0, 39, 0, 0, 69, 0, 64, 0, 0, + 101, 4, 65, 7, 0, 108, 72, 103, 99, 0, 22, 0, 0, 113, 0, 111, 106, 0, 18, 80, 0, 1, 0, 0, 56, 57, 0, 55, 11, 0, 33, 77, 89, 0, 110, 88, 0, 0, 45, 0, 90, 54, 0, 20, 0, 114, 34, 19, 0, 10, 97, 28, @@ -71152,22 +71206,22 @@ static int keywordCode(const char *z, int n){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, - 17, 0, 0, 0, 36, 39, 0, 0, 25, 0, 0, 31, 0, + 17, 0, 0, 0, 36, 38, 0, 0, 25, 0, 0, 31, 0, 0, 0, 43, 52, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 26, 0, 8, 46, - 2, 0, 0, 0, 0, 0, 0, 0, 3, 58, 66, 0, 13, - 0, 91, 85, 0, 94, 0, 74, 0, 0, 62, 0, 35, 101, + 3, 0, 0, 0, 0, 0, 0, 0, 2, 58, 66, 0, 13, + 0, 91, 85, 0, 94, 0, 74, 0, 0, 0, 62, 35, 102, 0, 0, 105, 23, 30, 60, 70, 0, 0, 59, 0, 0, }; static const unsigned char aLen[116] = { - 6, 7, 3, 6, 6, 7, 7, 3, 4, 6, 4, 5, 3, + 6, 3, 7, 6, 6, 7, 7, 3, 4, 6, 4, 5, 3, 10, 9, 5, 4, 4, 3, 8, 2, 6, 11, 2, 7, 5, - 5, 4, 6, 7, 10, 6, 5, 6, 6, 5, 6, 4, 9, + 5, 4, 6, 7, 10, 6, 5, 6, 6, 5, 6, 9, 4, 2, 5, 5, 7, 5, 9, 6, 7, 7, 3, 4, 4, 7, 3, 10, 4, 7, 6, 12, 6, 6, 9, 4, 6, 5, 4, 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, - 2, 4, 4, 4, 4, 4, 2, 2, 4, 6, 2, 3, 6, + 2, 4, 4, 4, 4, 4, 2, 2, 4, 2, 6, 3, 6, 5, 8, 5, 5, 8, 3, 5, 5, 6, 4, 9, 3, }; static const unsigned short int aOffset[116] = { @@ -71182,7 +71236,7 @@ static int keywordCode(const char *z, int n){ 464, 468, 476, 480, 485, 493, 496, 501, 506, 512, 516, 521, }; static const unsigned char aCode[116] = { - TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_LIKE_KW, + TK_BEFORE, TK_FOR, TK_FOREIGN, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, TK_ADD, TK_DESC, TK_ESCAPE, TK_EACH, TK_CHECK, TK_KEY, TK_CONSTRAINT, TK_INTERSECT, TK_TABLE, TK_JOIN_KW, TK_THEN, TK_END, TK_DATABASE, @@ -71202,7 +71256,7 @@ static int keywordCode(const char *z, int n){ TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, TK_BY, TK_IF, TK_INTO, - TK_OFFSET, TK_OF, TK_SET, TK_ISNULL, TK_ORDER, + TK_OF, TK_OFFSET, TK_SET, TK_ISNULL, TK_ORDER, TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, @@ -71577,7 +71631,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; - if( i>SQLITE_MAX_SQL_LENGTH ){ + if( SQLITE_MAX_SQL_LENGTH>0 && i>SQLITE_MAX_SQL_LENGTH ){ pParse->rc = SQLITE_TOOBIG; break; } @@ -71686,7 +71740,7 @@ abort_parse: ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ #ifndef SQLITE_OMIT_COMPLETE @@ -71957,7 +72011,7 @@ SQLITE_API int sqlite3_complete16(const void *zSql){ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ +** $Id: sqlite3.c,v 1.12 2008/01/22 13:54:06 mozilla%weilbacher.org Exp $ */ /* @@ -73426,40506 +73480,3 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo } /************** End of main.c ************************************************/ -/****************************************************************************** -** This file is an amalgamation of separate C source files from the SQLite -** Full Text Search extension 2 (fts3). 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. It also -** makes the code easier to import into other projects. -** -** This amalgamation was generated on 2007-12-14 17:40:57 UTC. -*/ -/************** Begin file fts3.c ********************************************/ -/* -** 2006 Oct 10 -** -** 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 is an SQLite module implementing full-text search. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ - -/* TODO(shess) Consider exporting this comment to an HTML file or the -** wiki. -*/ -/* The full-text index is stored in a series of b+tree (-like) -** structures called segments which map terms to doclists. The -** structures are like b+trees in layout, but are constructed from the -** bottom up in optimal fashion and are not updatable. Since trees -** are built from the bottom up, things will be described from the -** bottom up. -** -** -**** Varints **** -** The basic unit of encoding is a variable-length integer called a -** varint. We encode variable-length integers in little-endian order -** using seven bits * per byte as follows: -** -** KEY: -** A = 0xxxxxxx 7 bits of data and one flag bit -** B = 1xxxxxxx 7 bits of data and one flag bit -** -** 7 bits - A -** 14 bits - BA -** 21 bits - BBA -** and so on. -** -** This is identical to how sqlite encodes varints (see util.c). -** -** -**** Document lists **** -** A doclist (document list) holds a docid-sorted list of hits for a -** given term. Doclists hold docids, and can optionally associate -** token positions and offsets with docids. -** -** A DL_POSITIONS_OFFSETS doclist is stored like this: -** -** array { -** varint docid; -** array { (position list for column 0) -** varint position; (delta from previous position plus POS_BASE) -** varint startOffset; (delta from previous startOffset) -** varint endOffset; (delta from startOffset) -** } -** array { -** varint POS_COLUMN; (marks start of position list for new column) -** varint column; (index of new column) -** array { -** varint position; (delta from previous position plus POS_BASE) -** varint startOffset;(delta from previous startOffset) -** varint endOffset; (delta from startOffset) -** } -** } -** varint POS_END; (marks end of positions for this document. -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. A "position" is an index of a token in the token stream -** generated by the tokenizer, while an "offset" is a byte offset, -** both based at 0. Note that POS_END and POS_COLUMN occur in the -** same logical place as the position element, and act as sentinals -** ending a position list array. -** -** A DL_POSITIONS doclist omits the startOffset and endOffset -** information. A DL_DOCIDS doclist omits both the position and -** offset information, becoming an array of varint-encoded docids. -** -** On-disk data is stored as type DL_DEFAULT, so we don't serialize -** the type. Due to how deletion is implemented in the segmentation -** system, on-disk doclists MUST store at least positions. -** -** -**** Segment leaf nodes **** -** Segment leaf nodes store terms and doclists, ordered by term. Leaf -** nodes are written using LeafWriter, and read using LeafReader (to -** iterate through a single leaf node's data) and LeavesReader (to -** iterate through a segment's entire leaf layer). Leaf nodes have -** the format: -** -** varint iHeight; (height from leaf level, always 0) -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of prefix shared with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix];(unshared suffix of next term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. -** -** Leaf nodes are broken into blocks which are stored contiguously in -** the %_segments table in sorted order. This means that when the end -** of a node is reached, the next term is in the node with the next -** greater node id. -** -** New data is spilled to a new leaf node when the current node -** exceeds LEAF_MAX bytes (default 2048). New data which itself is -** larger than STANDALONE_MIN (default 1024) is placed in a standalone -** node (a leaf node with a single term and doclist). The goal of -** these settings is to pack together groups of small doclists while -** making it efficient to directly access large doclists. The -** assumption is that large doclists represent terms which are more -** likely to be query targets. -** -** TODO(shess) It may be useful for blocking decisions to be more -** dynamic. For instance, it may make more sense to have a 2.5k leaf -** node rather than splitting into 2k and .5k nodes. My intuition is -** that this might extend through 2x or 4x the pagesize. -** -** -**** Segment interior nodes **** -** Segment interior nodes store blockids for subtree nodes and terms -** to describe what data is stored by the each subtree. Interior -** nodes are written using InteriorWriter, and read using -** InteriorReader. InteriorWriters are created as needed when -** SegmentWriter creates new leaf nodes, or when an interior node -** itself grows too big and must be split. The format of interior -** nodes: -** -** varint iHeight; (height from leaf level, always >0) -** varint iBlockid; (block id of node's leftmost subtree) -** optional { -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of shared prefix with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix]; (unshared suffix of next term) -** } -** } -** -** Here, optional { X } means an optional element, while array { X } -** means zero or more occurrences of X, adjacent in memory. -** -** An interior node encodes n terms separating n+1 subtrees. The -** subtree blocks are contiguous, so only the first subtree's blockid -** is encoded. The subtree at iBlockid will contain all terms less -** than the first term encoded (or all terms if no term is encoded). -** Otherwise, for terms greater than or equal to pTerm[i] but less -** than pTerm[i+1], the subtree for that term will be rooted at -** iBlockid+i. Interior nodes only store enough term data to -** distinguish adjacent children (if the rightmost term of the left -** child is "something", and the leftmost term of the right child is -** "wicked", only "w" is stored). -** -** New data is spilled to a new interior node at the same height when -** the current node exceeds INTERIOR_MAX bytes (default 2048). -** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing -** interior nodes and making the tree too skinny. The interior nodes -** at a given height are naturally tracked by interior nodes at -** height+1, and so on. -** -** -**** Segment directory **** -** The segment directory in table %_segdir stores meta-information for -** merging and deleting segments, and also the root node of the -** segment's tree. -** -** The root node is the top node of the segment's tree after encoding -** the entire segment, restricted to ROOT_MAX bytes (default 1024). -** This could be either a leaf node or an interior node. If the top -** node requires more than ROOT_MAX bytes, it is flushed to %_segments -** and a new root interior node is generated (which should always fit -** within ROOT_MAX because it only needs space for 2 varints, the -** height and the blockid of the previous root). -** -** The meta-information in the segment directory is: -** level - segment level (see below) -** idx - index within level -** - (level,idx uniquely identify a segment) -** start_block - first leaf node -** leaves_end_block - last leaf node -** end_block - last block (including interior nodes) -** root - contents of root node -** -** If the root node is a leaf node, then start_block, -** leaves_end_block, and end_block are all 0. -** -** -**** Segment merging **** -** To amortize update costs, segments are groups into levels and -** merged in matches. Each increase in level represents exponentially -** more documents. -** -** New documents (actually, document updates) are tokenized and -** written individually (using LeafWriter) to a level 0 segment, with -** incrementing idx. When idx reaches MERGE_COUNT (default 16), all -** level 0 segments are merged into a single level 1 segment. Level 1 -** is populated like level 0, and eventually MERGE_COUNT level 1 -** segments are merged to a single level 2 segment (representing -** MERGE_COUNT^2 updates), and so on. -** -** A segment merge traverses all segments at a given level in -** parallel, performing a straightforward sorted merge. Since segment -** leaf nodes are written in to the %_segments table in order, this -** merge traverses the underlying sqlite disk structures efficiently. -** After the merge, all segment blocks from the merged level are -** deleted. -** -** MERGE_COUNT controls how often we merge segments. 16 seems to be -** somewhat of a sweet spot for insertion performance. 32 and 64 show -** very similar performance numbers to 16 on insertion, though they're -** a tiny bit slower (perhaps due to more overhead in merge-time -** sorting). 8 is about 20% slower than 16, 4 about 50% slower than -** 16, 2 about 66% slower than 16. -** -** At query time, high MERGE_COUNT increases the number of segments -** which need to be scanned and merged. For instance, with 100k docs -** inserted: -** -** MERGE_COUNT segments -** 16 25 -** 8 12 -** 4 10 -** 2 6 -** -** This appears to have only a moderate impact on queries for very -** frequent terms (which are somewhat dominated by segment merge -** costs), and infrequent and non-existent terms still seem to be fast -** even with many segments. -** -** TODO(shess) That said, it would be nice to have a better query-side -** argument for MERGE_COUNT of 16. Also, it is possible/likely that -** optimizations to things like doclist merging will swing the sweet -** spot around. -** -** -** -**** Handling of deletions and updates **** -** Since we're using a segmented structure, with no docid-oriented -** index into the term index, we clearly cannot simply update the term -** index when a document is deleted or updated. For deletions, we -** write an empty doclist (varint(docid) varint(POS_END)), for updates -** we simply write the new doclist. Segment merges overwrite older -** data for a particular docid with newer data, so deletes or updates -** will eventually overtake the earlier data and knock it out. The -** query logic likewise merges doclists so that newer data knocks out -** older data. -** -** TODO(shess) Provide a VACUUM type operation to clear out all -** deletions and duplications. This would basically be a forced merge -** into a single segment. -*/ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) -# define SQLITE_CORE 1 -#endif - -#include -#include -#include -#include -#include - -/************** Include fts3.h in the middle of fts3.c ***********************/ -/************** Begin file fts3.h ********************************************/ -/* -** 2006 Oct 10 -** -** 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 header file is used by programs that want to link against the -** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. -*/ -/************** Include sqlite3.h in the middle of fts3.h ********************/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ -#include /* Needed for the definition of va_list */ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3.h ***********************/ - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -int sqlite3Fts3Init(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - -/************** End of fts3.h ************************************************/ -/************** Continuing where we left off in fts3.c ***********************/ -/************** Include fts3_hash.h in the middle of fts3.c ******************/ -/************** Begin file fts3_hash.h ***************************************/ -/* -** 2001 September 22 -** -** 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 is the header file for the generic hash-table implemenation -** used in SQLite. We've modified it slightly to serve as a standalone -** hash table implementation for the full-text indexing module. -** -*/ -#ifndef _FTS3_HASH_H_ -#define _FTS3_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct fts3Hash fts3Hash; -typedef struct fts3HashElem fts3HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct fts3Hash { - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - fts3HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _fts3ht { /* the hash table */ - int count; /* Number of entries with this hash */ - fts3HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct fts3HashElem { - fts3HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 2 different modes of operation for a hash table: -** -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is respected in comparisons. -** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. -*/ -#define FTS3_HASH_STRING 1 -#define FTS3_HASH_BINARY 2 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -void sqlite3Fts3HashInit(fts3Hash*, int keytype, int copyKey); -void *sqlite3Fts3HashInsert(fts3Hash*, const void *pKey, int nKey, void *pData); -void *sqlite3Fts3HashFind(const fts3Hash*, const void *pKey, int nKey); -void sqlite3Fts3HashClear(fts3Hash*); - -/* -** Shorthand for the functions above -*/ -#define fts3HashInit sqlite3Fts3HashInit -#define fts3HashInsert sqlite3Fts3HashInsert -#define fts3HashFind sqlite3Fts3HashFind -#define fts3HashClear sqlite3Fts3HashClear - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** fts3Hash h; -** fts3HashElem *p; -** ... -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ -** SomeStructure *pData = fts3HashData(p); -** // do something with pData -** } -*/ -#define fts3HashFirst(H) ((H)->first) -#define fts3HashNext(E) ((E)->next) -#define fts3HashData(E) ((E)->data) -#define fts3HashKey(E) ((E)->pKey) -#define fts3HashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define fts3HashCount(H) ((H)->count) - -#endif /* _FTS3_HASH_H_ */ - -/************** End of fts3_hash.h *******************************************/ -/************** Continuing where we left off in fts3.c ***********************/ -/************** Include fts3_tokenizer.h in the middle of fts3.c *************/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -/************** Include sqlite3.h in the middle of fts3_tokenizer.h **********/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3_tokenizer.h *************/ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialised by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3.c ***********************/ -#ifndef SQLITE_CORE - #include "sqlite3ext.h" - SQLITE_EXTENSION_INIT1 -#endif - - -/* TODO(shess) MAN, this thing needs some refactoring. At minimum, it -** would be nice to order the file better, perhaps something along the -** lines of: -** -** - utility functions -** - table setup functions -** - table update functions -** - table query functions -** -** Put the query functions last because they're likely to reference -** typedefs or functions from the table update section. -*/ - -#if 0 -# define FTSTRACE(A) printf A; fflush(stdout) -#else -# define FTSTRACE(A) -#endif - -/* -** Default span for NEAR operators. -*/ -#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10 - -/* It is not safe to call isspace(), tolower(), or isalnum() on -** hi-bit-set characters. This is the same solution used in the -** tokenizer. -*/ -/* TODO(shess) The snippet-generation code should be using the -** tokenizer-generated tokens rather than doing its own local -** tokenization. -*/ -/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ -static int safe_isspace(char c){ - return (c&0x80)==0 ? isspace(c) : 0; -} -static int safe_tolower(char c){ - return (c&0x80)==0 ? tolower(c) : c; -} -static int safe_isalnum(char c){ - return (c&0x80)==0 ? isalnum(c) : 0; -} - -typedef enum DocListType { - DL_DOCIDS, /* docids only */ - DL_POSITIONS, /* docids + positions */ - DL_POSITIONS_OFFSETS /* docids + positions + offsets */ -} DocListType; - -/* -** By default, only positions and not offsets are stored in the doclists. -** To change this so that offsets are stored too, compile with -** -** -DDL_DEFAULT=DL_POSITIONS_OFFSETS -** -** If DL_DEFAULT is set to DL_DOCIDS, your table can only be inserted -** into (no deletes or updates). -*/ -#ifndef DL_DEFAULT -# define DL_DEFAULT DL_POSITIONS -#endif - -enum { - POS_END = 0, /* end of this position list */ - POS_COLUMN, /* followed by new column number */ - POS_BASE -}; - -/* MERGE_COUNT controls how often we merge segments (see comment at -** top of file). -*/ -#define MERGE_COUNT 16 - -/* utility functions */ - -/* CLEAR() and SCRAMBLE() abstract memset() on a pointer to a single -** record to prevent errors of the form: -** -** my_function(SomeType *b){ -** memset(b, '\0', sizeof(b)); // sizeof(b)!=sizeof(*b) -** } -*/ -/* TODO(shess) Obvious candidates for a header file. */ -#define CLEAR(b) memset(b, '\0', sizeof(*(b))) - -#ifndef NDEBUG -# define SCRAMBLE(b) memset(b, 0x55, sizeof(*(b))) -#else -# define SCRAMBLE(b) -#endif - -/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */ -#define VARINT_MAX 10 - -/* Write a 64-bit variable-length integer to memory starting at p[0]. - * The length of data written will be between 1 and VARINT_MAX bytes. - * The number of bytes written is returned. */ -static int fts3PutVarint(char *p, sqlite_int64 v){ - unsigned char *q = (unsigned char *) p; - sqlite_uint64 vu = v; - do{ - *q++ = (unsigned char) ((vu & 0x7f) | 0x80); - vu >>= 7; - }while( vu!=0 ); - q[-1] &= 0x7f; /* turn off high bit in final byte */ - assert( q - (unsigned char *)p <= VARINT_MAX ); - return (int) (q - (unsigned char *)p); -} - -/* Read a 64-bit variable-length integer from memory starting at p[0]. - * Return the number of bytes read, or 0 on error. - * The value is stored in *v. */ -static int fts3GetVarint(const char *p, sqlite_int64 *v){ - const unsigned char *q = (const unsigned char *) p; - sqlite_uint64 x = 0, y = 1; - while( (*q & 0x80) == 0x80 ){ - x += y * (*q++ & 0x7f); - y <<= 7; - if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */ - assert( 0 ); - return 0; - } - } - x += y * (*q++); - *v = (sqlite_int64) x; - return (int) (q - (unsigned char *)p); -} - -static int fts3GetVarint32(const char *p, int *pi){ - sqlite_int64 i; - int ret = fts3GetVarint(p, &i); - *pi = (int) i; - assert( *pi==i ); - return ret; -} - -/*******************************************************************/ -/* DataBuffer is used to collect data into a buffer in piecemeal -** fashion. It implements the usual distinction between amount of -** data currently stored (nData) and buffer capacity (nCapacity). -** -** dataBufferInit - create a buffer with given initial capacity. -** dataBufferReset - forget buffer's data, retaining capacity. -** dataBufferDestroy - free buffer's data. -** dataBufferSwap - swap contents of two buffers. -** dataBufferExpand - expand capacity without adding data. -** dataBufferAppend - append data. -** dataBufferAppend2 - append two pieces of data at once. -** dataBufferReplace - replace buffer's data. -*/ -typedef struct DataBuffer { - char *pData; /* Pointer to malloc'ed buffer. */ - int nCapacity; /* Size of pData buffer. */ - int nData; /* End of data loaded into pData. */ -} DataBuffer; - -static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){ - assert( nCapacity>=0 ); - pBuffer->nData = 0; - pBuffer->nCapacity = nCapacity; - pBuffer->pData = nCapacity==0 ? NULL : sqlite3_malloc(nCapacity); -} -static void dataBufferReset(DataBuffer *pBuffer){ - pBuffer->nData = 0; -} -static void dataBufferDestroy(DataBuffer *pBuffer){ - if( pBuffer->pData!=NULL ) sqlite3_free(pBuffer->pData); - SCRAMBLE(pBuffer); -} -static void dataBufferSwap(DataBuffer *pBuffer1, DataBuffer *pBuffer2){ - DataBuffer tmp = *pBuffer1; - *pBuffer1 = *pBuffer2; - *pBuffer2 = tmp; -} -static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){ - assert( nAddCapacity>0 ); - /* TODO(shess) Consider expanding more aggressively. Note that the - ** underlying malloc implementation may take care of such things for - ** us already. - */ - if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){ - pBuffer->nCapacity = pBuffer->nData+nAddCapacity; - pBuffer->pData = sqlite3_realloc(pBuffer->pData, pBuffer->nCapacity); - } -} -static void dataBufferAppend(DataBuffer *pBuffer, - const char *pSource, int nSource){ - assert( nSource>0 && pSource!=NULL ); - dataBufferExpand(pBuffer, nSource); - memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource); - pBuffer->nData += nSource; -} -static void dataBufferAppend2(DataBuffer *pBuffer, - const char *pSource1, int nSource1, - const char *pSource2, int nSource2){ - assert( nSource1>0 && pSource1!=NULL ); - assert( nSource2>0 && pSource2!=NULL ); - dataBufferExpand(pBuffer, nSource1+nSource2); - memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1); - memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2); - pBuffer->nData += nSource1+nSource2; -} -static void dataBufferReplace(DataBuffer *pBuffer, - const char *pSource, int nSource){ - dataBufferReset(pBuffer); - dataBufferAppend(pBuffer, pSource, nSource); -} - -/* StringBuffer is a null-terminated version of DataBuffer. */ -typedef struct StringBuffer { - DataBuffer b; /* Includes null terminator. */ -} StringBuffer; - -static void initStringBuffer(StringBuffer *sb){ - dataBufferInit(&sb->b, 100); - dataBufferReplace(&sb->b, "", 1); -} -static int stringBufferLength(StringBuffer *sb){ - return sb->b.nData-1; -} -static char *stringBufferData(StringBuffer *sb){ - return sb->b.pData; -} -static void stringBufferDestroy(StringBuffer *sb){ - dataBufferDestroy(&sb->b); -} - -static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){ - assert( sb->b.nData>0 ); - if( nFrom>0 ){ - sb->b.nData--; - dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1); - } -} -static void append(StringBuffer *sb, const char *zFrom){ - nappend(sb, zFrom, strlen(zFrom)); -} - -/* Append a list of strings separated by commas. */ -static void appendList(StringBuffer *sb, int nString, char **azString){ - int i; - for(i=0; i0 ) append(sb, ", "); - append(sb, azString[i]); - } -} - -static int endsInWhiteSpace(StringBuffer *p){ - return stringBufferLength(p)>0 && - safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]); -} - -/* If the StringBuffer ends in something other than white space, add a -** single space character to the end. -*/ -static void appendWhiteSpace(StringBuffer *p){ - if( stringBufferLength(p)==0 ) return; - if( !endsInWhiteSpace(p) ) append(p, " "); -} - -/* Remove white space from the end of the StringBuffer */ -static void trimWhiteSpace(StringBuffer *p){ - while( endsInWhiteSpace(p) ){ - p->b.pData[--p->b.nData-1] = '\0'; - } -} - -/*******************************************************************/ -/* DLReader is used to read document elements from a doclist. The -** current docid is cached, so dlrDocid() is fast. DLReader does not -** own the doclist buffer. -** -** dlrAtEnd - true if there's no more data to read. -** dlrDocid - docid of current document. -** dlrDocData - doclist data for current document (including docid). -** dlrDocDataBytes - length of same. -** dlrAllDataBytes - length of all remaining data. -** dlrPosData - position data for current document. -** dlrPosDataLen - length of pos data for current document (incl POS_END). -** dlrStep - step to current document. -** dlrInit - initial for doclist of given type against given data. -** dlrDestroy - clean up. -** -** Expected usage is something like: -** -** DLReader reader; -** dlrInit(&reader, pData, nData); -** while( !dlrAtEnd(&reader) ){ -** // calls to dlrDocid() and kin. -** dlrStep(&reader); -** } -** dlrDestroy(&reader); -*/ -typedef struct DLReader { - DocListType iType; - const char *pData; - int nData; - - sqlite_int64 iDocid; - int nElement; -} DLReader; - -static int dlrAtEnd(DLReader *pReader){ - assert( pReader->nData>=0 ); - return pReader->nData==0; -} -static sqlite_int64 dlrDocid(DLReader *pReader){ - assert( !dlrAtEnd(pReader) ); - return pReader->iDocid; -} -static const char *dlrDocData(DLReader *pReader){ - assert( !dlrAtEnd(pReader) ); - return pReader->pData; -} -static int dlrDocDataBytes(DLReader *pReader){ - assert( !dlrAtEnd(pReader) ); - return pReader->nElement; -} -static int dlrAllDataBytes(DLReader *pReader){ - assert( !dlrAtEnd(pReader) ); - return pReader->nData; -} -/* TODO(shess) Consider adding a field to track iDocid varint length -** to make these two functions faster. This might matter (a tiny bit) -** for queries. -*/ -static const char *dlrPosData(DLReader *pReader){ - sqlite_int64 iDummy; - int n = fts3GetVarint(pReader->pData, &iDummy); - assert( !dlrAtEnd(pReader) ); - return pReader->pData+n; -} -static int dlrPosDataLen(DLReader *pReader){ - sqlite_int64 iDummy; - int n = fts3GetVarint(pReader->pData, &iDummy); - assert( !dlrAtEnd(pReader) ); - return pReader->nElement-n; -} -static void dlrStep(DLReader *pReader){ - assert( !dlrAtEnd(pReader) ); - - /* Skip past current doclist element. */ - assert( pReader->nElement<=pReader->nData ); - pReader->pData += pReader->nElement; - pReader->nData -= pReader->nElement; - - /* If there is more data, read the next doclist element. */ - if( pReader->nData!=0 ){ - sqlite_int64 iDocidDelta; - int iDummy, n = fts3GetVarint(pReader->pData, &iDocidDelta); - pReader->iDocid += iDocidDelta; - if( pReader->iType>=DL_POSITIONS ){ - assert( nnData ); - while( 1 ){ - n += fts3GetVarint32(pReader->pData+n, &iDummy); - assert( n<=pReader->nData ); - if( iDummy==POS_END ) break; - if( iDummy==POS_COLUMN ){ - n += fts3GetVarint32(pReader->pData+n, &iDummy); - assert( nnData ); - }else if( pReader->iType==DL_POSITIONS_OFFSETS ){ - n += fts3GetVarint32(pReader->pData+n, &iDummy); - n += fts3GetVarint32(pReader->pData+n, &iDummy); - assert( nnData ); - } - } - } - pReader->nElement = n; - assert( pReader->nElement<=pReader->nData ); - } -} -static void dlrInit(DLReader *pReader, DocListType iType, - const char *pData, int nData){ - assert( pData!=NULL && nData!=0 ); - pReader->iType = iType; - pReader->pData = pData; - pReader->nData = nData; - pReader->nElement = 0; - pReader->iDocid = 0; - - /* Load the first element's data. There must be a first element. */ - dlrStep(pReader); -} -static void dlrDestroy(DLReader *pReader){ - SCRAMBLE(pReader); -} - -#ifndef NDEBUG -/* Verify that the doclist can be validly decoded. Also returns the -** last docid found because it is convenient in other assertions for -** DLWriter. -*/ -static void docListValidate(DocListType iType, const char *pData, int nData, - sqlite_int64 *pLastDocid){ - sqlite_int64 iPrevDocid = 0; - assert( nData>0 ); - assert( pData!=0 ); - assert( pData+nData>pData ); - while( nData!=0 ){ - sqlite_int64 iDocidDelta; - int n = fts3GetVarint(pData, &iDocidDelta); - iPrevDocid += iDocidDelta; - if( iType>DL_DOCIDS ){ - int iDummy; - while( 1 ){ - n += fts3GetVarint32(pData+n, &iDummy); - if( iDummy==POS_END ) break; - if( iDummy==POS_COLUMN ){ - n += fts3GetVarint32(pData+n, &iDummy); - }else if( iType>DL_POSITIONS ){ - n += fts3GetVarint32(pData+n, &iDummy); - n += fts3GetVarint32(pData+n, &iDummy); - } - assert( n<=nData ); - } - } - assert( n<=nData ); - pData += n; - nData -= n; - } - if( pLastDocid ) *pLastDocid = iPrevDocid; -} -#define ASSERT_VALID_DOCLIST(i, p, n, o) docListValidate(i, p, n, o) -#else -#define ASSERT_VALID_DOCLIST(i, p, n, o) assert( 1 ) -#endif - -/*******************************************************************/ -/* DLWriter is used to write doclist data to a DataBuffer. DLWriter -** always appends to the buffer and does not own it. -** -** dlwInit - initialize to write a given type doclistto a buffer. -** dlwDestroy - clear the writer's memory. Does not free buffer. -** dlwAppend - append raw doclist data to buffer. -** dlwCopy - copy next doclist from reader to writer. -** dlwAdd - construct doclist element and append to buffer. -** Only apply dlwAdd() to DL_DOCIDS doclists (else use PLWriter). -*/ -typedef struct DLWriter { - DocListType iType; - DataBuffer *b; - sqlite_int64 iPrevDocid; -#ifndef NDEBUG - int has_iPrevDocid; -#endif -} DLWriter; - -static void dlwInit(DLWriter *pWriter, DocListType iType, DataBuffer *b){ - pWriter->b = b; - pWriter->iType = iType; - pWriter->iPrevDocid = 0; -#ifndef NDEBUG - pWriter->has_iPrevDocid = 0; -#endif -} -static void dlwDestroy(DLWriter *pWriter){ - SCRAMBLE(pWriter); -} -/* iFirstDocid is the first docid in the doclist in pData. It is -** needed because pData may point within a larger doclist, in which -** case the first item would be delta-encoded. -** -** iLastDocid is the final docid in the doclist in pData. It is -** needed to create the new iPrevDocid for future delta-encoding. The -** code could decode the passed doclist to recreate iLastDocid, but -** the only current user (docListMerge) already has decoded this -** information. -*/ -/* TODO(shess) This has become just a helper for docListMerge. -** Consider a refactor to make this cleaner. -*/ -static void dlwAppend(DLWriter *pWriter, - const char *pData, int nData, - sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ - sqlite_int64 iDocid = 0; - char c[VARINT_MAX]; - int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */ -#ifndef NDEBUG - sqlite_int64 iLastDocidDelta; -#endif - - /* Recode the initial docid as delta from iPrevDocid. */ - nFirstOld = fts3GetVarint(pData, &iDocid); - assert( nFirstOldiType==DL_DOCIDS) ); - nFirstNew = fts3PutVarint(c, iFirstDocid-pWriter->iPrevDocid); - - /* Verify that the incoming doclist is valid AND that it ends with - ** the expected docid. This is essential because we'll trust this - ** docid in future delta-encoding. - */ - ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta); - assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta ); - - /* Append recoded initial docid and everything else. Rest of docids - ** should have been delta-encoded from previous initial docid. - */ - if( nFirstOldb, c, nFirstNew, - pData+nFirstOld, nData-nFirstOld); - }else{ - dataBufferAppend(pWriter->b, c, nFirstNew); - } - pWriter->iPrevDocid = iLastDocid; -} -static void dlwCopy(DLWriter *pWriter, DLReader *pReader){ - dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), - dlrDocid(pReader), dlrDocid(pReader)); -} -static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){ - char c[VARINT_MAX]; - int n = fts3PutVarint(c, iDocid-pWriter->iPrevDocid); - - /* Docids must ascend. */ - assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid ); - assert( pWriter->iType==DL_DOCIDS ); - - dataBufferAppend(pWriter->b, c, n); - pWriter->iPrevDocid = iDocid; -#ifndef NDEBUG - pWriter->has_iPrevDocid = 1; -#endif -} - -/*******************************************************************/ -/* PLReader is used to read data from a document's position list. As -** the caller steps through the list, data is cached so that varints -** only need to be decoded once. -** -** plrInit, plrDestroy - create/destroy a reader. -** plrColumn, plrPosition, plrStartOffset, plrEndOffset - accessors -** plrAtEnd - at end of stream, only call plrDestroy once true. -** plrStep - step to the next element. -*/ -typedef struct PLReader { - /* These refer to the next position's data. nData will reach 0 when - ** reading the last position, so plrStep() signals EOF by setting - ** pData to NULL. - */ - const char *pData; - int nData; - - DocListType iType; - int iColumn; /* the last column read */ - int iPosition; /* the last position read */ - int iStartOffset; /* the last start offset read */ - int iEndOffset; /* the last end offset read */ -} PLReader; - -static int plrAtEnd(PLReader *pReader){ - return pReader->pData==NULL; -} -static int plrColumn(PLReader *pReader){ - assert( !plrAtEnd(pReader) ); - return pReader->iColumn; -} -static int plrPosition(PLReader *pReader){ - assert( !plrAtEnd(pReader) ); - return pReader->iPosition; -} -static int plrStartOffset(PLReader *pReader){ - assert( !plrAtEnd(pReader) ); - return pReader->iStartOffset; -} -static int plrEndOffset(PLReader *pReader){ - assert( !plrAtEnd(pReader) ); - return pReader->iEndOffset; -} -static void plrStep(PLReader *pReader){ - int i, n; - - assert( !plrAtEnd(pReader) ); - - if( pReader->nData==0 ){ - pReader->pData = NULL; - return; - } - - n = fts3GetVarint32(pReader->pData, &i); - if( i==POS_COLUMN ){ - n += fts3GetVarint32(pReader->pData+n, &pReader->iColumn); - pReader->iPosition = 0; - pReader->iStartOffset = 0; - n += fts3GetVarint32(pReader->pData+n, &i); - } - /* Should never see adjacent column changes. */ - assert( i!=POS_COLUMN ); - - if( i==POS_END ){ - pReader->nData = 0; - pReader->pData = NULL; - return; - } - - pReader->iPosition += i-POS_BASE; - if( pReader->iType==DL_POSITIONS_OFFSETS ){ - n += fts3GetVarint32(pReader->pData+n, &i); - pReader->iStartOffset += i; - n += fts3GetVarint32(pReader->pData+n, &i); - pReader->iEndOffset = pReader->iStartOffset+i; - } - assert( n<=pReader->nData ); - pReader->pData += n; - pReader->nData -= n; -} - -static void plrInit(PLReader *pReader, DLReader *pDLReader){ - pReader->pData = dlrPosData(pDLReader); - pReader->nData = dlrPosDataLen(pDLReader); - pReader->iType = pDLReader->iType; - pReader->iColumn = 0; - pReader->iPosition = 0; - pReader->iStartOffset = 0; - pReader->iEndOffset = 0; - plrStep(pReader); -} -static void plrDestroy(PLReader *pReader){ - SCRAMBLE(pReader); -} - -/*******************************************************************/ -/* PLWriter is used in constructing a document's position list. As a -** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op. -** PLWriter writes to the associated DLWriter's buffer. -** -** plwInit - init for writing a document's poslist. -** plwDestroy - clear a writer. -** plwAdd - append position and offset information. -** plwCopy - copy next position's data from reader to writer. -** plwTerminate - add any necessary doclist terminator. -** -** Calling plwAdd() after plwTerminate() may result in a corrupt -** doclist. -*/ -/* TODO(shess) Until we've written the second item, we can cache the -** first item's information. Then we'd have three states: -** -** - initialized with docid, no positions. -** - docid and one position. -** - docid and multiple positions. -** -** Only the last state needs to actually write to dlw->b, which would -** be an improvement in the DLCollector case. -*/ -typedef struct PLWriter { - DLWriter *dlw; - - int iColumn; /* the last column written */ - int iPos; /* the last position written */ - int iOffset; /* the last start offset written */ -} PLWriter; - -/* TODO(shess) In the case where the parent is reading these values -** from a PLReader, we could optimize to a copy if that PLReader has -** the same type as pWriter. -*/ -static void plwAdd(PLWriter *pWriter, int iColumn, int iPos, - int iStartOffset, int iEndOffset){ - /* Worst-case space for POS_COLUMN, iColumn, iPosDelta, - ** iStartOffsetDelta, and iEndOffsetDelta. - */ - char c[5*VARINT_MAX]; - int n = 0; - - /* Ban plwAdd() after plwTerminate(). */ - assert( pWriter->iPos!=-1 ); - - if( pWriter->dlw->iType==DL_DOCIDS ) return; - - if( iColumn!=pWriter->iColumn ){ - n += fts3PutVarint(c+n, POS_COLUMN); - n += fts3PutVarint(c+n, iColumn); - pWriter->iColumn = iColumn; - pWriter->iPos = 0; - pWriter->iOffset = 0; - } - assert( iPos>=pWriter->iPos ); - n += fts3PutVarint(c+n, POS_BASE+(iPos-pWriter->iPos)); - pWriter->iPos = iPos; - if( pWriter->dlw->iType==DL_POSITIONS_OFFSETS ){ - assert( iStartOffset>=pWriter->iOffset ); - n += fts3PutVarint(c+n, iStartOffset-pWriter->iOffset); - pWriter->iOffset = iStartOffset; - assert( iEndOffset>=iStartOffset ); - n += fts3PutVarint(c+n, iEndOffset-iStartOffset); - } - dataBufferAppend(pWriter->dlw->b, c, n); -} -static void plwCopy(PLWriter *pWriter, PLReader *pReader){ - plwAdd(pWriter, plrColumn(pReader), plrPosition(pReader), - plrStartOffset(pReader), plrEndOffset(pReader)); -} -static void plwInit(PLWriter *pWriter, DLWriter *dlw, sqlite_int64 iDocid){ - char c[VARINT_MAX]; - int n; - - pWriter->dlw = dlw; - - /* Docids must ascend. */ - assert( !pWriter->dlw->has_iPrevDocid || iDocid>pWriter->dlw->iPrevDocid ); - n = fts3PutVarint(c, iDocid-pWriter->dlw->iPrevDocid); - dataBufferAppend(pWriter->dlw->b, c, n); - pWriter->dlw->iPrevDocid = iDocid; -#ifndef NDEBUG - pWriter->dlw->has_iPrevDocid = 1; -#endif - - pWriter->iColumn = 0; - pWriter->iPos = 0; - pWriter->iOffset = 0; -} -/* TODO(shess) Should plwDestroy() also terminate the doclist? But -** then plwDestroy() would no longer be just a destructor, it would -** also be doing work, which isn't consistent with the overall idiom. -** Another option would be for plwAdd() to always append any necessary -** terminator, so that the output is always correct. But that would -** add incremental work to the common case with the only benefit being -** API elegance. Punt for now. -*/ -static void plwTerminate(PLWriter *pWriter){ - if( pWriter->dlw->iType>DL_DOCIDS ){ - char c[VARINT_MAX]; - int n = fts3PutVarint(c, POS_END); - dataBufferAppend(pWriter->dlw->b, c, n); - } -#ifndef NDEBUG - /* Mark as terminated for assert in plwAdd(). */ - pWriter->iPos = -1; -#endif -} -static void plwDestroy(PLWriter *pWriter){ - SCRAMBLE(pWriter); -} - -/*******************************************************************/ -/* DLCollector wraps PLWriter and DLWriter to provide a -** dynamically-allocated doclist area to use during tokenization. -** -** dlcNew - malloc up and initialize a collector. -** dlcDelete - destroy a collector and all contained items. -** dlcAddPos - append position and offset information. -** dlcAddDoclist - add the collected doclist to the given buffer. -** dlcNext - terminate the current document and open another. -*/ -typedef struct DLCollector { - DataBuffer b; - DLWriter dlw; - PLWriter plw; -} DLCollector; - -/* TODO(shess) This could also be done by calling plwTerminate() and -** dataBufferAppend(). I tried that, expecting nominal performance -** differences, but it seemed to pretty reliably be worth 1% to code -** it this way. I suspect it is the incremental malloc overhead (some -** percentage of the plwTerminate() calls will cause a realloc), so -** this might be worth revisiting if the DataBuffer implementation -** changes. -*/ -static void dlcAddDoclist(DLCollector *pCollector, DataBuffer *b){ - if( pCollector->dlw.iType>DL_DOCIDS ){ - char c[VARINT_MAX]; - int n = fts3PutVarint(c, POS_END); - dataBufferAppend2(b, pCollector->b.pData, pCollector->b.nData, c, n); - }else{ - dataBufferAppend(b, pCollector->b.pData, pCollector->b.nData); - } -} -static void dlcNext(DLCollector *pCollector, sqlite_int64 iDocid){ - plwTerminate(&pCollector->plw); - plwDestroy(&pCollector->plw); - plwInit(&pCollector->plw, &pCollector->dlw, iDocid); -} -static void dlcAddPos(DLCollector *pCollector, int iColumn, int iPos, - int iStartOffset, int iEndOffset){ - plwAdd(&pCollector->plw, iColumn, iPos, iStartOffset, iEndOffset); -} - -static DLCollector *dlcNew(sqlite_int64 iDocid, DocListType iType){ - DLCollector *pCollector = sqlite3_malloc(sizeof(DLCollector)); - dataBufferInit(&pCollector->b, 0); - dlwInit(&pCollector->dlw, iType, &pCollector->b); - plwInit(&pCollector->plw, &pCollector->dlw, iDocid); - return pCollector; -} -static void dlcDelete(DLCollector *pCollector){ - plwDestroy(&pCollector->plw); - dlwDestroy(&pCollector->dlw); - dataBufferDestroy(&pCollector->b); - SCRAMBLE(pCollector); - sqlite3_free(pCollector); -} - - -/* Copy the doclist data of iType in pData/nData into *out, trimming -** unnecessary data as we go. Only columns matching iColumn are -** copied, all columns copied if iColumn is -1. Elements with no -** matching columns are dropped. The output is an iOutType doclist. -*/ -/* NOTE(shess) This code is only valid after all doclists are merged. -** If this is run before merges, then doclist items which represent -** deletion will be trimmed, and will thus not effect a deletion -** during the merge. -*/ -static void docListTrim(DocListType iType, const char *pData, int nData, - int iColumn, DocListType iOutType, DataBuffer *out){ - DLReader dlReader; - DLWriter dlWriter; - - assert( iOutType<=iType ); - - dlrInit(&dlReader, iType, pData, nData); - dlwInit(&dlWriter, iOutType, out); - - while( !dlrAtEnd(&dlReader) ){ - PLReader plReader; - PLWriter plWriter; - int match = 0; - - plrInit(&plReader, &dlReader); - - while( !plrAtEnd(&plReader) ){ - if( iColumn==-1 || plrColumn(&plReader)==iColumn ){ - if( !match ){ - plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader)); - match = 1; - } - plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader), - plrStartOffset(&plReader), plrEndOffset(&plReader)); - } - plrStep(&plReader); - } - if( match ){ - plwTerminate(&plWriter); - plwDestroy(&plWriter); - } - - plrDestroy(&plReader); - dlrStep(&dlReader); - } - dlwDestroy(&dlWriter); - dlrDestroy(&dlReader); -} - -/* Used by docListMerge() to keep doclists in the ascending order by -** docid, then ascending order by age (so the newest comes first). -*/ -typedef struct OrderedDLReader { - DLReader *pReader; - - /* TODO(shess) If we assume that docListMerge pReaders is ordered by - ** age (which we do), then we could use pReader comparisons to break - ** ties. - */ - int idx; -} OrderedDLReader; - -/* Order eof to end, then by docid asc, idx desc. */ -static int orderedDLReaderCmp(OrderedDLReader *r1, OrderedDLReader *r2){ - if( dlrAtEnd(r1->pReader) ){ - if( dlrAtEnd(r2->pReader) ) return 0; /* Both atEnd(). */ - return 1; /* Only r1 atEnd(). */ - } - if( dlrAtEnd(r2->pReader) ) return -1; /* Only r2 atEnd(). */ - - if( dlrDocid(r1->pReader)pReader) ) return -1; - if( dlrDocid(r1->pReader)>dlrDocid(r2->pReader) ) return 1; - - /* Descending on idx. */ - return r2->idx-r1->idx; -} - -/* Bubble p[0] to appropriate place in p[1..n-1]. Assumes that -** p[1..n-1] is already sorted. -*/ -/* TODO(shess) Is this frequent enough to warrant a binary search? -** Before implementing that, instrument the code to check. In most -** current usage, I expect that p[0] will be less than p[1] a very -** high proportion of the time. -*/ -static void orderedDLReaderReorder(OrderedDLReader *p, int n){ - while( n>1 && orderedDLReaderCmp(p, p+1)>0 ){ - OrderedDLReader tmp = p[0]; - p[0] = p[1]; - p[1] = tmp; - n--; - p++; - } -} - -/* Given an array of doclist readers, merge their doclist elements -** into out in sorted order (by docid), dropping elements from older -** readers when there is a duplicate docid. pReaders is assumed to be -** ordered by age, oldest first. -*/ -/* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably -** be fixed. -*/ -static void docListMerge(DataBuffer *out, - DLReader *pReaders, int nReaders){ - OrderedDLReader readers[MERGE_COUNT]; - DLWriter writer; - int i, n; - const char *pStart = 0; - int nStart = 0; - sqlite_int64 iFirstDocid = 0, iLastDocid = 0; - - assert( nReaders>0 ); - if( nReaders==1 ){ - dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); - return; - } - - assert( nReaders<=MERGE_COUNT ); - n = 0; - for(i=0; i0 ){ - orderedDLReaderReorder(readers+i, nReaders-i); - } - - dlwInit(&writer, pReaders[0].iType, out); - while( !dlrAtEnd(readers[0].pReader) ){ - sqlite_int64 iDocid = dlrDocid(readers[0].pReader); - - /* If this is a continuation of the current buffer to copy, extend - ** that buffer. memcpy() seems to be more efficient if it has a - ** lots of data to copy. - */ - if( dlrDocData(readers[0].pReader)==pStart+nStart ){ - nStart += dlrDocDataBytes(readers[0].pReader); - }else{ - if( pStart!=0 ){ - dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); - } - pStart = dlrDocData(readers[0].pReader); - nStart = dlrDocDataBytes(readers[0].pReader); - iFirstDocid = iDocid; - } - iLastDocid = iDocid; - dlrStep(readers[0].pReader); - - /* Drop all of the older elements with the same docid. */ - for(i=1; i0 ){ - orderedDLReaderReorder(readers+i, nReaders-i); - } - } - - /* Copy over any remaining elements. */ - if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); - dlwDestroy(&writer); -} - -/* Helper function for posListUnion(). Compares the current position -** between left and right, returning as standard C idiom of <0 if -** left0 if left>right, and 0 if left==right. "End" always -** compares greater. -*/ -static int posListCmp(PLReader *pLeft, PLReader *pRight){ - assert( pLeft->iType==pRight->iType ); - if( pLeft->iType==DL_DOCIDS ) return 0; - - if( plrAtEnd(pLeft) ) return plrAtEnd(pRight) ? 0 : 1; - if( plrAtEnd(pRight) ) return -1; - - if( plrColumn(pLeft)plrColumn(pRight) ) return 1; - - if( plrPosition(pLeft)plrPosition(pRight) ) return 1; - if( pLeft->iType==DL_POSITIONS ) return 0; - - if( plrStartOffset(pLeft)plrStartOffset(pRight) ) return 1; - - if( plrEndOffset(pLeft)plrEndOffset(pRight) ) return 1; - - return 0; -} - -/* Write the union of position lists in pLeft and pRight to pOut. -** "Union" in this case meaning "All unique position tuples". Should -** work with any doclist type, though both inputs and the output -** should be the same type. -*/ -static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ - PLReader left, right; - PLWriter writer; - - assert( dlrDocid(pLeft)==dlrDocid(pRight) ); - assert( pLeft->iType==pRight->iType ); - assert( pLeft->iType==pOut->iType ); - - plrInit(&left, pLeft); - plrInit(&right, pRight); - plwInit(&writer, pOut, dlrDocid(pLeft)); - - while( !plrAtEnd(&left) || !plrAtEnd(&right) ){ - int c = posListCmp(&left, &right); - if( c<0 ){ - plwCopy(&writer, &left); - plrStep(&left); - }else if( c>0 ){ - plwCopy(&writer, &right); - plrStep(&right); - }else{ - plwCopy(&writer, &left); - plrStep(&left); - plrStep(&right); - } - } - - plwTerminate(&writer); - plwDestroy(&writer); - plrDestroy(&left); - plrDestroy(&right); -} - -/* Write the union of doclists in pLeft and pRight to pOut. For -** docids in common between the inputs, the union of the position -** lists is written. Inputs and outputs are always type DL_DEFAULT. -*/ -static void docListUnion( - const char *pLeft, int nLeft, - const char *pRight, int nRight, - DataBuffer *pOut /* Write the combined doclist here */ -){ - DLReader left, right; - DLWriter writer; - - if( nLeft==0 ){ - if( nRight!=0) dataBufferAppend(pOut, pRight, nRight); - return; - } - if( nRight==0 ){ - dataBufferAppend(pOut, pLeft, nLeft); - return; - } - - dlrInit(&left, DL_DEFAULT, pLeft, nLeft); - dlrInit(&right, DL_DEFAULT, pRight, nRight); - dlwInit(&writer, DL_DEFAULT, pOut); - - while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ - if( dlrAtEnd(&right) ){ - dlwCopy(&writer, &left); - dlrStep(&left); - }else if( dlrAtEnd(&left) ){ - dlwCopy(&writer, &right); - dlrStep(&right); - }else if( dlrDocid(&left)dlrDocid(&right) ){ - dlwCopy(&writer, &right); - dlrStep(&right); - }else{ - posListUnion(&left, &right, &writer); - dlrStep(&left); - dlrStep(&right); - } - } - - dlrDestroy(&left); - dlrDestroy(&right); - dlwDestroy(&writer); -} - -/* -** This function is used as part of the implementation of phrase and -** NEAR matching. -** -** pLeft and pRight are DLReaders positioned to the same docid in -** lists of type DL_POSITION. This function writes an entry to the -** DLWriter pOut for each position in pRight that is less than -** (nNear+1) greater (but not equal to or smaller) than a position -** in pLeft. For example, if nNear is 0, and the positions contained -** by pLeft and pRight are: -** -** pLeft: 5 10 15 20 -** pRight: 6 9 17 21 -** -** then the docid is added to pOut. If pOut is of type DL_POSITIONS, -** then a positionids "6" and "21" are also added to pOut. -** -** If boolean argument isSaveLeft is true, then positionids are copied -** from pLeft instead of pRight. In the example above, the positions "5" -** and "20" would be added instead of "6" and "21". -*/ -static void posListPhraseMerge( - DLReader *pLeft, - DLReader *pRight, - int nNear, - int isSaveLeft, - DLWriter *pOut -){ - PLReader left, right; - PLWriter writer; - int match = 0; - - assert( dlrDocid(pLeft)==dlrDocid(pRight) ); - assert( pOut->iType!=DL_POSITIONS_OFFSETS ); - - plrInit(&left, pLeft); - plrInit(&right, pRight); - - while( !plrAtEnd(&left) && !plrAtEnd(&right) ){ - if( plrColumn(&left)plrColumn(&right) ){ - plrStep(&right); - }else if( plrPosition(&left)>=plrPosition(&right) ){ - plrStep(&right); - }else{ - if( (plrPosition(&right)-plrPosition(&left))<=(nNear+1) ){ - if( !match ){ - plwInit(&writer, pOut, dlrDocid(pLeft)); - match = 1; - } - if( !isSaveLeft ){ - plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); - }else{ - plwAdd(&writer, plrColumn(&left), plrPosition(&left), 0, 0); - } - plrStep(&right); - }else{ - plrStep(&left); - } - } - } - - if( match ){ - plwTerminate(&writer); - plwDestroy(&writer); - } - - plrDestroy(&left); - plrDestroy(&right); -} - -/* -** Compare the values pointed to by the PLReaders passed as arguments. -** Return -1 if the value pointed to by pLeft is considered less than -** the value pointed to by pRight, +1 if it is considered greater -** than it, or 0 if it is equal. i.e. -** -** (*pLeft - *pRight) -** -** A PLReader that is in the EOF condition is considered greater than -** any other. If neither argument is in EOF state, the return value of -** plrColumn() is used. If the plrColumn() values are equal, the -** comparison is on the basis of plrPosition(). -*/ -static int plrCompare(PLReader *pLeft, PLReader *pRight){ - assert(!plrAtEnd(pLeft) || !plrAtEnd(pRight)); - - if( plrAtEnd(pRight) || plrAtEnd(pLeft) ){ - return (plrAtEnd(pRight) ? -1 : 1); - } - if( plrColumn(pLeft)!=plrColumn(pRight) ){ - return ((plrColumn(pLeft)0) -** and write the results into pOut. -** -** A phrase intersection means that two documents only match -** if pLeft.iPos+1==pRight.iPos. -** -** A NEAR intersection means that two documents only match if -** (abs(pLeft.iPos-pRight.iPos) one AND (two OR three) - * [one OR two three] ==> (one OR two) AND three - * - * A "-" before a term matches all entries that lack that term. - * The "-" must occur immediately before the term with in intervening - * space. This is how the search engines do it. - * - * A NOT term cannot be the right-hand operand of an OR. If this - * occurs in the query string, the NOT is ignored: - * - * [one OR -two] ==> one OR two - * - */ -typedef struct Query { - fulltext_vtab *pFts; /* The full text index */ - int nTerms; /* Number of terms in the query */ - QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */ - int nextIsOr; /* Set the isOr flag on the next inserted term */ - int nextIsNear; /* Set the isOr flag on the next inserted term */ - int nextColumn; /* Next word parsed must be in this column */ - int dfltColumn; /* The default column */ -} Query; - - -/* -** An instance of the following structure keeps track of generated -** matching-word offset information and snippets. -*/ -typedef struct Snippet { - int nMatch; /* Total number of matches */ - int nAlloc; /* Space allocated for aMatch[] */ - struct snippetMatch { /* One entry for each matching term */ - char snStatus; /* Status flag for use while constructing snippets */ - short int iCol; /* The column that contains the match */ - short int iTerm; /* The index in Query.pTerms[] of the matching term */ - int iToken; /* The index of the matching document token */ - short int nByte; /* Number of bytes in the term */ - int iStart; /* The offset to the first character of the term */ - } *aMatch; /* Points to space obtained from malloc */ - char *zOffset; /* Text rendering of aMatch[] */ - int nOffset; /* strlen(zOffset) */ - char *zSnippet; /* Snippet text */ - int nSnippet; /* strlen(zSnippet) */ -} Snippet; - - -typedef enum QueryType { - QUERY_GENERIC, /* table scan */ - QUERY_DOCID, /* lookup by docid */ - QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/ -} QueryType; - -typedef enum fulltext_statement { - CONTENT_INSERT_STMT, - CONTENT_SELECT_STMT, - CONTENT_UPDATE_STMT, - CONTENT_DELETE_STMT, - - BLOCK_INSERT_STMT, - BLOCK_SELECT_STMT, - BLOCK_DELETE_STMT, - - SEGDIR_MAX_INDEX_STMT, - SEGDIR_SET_STMT, - SEGDIR_SELECT_STMT, - SEGDIR_SPAN_STMT, - SEGDIR_DELETE_STMT, - SEGDIR_SELECT_ALL_STMT, - - MAX_STMT /* Always at end! */ -} fulltext_statement; - -/* These must exactly match the enum above. */ -/* TODO(shess): Is there some risk that a statement will be used in two -** cursors at once, e.g. if a query joins a virtual table to itself? -** If so perhaps we should move some of these to the cursor object. -*/ -static const char *const fulltext_zStatement[MAX_STMT] = { - /* CONTENT_INSERT */ NULL, /* generated in contentInsertStatement() */ - /* CONTENT_SELECT */ NULL, /* generated in contentSelectStatement() */ - /* CONTENT_UPDATE */ NULL, /* generated in contentUpdateStatement() */ - /* CONTENT_DELETE */ "delete from %_content where docid = ?", - - /* BLOCK_INSERT */ - "insert into %_segments (blockid, block) values (null, ?)", - /* BLOCK_SELECT */ "select block from %_segments where blockid = ?", - /* BLOCK_DELETE */ "delete from %_segments where blockid between ? and ?", - - /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?", - /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)", - /* SEGDIR_SELECT */ - "select start_block, leaves_end_block, root from %_segdir " - " where level = ? order by idx", - /* SEGDIR_SPAN */ - "select min(start_block), max(end_block) from %_segdir " - " where level = ? and start_block <> 0", - /* SEGDIR_DELETE */ "delete from %_segdir where level = ?", - /* SEGDIR_SELECT_ALL */ - "select root, leaves_end_block from %_segdir order by level desc, idx", -}; - -/* -** A connection to a fulltext index is an instance of the following -** structure. The xCreate and xConnect methods create an instance -** of this structure and xDestroy and xDisconnect free that instance. -** All other methods receive a pointer to the structure as one of their -** arguments. -*/ -struct fulltext_vtab { - sqlite3_vtab base; /* Base class used by SQLite core */ - sqlite3 *db; /* The database connection */ - const char *zDb; /* logical database name */ - const char *zName; /* virtual table name */ - int nColumn; /* number of columns in virtual table */ - char **azColumn; /* column names. malloced */ - char **azContentColumn; /* column names in content table; malloced */ - sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ - - /* Precompiled statements which we keep as long as the table is - ** open. - */ - sqlite3_stmt *pFulltextStatements[MAX_STMT]; - - /* Precompiled statements used for segment merges. We run a - ** separate select across the leaf level of each tree being merged. - */ - sqlite3_stmt *pLeafSelectStmts[MERGE_COUNT]; - /* The statement used to prepare pLeafSelectStmts. */ -#define LEAF_SELECT \ - "select block from %_segments where blockid between ? and ? order by blockid" - - /* These buffer pending index updates during transactions. - ** nPendingData estimates the memory size of the pending data. It - ** doesn't include the hash-bucket overhead, nor any malloc - ** overhead. When nPendingData exceeds kPendingThreshold, the - ** buffer is flushed even before the transaction closes. - ** pendingTerms stores the data, and is only valid when nPendingData - ** is >=0 (nPendingData<0 means pendingTerms has not been - ** initialized). iPrevDocid is the last docid written, used to make - ** certain we're inserting in sorted order. - */ - int nPendingData; -#define kPendingThreshold (1*1024*1024) - sqlite_int64 iPrevDocid; - fts3Hash pendingTerms; -}; - -/* -** When the core wants to do a query, it create a cursor using a -** call to xOpen. This structure is an instance of a cursor. It -** is destroyed by xClose. -*/ -typedef struct fulltext_cursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - QueryType iCursorType; /* Copy of sqlite3_index_info.idxNum */ - sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ - int eof; /* True if at End Of Results */ - Query q; /* Parsed query string */ - Snippet snippet; /* Cached snippet for the current row */ - int iColumn; /* Column being searched */ - DataBuffer result; /* Doclist results from fulltextQuery */ - DLReader reader; /* Result reader if result not empty */ -} fulltext_cursor; - -static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){ - return (fulltext_vtab *) c->base.pVtab; -} - -static const sqlite3_module fts3Module; /* forward declaration */ - -/* Return a dynamically generated statement of the form - * insert into %_content (docid, ...) values (?, ...) - */ -static const char *contentInsertStatement(fulltext_vtab *v){ - StringBuffer sb; - int i; - - initStringBuffer(&sb); - append(&sb, "insert into %_content (docid, "); - appendList(&sb, v->nColumn, v->azContentColumn); - append(&sb, ") values (?"); - for(i=0; inColumn; ++i) - append(&sb, ", ?"); - append(&sb, ")"); - return stringBufferData(&sb); -} - -/* Return a dynamically generated statement of the form - * select from %_content where docid = ? - */ -static const char *contentSelectStatement(fulltext_vtab *v){ - StringBuffer sb; - initStringBuffer(&sb); - append(&sb, "SELECT "); - appendList(&sb, v->nColumn, v->azContentColumn); - append(&sb, " FROM %_content WHERE docid = ?"); - return stringBufferData(&sb); -} - -/* Return a dynamically generated statement of the form - * update %_content set [col_0] = ?, [col_1] = ?, ... - * where docid = ? - */ -static const char *contentUpdateStatement(fulltext_vtab *v){ - StringBuffer sb; - int i; - - initStringBuffer(&sb); - append(&sb, "update %_content set "); - for(i=0; inColumn; ++i) { - if( i>0 ){ - append(&sb, ", "); - } - append(&sb, v->azContentColumn[i]); - append(&sb, " = ?"); - } - append(&sb, " where docid = ?"); - return stringBufferData(&sb); -} - -/* Puts a freshly-prepared statement determined by iStmt in *ppStmt. -** If the indicated statement has never been prepared, it is prepared -** and cached, otherwise the cached version is reset. -*/ -static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt, - sqlite3_stmt **ppStmt){ - assert( iStmtpFulltextStatements[iStmt]==NULL ){ - const char *zStmt; - int rc; - switch( iStmt ){ - case CONTENT_INSERT_STMT: - zStmt = contentInsertStatement(v); break; - case CONTENT_SELECT_STMT: - zStmt = contentSelectStatement(v); break; - case CONTENT_UPDATE_STMT: - zStmt = contentUpdateStatement(v); break; - default: - zStmt = fulltext_zStatement[iStmt]; - } - rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt], - zStmt); - if( zStmt != fulltext_zStatement[iStmt]) sqlite3_free((void *) zStmt); - if( rc!=SQLITE_OK ) return rc; - } else { - int rc = sqlite3_reset(v->pFulltextStatements[iStmt]); - if( rc!=SQLITE_OK ) return rc; - } - - *ppStmt = v->pFulltextStatements[iStmt]; - return SQLITE_OK; -} - -/* Like sqlite3_step(), but convert SQLITE_DONE to SQLITE_OK and -** SQLITE_ROW to SQLITE_ERROR. Useful for statements like UPDATE, -** where we expect no results. -*/ -static int sql_single_step(sqlite3_stmt *s){ - int rc = sqlite3_step(s); - return (rc==SQLITE_DONE) ? SQLITE_OK : rc; -} - -/* Like sql_get_statement(), but for special replicated LEAF_SELECT -** statements. -*/ -/* TODO(shess) Write version for generic statements and then share -** that between the cached-statement functions. -*/ -static int sql_get_leaf_statement(fulltext_vtab *v, int idx, - sqlite3_stmt **ppStmt){ - assert( idx>=0 && idxpLeafSelectStmts[idx]==NULL ){ - int rc = sql_prepare(v->db, v->zDb, v->zName, &v->pLeafSelectStmts[idx], - LEAF_SELECT); - if( rc!=SQLITE_OK ) return rc; - }else{ - int rc = sqlite3_reset(v->pLeafSelectStmts[idx]); - if( rc!=SQLITE_OK ) return rc; - } - - *ppStmt = v->pLeafSelectStmts[idx]; - return SQLITE_OK; -} - -/* insert into %_content (docid, ...) values ([docid], [pValues]) -** If the docid contains SQL NULL, then a unique docid will be -** generated. -*/ -static int content_insert(fulltext_vtab *v, sqlite3_value *docid, - sqlite3_value **pValues){ - sqlite3_stmt *s; - int i; - int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_value(s, 1, docid); - if( rc!=SQLITE_OK ) return rc; - - for(i=0; inColumn; ++i){ - rc = sqlite3_bind_value(s, 2+i, pValues[i]); - if( rc!=SQLITE_OK ) return rc; - } - - return sql_single_step(s); -} - -/* update %_content set col0 = pValues[0], col1 = pValues[1], ... - * where docid = [iDocid] */ -static int content_update(fulltext_vtab *v, sqlite3_value **pValues, - sqlite_int64 iDocid){ - sqlite3_stmt *s; - int i; - int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - for(i=0; inColumn; ++i){ - rc = sqlite3_bind_value(s, 1+i, pValues[i]); - if( rc!=SQLITE_OK ) return rc; - } - - rc = sqlite3_bind_int64(s, 1+v->nColumn, iDocid); - if( rc!=SQLITE_OK ) return rc; - - return sql_single_step(s); -} - -static void freeStringArray(int nString, const char **pString){ - int i; - - for (i=0 ; i < nString ; ++i) { - if( pString[i]!=NULL ) sqlite3_free((void *) pString[i]); - } - sqlite3_free((void *) pString); -} - -/* select * from %_content where docid = [iDocid] - * The caller must delete the returned array and all strings in it. - * null fields will be NULL in the returned array. - * - * TODO: Perhaps we should return pointer/length strings here for consistency - * with other code which uses pointer/length. */ -static int content_select(fulltext_vtab *v, sqlite_int64 iDocid, - const char ***pValues){ - sqlite3_stmt *s; - const char **values; - int i; - int rc; - - *pValues = NULL; - - rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 1, iDocid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_step(s); - if( rc!=SQLITE_ROW ) return rc; - - values = (const char **) sqlite3_malloc(v->nColumn * sizeof(const char *)); - for(i=0; inColumn; ++i){ - if( sqlite3_column_type(s, i)==SQLITE_NULL ){ - values[i] = NULL; - }else{ - values[i] = string_dup((char*)sqlite3_column_text(s, i)); - } - } - - /* We expect only one row. We must execute another sqlite3_step() - * to complete the iteration; otherwise the table will remain locked. */ - rc = sqlite3_step(s); - if( rc==SQLITE_DONE ){ - *pValues = values; - return SQLITE_OK; - } - - freeStringArray(v->nColumn, values); - return rc; -} - -/* delete from %_content where docid = [iDocid ] */ -static int content_delete(fulltext_vtab *v, sqlite_int64 iDocid){ - sqlite3_stmt *s; - int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 1, iDocid); - if( rc!=SQLITE_OK ) return rc; - - return sql_single_step(s); -} - -/* insert into %_segments values ([pData]) -** returns assigned blockid in *piBlockid -*/ -static int block_insert(fulltext_vtab *v, const char *pData, int nData, - sqlite_int64 *piBlockid){ - sqlite3_stmt *s; - int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_step(s); - if( rc==SQLITE_ROW ) return SQLITE_ERROR; - if( rc!=SQLITE_DONE ) return rc; - - /* blockid column is an alias for rowid. */ - *piBlockid = sqlite3_last_insert_rowid(v->db); - return SQLITE_OK; -} - -/* delete from %_segments -** where blockid between [iStartBlockid] and [iEndBlockid] -** -** Deletes the range of blocks, inclusive, used to delete the blocks -** which form a segment. -*/ -static int block_delete(fulltext_vtab *v, - sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){ - sqlite3_stmt *s; - int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 1, iStartBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 2, iEndBlockid); - if( rc!=SQLITE_OK ) return rc; - - return sql_single_step(s); -} - -/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found -** at iLevel. Returns SQLITE_DONE if there are no segments at -** iLevel. Otherwise returns an error. -*/ -static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){ - sqlite3_stmt *s; - int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int(s, 1, iLevel); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_step(s); - /* Should always get at least one row due to how max() works. */ - if( rc==SQLITE_DONE ) return SQLITE_DONE; - if( rc!=SQLITE_ROW ) return rc; - - /* NULL means that there were no inputs to max(). */ - if( SQLITE_NULL==sqlite3_column_type(s, 0) ){ - rc = sqlite3_step(s); - if( rc==SQLITE_ROW ) return SQLITE_ERROR; - return rc; - } - - *pidx = sqlite3_column_int(s, 0); - - /* We expect only one row. We must execute another sqlite3_step() - * to complete the iteration; otherwise the table will remain locked. */ - rc = sqlite3_step(s); - if( rc==SQLITE_ROW ) return SQLITE_ERROR; - if( rc!=SQLITE_DONE ) return rc; - return SQLITE_ROW; -} - -/* insert into %_segdir values ( -** [iLevel], [idx], -** [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid], -** [pRootData] -** ) -*/ -static int segdir_set(fulltext_vtab *v, int iLevel, int idx, - sqlite_int64 iStartBlockid, - sqlite_int64 iLeavesEndBlockid, - sqlite_int64 iEndBlockid, - const char *pRootData, int nRootData){ - sqlite3_stmt *s; - int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int(s, 1, iLevel); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int(s, 2, idx); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 3, iStartBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 5, iEndBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC); - if( rc!=SQLITE_OK ) return rc; - - return sql_single_step(s); -} - -/* Queries %_segdir for the block span of the segments in level -** iLevel. Returns SQLITE_DONE if there are no blocks for iLevel, -** SQLITE_ROW if there are blocks, else an error. -*/ -static int segdir_span(fulltext_vtab *v, int iLevel, - sqlite_int64 *piStartBlockid, - sqlite_int64 *piEndBlockid){ - sqlite3_stmt *s; - int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int(s, 1, iLevel); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_step(s); - if( rc==SQLITE_DONE ) return SQLITE_DONE; /* Should never happen */ - if( rc!=SQLITE_ROW ) return rc; - - /* This happens if all segments at this level are entirely inline. */ - if( SQLITE_NULL==sqlite3_column_type(s, 0) ){ - /* We expect only one row. We must execute another sqlite3_step() - * to complete the iteration; otherwise the table will remain locked. */ - int rc2 = sqlite3_step(s); - if( rc2==SQLITE_ROW ) return SQLITE_ERROR; - return rc2; - } - - *piStartBlockid = sqlite3_column_int64(s, 0); - *piEndBlockid = sqlite3_column_int64(s, 1); - - /* We expect only one row. We must execute another sqlite3_step() - * to complete the iteration; otherwise the table will remain locked. */ - rc = sqlite3_step(s); - if( rc==SQLITE_ROW ) return SQLITE_ERROR; - if( rc!=SQLITE_DONE ) return rc; - return SQLITE_ROW; -} - -/* Delete the segment blocks and segment directory records for all -** segments at iLevel. -*/ -static int segdir_delete(fulltext_vtab *v, int iLevel){ - sqlite3_stmt *s; - sqlite_int64 iStartBlockid, iEndBlockid; - int rc = segdir_span(v, iLevel, &iStartBlockid, &iEndBlockid); - if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc; - - if( rc==SQLITE_ROW ){ - rc = block_delete(v, iStartBlockid, iEndBlockid); - if( rc!=SQLITE_OK ) return rc; - } - - /* Delete the segment directory itself. */ - rc = sql_get_statement(v, SEGDIR_DELETE_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 1, iLevel); - if( rc!=SQLITE_OK ) return rc; - - return sql_single_step(s); -} - -/* TODO(shess) clearPendingTerms() is far down the file because -** writeZeroSegment() is far down the file because LeafWriter is far -** down the file. Consider refactoring the code to move the non-vtab -** code above the vtab code so that we don't need this forward -** reference. -*/ -static int clearPendingTerms(fulltext_vtab *v); - -/* -** Free the memory used to contain a fulltext_vtab structure. -*/ -static void fulltext_vtab_destroy(fulltext_vtab *v){ - int iStmt, i; - - FTSTRACE(("FTS3 Destroy %p\n", v)); - for( iStmt=0; iStmtpFulltextStatements[iStmt]!=NULL ){ - sqlite3_finalize(v->pFulltextStatements[iStmt]); - v->pFulltextStatements[iStmt] = NULL; - } - } - - for( i=0; ipLeafSelectStmts[i]!=NULL ){ - sqlite3_finalize(v->pLeafSelectStmts[i]); - v->pLeafSelectStmts[i] = NULL; - } - } - - if( v->pTokenizer!=NULL ){ - v->pTokenizer->pModule->xDestroy(v->pTokenizer); - v->pTokenizer = NULL; - } - - clearPendingTerms(v); - - sqlite3_free(v->azColumn); - for(i = 0; i < v->nColumn; ++i) { - sqlite3_free(v->azContentColumn[i]); - } - sqlite3_free(v->azContentColumn); - sqlite3_free(v); -} - -/* -** Token types for parsing the arguments to xConnect or xCreate. -*/ -#define TOKEN_EOF 0 /* End of file */ -#define TOKEN_SPACE 1 /* Any kind of whitespace */ -#define TOKEN_ID 2 /* An identifier */ -#define TOKEN_STRING 3 /* A string literal */ -#define TOKEN_PUNCT 4 /* A single punctuation character */ - -/* -** If X is a character that can be used in an identifier then -** ftsIdChar(X) will be true. Otherwise it is false. -** -** For ASCII, any character with the high-order bit set is -** allowed in an identifier. For 7-bit characters, -** isFtsIdChar[X] must be 1. -** -** Ticket #1066. the SQL standard does not allow '$' in the -** middle of identfiers. But many SQL implementations do. -** SQLite will allow '$' in identifiers for compatibility. -** But the feature is undocumented. -*/ -static const char isFtsIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ -}; -#define ftsIdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isFtsIdChar[c-0x20])) - - -/* -** Return the length of the token that begins at z[0]. -** Store the token type in *tokenType before returning. -*/ -static int ftsGetToken(const char *z, int *tokenType){ - int i, c; - switch( *z ){ - case 0: { - *tokenType = TOKEN_EOF; - return 0; - } - case ' ': case '\t': case '\n': case '\f': case '\r': { - for(i=1; safe_isspace(z[i]); i++){} - *tokenType = TOKEN_SPACE; - return i; - } - case '`': - case '\'': - case '"': { - int delim = z[0]; - for(i=1; (c=z[i])!=0; i++){ - if( c==delim ){ - if( z[i+1]==delim ){ - i++; - }else{ - break; - } - } - } - *tokenType = TOKEN_STRING; - return i + (c!=0); - } - case '[': { - for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} - *tokenType = TOKEN_ID; - return i; - } - default: { - if( !ftsIdChar(*z) ){ - break; - } - for(i=1; ftsIdChar(z[i]); i++){} - *tokenType = TOKEN_ID; - return i; - } - } - *tokenType = TOKEN_PUNCT; - return 1; -} - -/* -** A token extracted from a string is an instance of the following -** structure. -*/ -typedef struct FtsToken { - const char *z; /* Pointer to token text. Not '\000' terminated */ - short int n; /* Length of the token text in bytes. */ -} FtsToken; - -/* -** Given a input string (which is really one of the argv[] parameters -** passed into xConnect or xCreate) split the string up into tokens. -** Return an array of pointers to '\000' terminated strings, one string -** for each non-whitespace token. -** -** The returned array is terminated by a single NULL pointer. -** -** Space to hold the returned array is obtained from a single -** malloc and should be freed by passing the return value to free(). -** The individual strings within the token list are all a part of -** the single memory allocation and will all be freed at once. -*/ -static char **tokenizeString(const char *z, int *pnToken){ - int nToken = 0; - FtsToken *aToken = sqlite3_malloc( strlen(z) * sizeof(aToken[0]) ); - int n = 1; - int e, i; - int totalSize = 0; - char **azToken; - char *zCopy; - while( n>0 ){ - n = ftsGetToken(z, &e); - if( e!=TOKEN_SPACE ){ - aToken[nToken].z = z; - aToken[nToken].n = n; - nToken++; - totalSize += n+1; - } - z += n; - } - azToken = (char**)sqlite3_malloc( nToken*sizeof(char*) + totalSize ); - zCopy = (char*)&azToken[nToken]; - nToken--; - for(i=0; i=0 ){ - azIn[j] = azIn[i]; - } - j++; - } - } - azIn[j] = 0; - } -} - - -/* -** Find the first alphanumeric token in the string zIn. Null-terminate -** this token. Remove any quotation marks. And return a pointer to -** the result. -*/ -static char *firstToken(char *zIn, char **pzTail){ - int n, ttype; - while(1){ - n = ftsGetToken(zIn, &ttype); - if( ttype==TOKEN_SPACE ){ - zIn += n; - }else if( ttype==TOKEN_EOF ){ - *pzTail = zIn; - return 0; - }else{ - zIn[n] = 0; - *pzTail = &zIn[1]; - dequoteString(zIn); - return zIn; - } - } - /*NOTREACHED*/ -} - -/* Return true if... -** -** * s begins with the string t, ignoring case -** * s is longer than t -** * The first character of s beyond t is not a alphanumeric -** -** Ignore leading space in *s. -** -** To put it another way, return true if the first token of -** s[] is t[]. -*/ -static int startsWith(const char *s, const char *t){ - while( safe_isspace(*s) ){ s++; } - while( *t ){ - if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0; - } - return *s!='_' && !safe_isalnum(*s); -} - -/* -** An instance of this structure defines the "spec" of a -** full text index. This structure is populated by parseSpec -** and use by fulltextConnect and fulltextCreate. -*/ -typedef struct TableSpec { - const char *zDb; /* Logical database name */ - const char *zName; /* Name of the full-text index */ - int nColumn; /* Number of columns to be indexed */ - char **azColumn; /* Original names of columns to be indexed */ - char **azContentColumn; /* Column names for %_content */ - char **azTokenizer; /* Name of tokenizer and its arguments */ -} TableSpec; - -/* -** Reclaim all of the memory used by a TableSpec -*/ -static void clearTableSpec(TableSpec *p) { - sqlite3_free(p->azColumn); - sqlite3_free(p->azContentColumn); - sqlite3_free(p->azTokenizer); -} - -/* Parse a CREATE VIRTUAL TABLE statement, which looks like this: - * - * CREATE VIRTUAL TABLE email - * USING fts3(subject, body, tokenize mytokenizer(myarg)) - * - * We return parsed information in a TableSpec structure. - * - */ -static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv, - char**pzErr){ - int i, n; - char *z, *zDummy; - char **azArg; - const char *zTokenizer = 0; /* argv[] entry describing the tokenizer */ - - assert( argc>=3 ); - /* Current interface: - ** argv[0] - module name - ** argv[1] - database name - ** argv[2] - table name - ** argv[3..] - columns, optionally followed by tokenizer specification - ** and snippet delimiters specification. - */ - - /* Make a copy of the complete argv[][] array in a single allocation. - ** The argv[][] array is read-only and transient. We can write to the - ** copy in order to modify things and the copy is persistent. - */ - CLEAR(pSpec); - for(i=n=0; izDb = azArg[1]; - pSpec->zName = azArg[2]; - pSpec->nColumn = 0; - pSpec->azColumn = azArg; - zTokenizer = "tokenize simple"; - for(i=3; inColumn] = firstToken(azArg[i], &zDummy); - pSpec->nColumn++; - } - } - if( pSpec->nColumn==0 ){ - azArg[0] = "content"; - pSpec->nColumn = 1; - } - - /* - ** Construct the list of content column names. - ** - ** Each content column name will be of the form cNNAAAA - ** where NN is the column number and AAAA is the sanitized - ** column name. "sanitized" means that special characters are - ** converted to "_". The cNN prefix guarantees that all column - ** names are unique. - ** - ** The AAAA suffix is not strictly necessary. It is included - ** for the convenience of people who might examine the generated - ** %_content table and wonder what the columns are used for. - */ - pSpec->azContentColumn = sqlite3_malloc( pSpec->nColumn * sizeof(char *) ); - if( pSpec->azContentColumn==0 ){ - clearTableSpec(pSpec); - return SQLITE_NOMEM; - } - for(i=0; inColumn; i++){ - char *p; - pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]); - for (p = pSpec->azContentColumn[i]; *p ; ++p) { - if( !safe_isalnum(*p) ) *p = '_'; - } - } - - /* - ** Parse the tokenizer specification string. - */ - pSpec->azTokenizer = tokenizeString(zTokenizer, &n); - tokenListToIdList(pSpec->azTokenizer); - - return SQLITE_OK; -} - -/* -** Generate a CREATE TABLE statement that describes the schema of -** the virtual table. Return a pointer to this schema string. -** -** Space is obtained from sqlite3_mprintf() and should be freed -** using sqlite3_free(). -*/ -static char *fulltextSchema( - int nColumn, /* Number of columns */ - const char *const* azColumn, /* List of columns */ - const char *zTableName /* Name of the table */ -){ - int i; - char *zSchema, *zNext; - const char *zSep = "("; - zSchema = sqlite3_mprintf("CREATE TABLE x"); - for(i=0; ibase */ - v->db = db; - v->zDb = spec->zDb; /* Freed when azColumn is freed */ - v->zName = spec->zName; /* Freed when azColumn is freed */ - v->nColumn = spec->nColumn; - v->azContentColumn = spec->azContentColumn; - spec->azContentColumn = 0; - v->azColumn = spec->azColumn; - spec->azColumn = 0; - - if( spec->azTokenizer==0 ){ - return SQLITE_NOMEM; - } - - zTok = spec->azTokenizer[0]; - if( !zTok ){ - zTok = "simple"; - } - nTok = strlen(zTok)+1; - - m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zTok, nTok); - if( !m ){ - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]); - rc = SQLITE_ERROR; - goto err; - } - - for(n=0; spec->azTokenizer[n]; n++){} - if( n ){ - rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1], - &v->pTokenizer); - }else{ - rc = m->xCreate(0, 0, &v->pTokenizer); - } - if( rc!=SQLITE_OK ) goto err; - v->pTokenizer->pModule = m; - - /* TODO: verify the existence of backing tables foo_content, foo_term */ - - schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn, - spec->zName); - rc = sqlite3_declare_vtab(db, schema); - sqlite3_free(schema); - if( rc!=SQLITE_OK ) goto err; - - memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); - - /* Indicate that the buffer is not live. */ - v->nPendingData = -1; - - *ppVTab = &v->base; - FTSTRACE(("FTS3 Connect %p\n", v)); - - return rc; - -err: - fulltext_vtab_destroy(v); - return rc; -} - -static int fulltextConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, - char **pzErr -){ - TableSpec spec; - int rc = parseSpec(&spec, argc, argv, pzErr); - if( rc!=SQLITE_OK ) return rc; - - rc = constructVtab(db, (fts3Hash *)pAux, &spec, ppVTab, pzErr); - clearTableSpec(&spec); - return rc; -} - -/* The %_content table holds the text of each document, with -** the docid column exposed as the SQLite rowid for the table. -*/ -/* TODO(shess) This comment needs elaboration to match the updated -** code. Work it into the top-of-file comment at that time. -*/ -static int fulltextCreate(sqlite3 *db, void *pAux, - int argc, const char * const *argv, - sqlite3_vtab **ppVTab, char **pzErr){ - int rc; - TableSpec spec; - StringBuffer schema; - FTSTRACE(("FTS3 Create\n")); - - rc = parseSpec(&spec, argc, argv, pzErr); - if( rc!=SQLITE_OK ) return rc; - - initStringBuffer(&schema); - append(&schema, "CREATE TABLE %_content("); - append(&schema, " docid INTEGER PRIMARY KEY,"); - appendList(&schema, spec.nColumn, spec.azContentColumn); - append(&schema, ")"); - rc = sql_exec(db, spec.zDb, spec.zName, stringBufferData(&schema)); - stringBufferDestroy(&schema); - if( rc!=SQLITE_OK ) goto out; - - rc = sql_exec(db, spec.zDb, spec.zName, - "create table %_segments(" - " blockid INTEGER PRIMARY KEY," - " block blob" - ");" - ); - if( rc!=SQLITE_OK ) goto out; - - rc = sql_exec(db, spec.zDb, spec.zName, - "create table %_segdir(" - " level integer," - " idx integer," - " start_block integer," - " leaves_end_block integer," - " end_block integer," - " root blob," - " primary key(level, idx)" - ");"); - if( rc!=SQLITE_OK ) goto out; - - rc = constructVtab(db, (fts3Hash *)pAux, &spec, ppVTab, pzErr); - -out: - clearTableSpec(&spec); - return rc; -} - -/* Decide how to handle an SQL query. */ -static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ - fulltext_vtab *v = (fulltext_vtab *)pVTab; - int i; - FTSTRACE(("FTS3 BestIndex\n")); - - for(i=0; inConstraint; ++i){ - const struct sqlite3_index_constraint *pConstraint; - pConstraint = &pInfo->aConstraint[i]; - if( pConstraint->usable ) { - if( (pConstraint->iColumn==-1 || pConstraint->iColumn==v->nColumn+1) && - pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - pInfo->idxNum = QUERY_DOCID; /* lookup by docid */ - FTSTRACE(("FTS3 QUERY_DOCID\n")); - } else if( pConstraint->iColumn>=0 && pConstraint->iColumn<=v->nColumn && - pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - /* full-text search */ - pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn; - FTSTRACE(("FTS3 QUERY_FULLTEXT %d\n", pConstraint->iColumn)); - } else continue; - - pInfo->aConstraintUsage[i].argvIndex = 1; - pInfo->aConstraintUsage[i].omit = 1; - - /* An arbitrary value for now. - * TODO: Perhaps docid matches should be considered cheaper than - * full-text searches. */ - pInfo->estimatedCost = 1.0; - - return SQLITE_OK; - } - } - pInfo->idxNum = QUERY_GENERIC; - return SQLITE_OK; -} - -static int fulltextDisconnect(sqlite3_vtab *pVTab){ - FTSTRACE(("FTS3 Disconnect %p\n", pVTab)); - fulltext_vtab_destroy((fulltext_vtab *)pVTab); - return SQLITE_OK; -} - -static int fulltextDestroy(sqlite3_vtab *pVTab){ - fulltext_vtab *v = (fulltext_vtab *)pVTab; - int rc; - - FTSTRACE(("FTS3 Destroy %p\n", pVTab)); - rc = sql_exec(v->db, v->zDb, v->zName, - "drop table if exists %_content;" - "drop table if exists %_segments;" - "drop table if exists %_segdir;" - ); - if( rc!=SQLITE_OK ) return rc; - - fulltext_vtab_destroy((fulltext_vtab *)pVTab); - return SQLITE_OK; -} - -static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - fulltext_cursor *c; - - c = (fulltext_cursor *) sqlite3_malloc(sizeof(fulltext_cursor)); - if( c ){ - memset(c, 0, sizeof(fulltext_cursor)); - /* sqlite will initialize c->base */ - *ppCursor = &c->base; - FTSTRACE(("FTS3 Open %p: %p\n", pVTab, c)); - return SQLITE_OK; - }else{ - return SQLITE_NOMEM; - } -} - - -/* Free all of the dynamically allocated memory held by *q -*/ -static void queryClear(Query *q){ - int i; - for(i = 0; i < q->nTerms; ++i){ - sqlite3_free(q->pTerms[i].pTerm); - } - sqlite3_free(q->pTerms); - CLEAR(q); -} - -/* Free all of the dynamically allocated memory held by the -** Snippet -*/ -static void snippetClear(Snippet *p){ - sqlite3_free(p->aMatch); - sqlite3_free(p->zOffset); - sqlite3_free(p->zSnippet); - CLEAR(p); -} -/* -** Append a single entry to the p->aMatch[] log. -*/ -static void snippetAppendMatch( - Snippet *p, /* Append the entry to this snippet */ - int iCol, int iTerm, /* The column and query term */ - int iToken, /* Matching token in document */ - int iStart, int nByte /* Offset and size of the match */ -){ - int i; - struct snippetMatch *pMatch; - if( p->nMatch+1>=p->nAlloc ){ - p->nAlloc = p->nAlloc*2 + 10; - p->aMatch = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); - if( p->aMatch==0 ){ - p->nMatch = 0; - p->nAlloc = 0; - return; - } - } - i = p->nMatch++; - pMatch = &p->aMatch[i]; - pMatch->iCol = iCol; - pMatch->iTerm = iTerm; - pMatch->iToken = iToken; - pMatch->iStart = iStart; - pMatch->nByte = nByte; -} - -/* -** Sizing information for the circular buffer used in snippetOffsetsOfColumn() -*/ -#define FTS3_ROTOR_SZ (32) -#define FTS3_ROTOR_MASK (FTS3_ROTOR_SZ-1) - -/* -** Add entries to pSnippet->aMatch[] for every match that occurs against -** document zDoc[0..nDoc-1] which is stored in column iColumn. -*/ -static void snippetOffsetsOfColumn( - Query *pQuery, - Snippet *pSnippet, - int iColumn, - const char *zDoc, - int nDoc -){ - const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */ - sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */ - sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */ - fulltext_vtab *pVtab; /* The full text index */ - int nColumn; /* Number of columns in the index */ - const QueryTerm *aTerm; /* Query string terms */ - int nTerm; /* Number of query string terms */ - int i, j; /* Loop counters */ - int rc; /* Return code */ - unsigned int match, prevMatch; /* Phrase search bitmasks */ - const char *zToken; /* Next token from the tokenizer */ - int nToken; /* Size of zToken */ - int iBegin, iEnd, iPos; /* Offsets of beginning and end */ - - /* The following variables keep a circular buffer of the last - ** few tokens */ - unsigned int iRotor = 0; /* Index of current token */ - int iRotorBegin[FTS3_ROTOR_SZ]; /* Beginning offset of token */ - int iRotorLen[FTS3_ROTOR_SZ]; /* Length of token */ - - pVtab = pQuery->pFts; - nColumn = pVtab->nColumn; - pTokenizer = pVtab->pTokenizer; - pTModule = pTokenizer->pModule; - rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); - if( rc ) return; - pTCursor->pTokenizer = pTokenizer; - aTerm = pQuery->pTerms; - nTerm = pQuery->nTerms; - if( nTerm>=FTS3_ROTOR_SZ ){ - nTerm = FTS3_ROTOR_SZ - 1; - } - prevMatch = 0; - while(1){ - rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos); - if( rc ) break; - iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; - iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; - match = 0; - for(i=0; i=0 && iColnToken ) continue; - if( !aTerm[i].isPrefix && aTerm[i].nTerm1 && (prevMatch & (1<=0; j--){ - int k = (iRotor-j) & FTS3_ROTOR_MASK; - snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, - iRotorBegin[k], iRotorLen[k]); - } - } - } - prevMatch = match<<1; - iRotor++; - } - pTModule->xClose(pTCursor); -} - -/* -** Remove entries from the pSnippet structure to account for the NEAR -** operator. When this is called, pSnippet contains the list of token -** offsets produced by treating all NEAR operators as AND operators. -** This function removes any entries that should not be present after -** accounting for the NEAR restriction. For example, if the queried -** document is: -** -** "A B C D E A" -** -** and the query is: -** -** A NEAR/0 E -** -** then when this function is called the Snippet contains token offsets -** 0, 4 and 5. This function removes the "0" entry (because the first A -** is not near enough to an E). -*/ -static void trimSnippetOffsetsForNear(Query *pQuery, Snippet *pSnippet){ - int ii; - int iDir = 1; - - while(iDir>-2) { - assert( iDir==1 || iDir==-1 ); - for(ii=0; iinMatch; ii++){ - int jj; - int nNear; - struct snippetMatch *pMatch = &pSnippet->aMatch[ii]; - QueryTerm *pQueryTerm = &pQuery->pTerms[pMatch->iTerm]; - - if( (pMatch->iTerm+iDir)<0 - || (pMatch->iTerm+iDir)>=pQuery->nTerms - ){ - continue; - } - - nNear = pQueryTerm->nNear; - if( iDir<0 ){ - nNear = pQueryTerm[-1].nNear; - } - - if( pMatch->iTerm>=0 && nNear ){ - int isOk = 0; - int iNextTerm = pMatch->iTerm+iDir; - int iPrevTerm = iNextTerm; - - int iEndToken; - int iStartToken; - - if( iDir<0 ){ - int nPhrase = 1; - iStartToken = pMatch->iToken; - while( (pMatch->iTerm+nPhrase)nTerms - && pQuery->pTerms[pMatch->iTerm+nPhrase].iPhrase>1 - ){ - nPhrase++; - } - iEndToken = iStartToken + nPhrase - 1; - }else{ - iEndToken = pMatch->iToken; - iStartToken = pMatch->iToken+1-pQueryTerm->iPhrase; - } - - while( pQuery->pTerms[iNextTerm].iPhrase>1 ){ - iNextTerm--; - } - while( (iPrevTerm+1)nTerms && - pQuery->pTerms[iPrevTerm+1].iPhrase>1 - ){ - iPrevTerm++; - } - - for(jj=0; isOk==0 && jjnMatch; jj++){ - struct snippetMatch *p = &pSnippet->aMatch[jj]; - if( p->iCol==pMatch->iCol && (( - p->iTerm==iNextTerm && - p->iToken>iEndToken && - p->iToken<=iEndToken+nNear - ) || ( - p->iTerm==iPrevTerm && - p->iTokeniToken>=iStartToken-nNear - ))){ - isOk = 1; - } - } - if( !isOk ){ - for(jj=1-pQueryTerm->iPhrase; jj<=0; jj++){ - pMatch[jj].iTerm = -1; - } - ii = -1; - iDir = 1; - } - } - } - iDir -= 2; - } -} - -/* -** Compute all offsets for the current row of the query. -** If the offsets have already been computed, this routine is a no-op. -*/ -static void snippetAllOffsets(fulltext_cursor *p){ - int nColumn; - int iColumn, i; - int iFirst, iLast; - fulltext_vtab *pFts; - - if( p->snippet.nMatch ) return; - if( p->q.nTerms==0 ) return; - pFts = p->q.pFts; - nColumn = pFts->nColumn; - iColumn = (p->iCursorType - QUERY_FULLTEXT); - if( iColumn<0 || iColumn>=nColumn ){ - iFirst = 0; - iLast = nColumn-1; - }else{ - iFirst = iColumn; - iLast = iColumn; - } - for(i=iFirst; i<=iLast; i++){ - const char *zDoc; - int nDoc; - zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1); - nDoc = sqlite3_column_bytes(p->pStmt, i+1); - snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc); - } - - trimSnippetOffsetsForNear(&p->q, &p->snippet); -} - -/* -** Convert the information in the aMatch[] array of the snippet -** into the string zOffset[0..nOffset-1]. -*/ -static void snippetOffsetText(Snippet *p){ - int i; - int cnt = 0; - StringBuffer sb; - char zBuf[200]; - if( p->zOffset ) return; - initStringBuffer(&sb); - for(i=0; inMatch; i++){ - struct snippetMatch *pMatch = &p->aMatch[i]; - if( pMatch->iTerm>=0 ){ - /* If snippetMatch.iTerm is less than 0, then the match was - ** discarded as part of processing the NEAR operator (see the - ** trimSnippetOffsetsForNear() function for details). Ignore - ** it in this case - */ - zBuf[0] = ' '; - sprintf(&zBuf[cnt>0], "%d %d %d %d", pMatch->iCol, - pMatch->iTerm, pMatch->iStart, pMatch->nByte); - append(&sb, zBuf); - cnt++; - } - } - p->zOffset = stringBufferData(&sb); - p->nOffset = stringBufferLength(&sb); -} - -/* -** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set -** of matching words some of which might be in zDoc. zDoc is column -** number iCol. -** -** iBreak is suggested spot in zDoc where we could begin or end an -** excerpt. Return a value similar to iBreak but possibly adjusted -** to be a little left or right so that the break point is better. -*/ -static int wordBoundary( - int iBreak, /* The suggested break point */ - const char *zDoc, /* Document text */ - int nDoc, /* Number of bytes in zDoc[] */ - struct snippetMatch *aMatch, /* Matching words */ - int nMatch, /* Number of entries in aMatch[] */ - int iCol /* The column number for zDoc[] */ -){ - int i; - if( iBreak<=10 ){ - return 0; - } - if( iBreak>=nDoc-10 ){ - return nDoc; - } - for(i=0; i0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ - return aMatch[i-1].iStart; - } - } - for(i=1; i<=10; i++){ - if( safe_isspace(zDoc[iBreak-i]) ){ - return iBreak - i + 1; - } - if( safe_isspace(zDoc[iBreak+i]) ){ - return iBreak + i + 1; - } - } - return iBreak; -} - - - -/* -** Allowed values for Snippet.aMatch[].snStatus -*/ -#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */ -#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */ - -/* -** Generate the text of a snippet. -*/ -static void snippetText( - fulltext_cursor *pCursor, /* The cursor we need the snippet for */ - const char *zStartMark, /* Markup to appear before each match */ - const char *zEndMark, /* Markup to appear after each match */ - const char *zEllipsis /* Ellipsis mark */ -){ - int i, j; - struct snippetMatch *aMatch; - int nMatch; - int nDesired; - StringBuffer sb; - int tailCol; - int tailOffset; - int iCol; - int nDoc; - const char *zDoc; - int iStart, iEnd; - int tailEllipsis = 0; - int iMatch; - - - sqlite3_free(pCursor->snippet.zSnippet); - pCursor->snippet.zSnippet = 0; - aMatch = pCursor->snippet.aMatch; - nMatch = pCursor->snippet.nMatch; - initStringBuffer(&sb); - - for(i=0; iq.nTerms; i++){ - for(j=0; j0; i++){ - if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue; - nDesired--; - iCol = aMatch[i].iCol; - zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1); - nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1); - iStart = aMatch[i].iStart - 40; - iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol); - if( iStart<=10 ){ - iStart = 0; - } - if( iCol==tailCol && iStart<=tailOffset+20 ){ - iStart = tailOffset; - } - if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ - trimWhiteSpace(&sb); - appendWhiteSpace(&sb); - append(&sb, zEllipsis); - appendWhiteSpace(&sb); - } - iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; - iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); - if( iEnd>=nDoc-10 ){ - iEnd = nDoc; - tailEllipsis = 0; - }else{ - tailEllipsis = 1; - } - while( iMatchsnippet.zSnippet = stringBufferData(&sb); - pCursor->snippet.nSnippet = stringBufferLength(&sb); -} - - -/* -** Close the cursor. For additional information see the documentation -** on the xClose method of the virtual table interface. -*/ -static int fulltextClose(sqlite3_vtab_cursor *pCursor){ - fulltext_cursor *c = (fulltext_cursor *) pCursor; - FTSTRACE(("FTS3 Close %p\n", c)); - sqlite3_finalize(c->pStmt); - queryClear(&c->q); - snippetClear(&c->snippet); - if( c->result.nData!=0 ) dlrDestroy(&c->reader); - dataBufferDestroy(&c->result); - sqlite3_free(c); - return SQLITE_OK; -} - -static int fulltextNext(sqlite3_vtab_cursor *pCursor){ - fulltext_cursor *c = (fulltext_cursor *) pCursor; - int rc; - - FTSTRACE(("FTS3 Next %p\n", pCursor)); - snippetClear(&c->snippet); - if( c->iCursorType < QUERY_FULLTEXT ){ - /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ - rc = sqlite3_step(c->pStmt); - switch( rc ){ - case SQLITE_ROW: - c->eof = 0; - return SQLITE_OK; - case SQLITE_DONE: - c->eof = 1; - return SQLITE_OK; - default: - c->eof = 1; - return rc; - } - } else { /* full-text query */ - rc = sqlite3_reset(c->pStmt); - if( rc!=SQLITE_OK ) return rc; - - if( c->result.nData==0 || dlrAtEnd(&c->reader) ){ - c->eof = 1; - return SQLITE_OK; - } - rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader)); - dlrStep(&c->reader); - if( rc!=SQLITE_OK ) return rc; - /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ - rc = sqlite3_step(c->pStmt); - if( rc==SQLITE_ROW ){ /* the case we expect */ - c->eof = 0; - return SQLITE_OK; - } - /* an error occurred; abort */ - return rc==SQLITE_DONE ? SQLITE_ERROR : rc; - } -} - - -/* TODO(shess) If we pushed LeafReader to the top of the file, or to -** another file, term_select() could be pushed above -** docListOfTerm(). -*/ -static int termSelect(fulltext_vtab *v, int iColumn, - const char *pTerm, int nTerm, int isPrefix, - DocListType iType, DataBuffer *out); - -/* Return a DocList corresponding to the query term *pTerm. If *pTerm -** is the first term of a phrase query, go ahead and evaluate the phrase -** query and return the doclist for the entire phrase query. -** -** The resulting DL_DOCIDS doclist is stored in pResult, which is -** overwritten. -*/ -static int docListOfTerm( - fulltext_vtab *v, /* The full text index */ - int iColumn, /* column to restrict to. No restriction if >=nColumn */ - QueryTerm *pQTerm, /* Term we are looking for, or 1st term of a phrase */ - DataBuffer *pResult /* Write the result here */ -){ - DataBuffer left, right, new; - int i, rc; - - /* No phrase search if no position info. */ - assert( pQTerm->nPhrase==0 || DL_DEFAULT!=DL_DOCIDS ); - - /* This code should never be called with buffered updates. */ - assert( v->nPendingData<0 ); - - dataBufferInit(&left, 0); - rc = termSelect(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pQTerm->isPrefix, - (0nPhrase ? DL_POSITIONS : DL_DOCIDS), &left); - if( rc ) return rc; - for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){ - /* If this token is connected to the next by a NEAR operator, and - ** the next token is the start of a phrase, then set nPhraseRight - ** to the number of tokens in the phrase. Otherwise leave it at 1. - */ - int nPhraseRight = 1; - while( (i+nPhraseRight)<=pQTerm->nPhrase - && pQTerm[i+nPhraseRight].nNear==0 - ){ - nPhraseRight++; - } - - dataBufferInit(&right, 0); - rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, - pQTerm[i].isPrefix, DL_POSITIONS, &right); - if( rc ){ - dataBufferDestroy(&left); - return rc; - } - dataBufferInit(&new, 0); - docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, - pQTerm[i-1].nNear, pQTerm[i-1].iPhrase + nPhraseRight, - ((inPhrase) ? DL_POSITIONS : DL_DOCIDS), - &new); - dataBufferDestroy(&left); - dataBufferDestroy(&right); - left = new; - } - *pResult = left; - return SQLITE_OK; -} - -/* Add a new term pTerm[0..nTerm-1] to the query *q. -*/ -static void queryAdd(Query *q, const char *pTerm, int nTerm){ - QueryTerm *t; - ++q->nTerms; - q->pTerms = sqlite3_realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0])); - if( q->pTerms==0 ){ - q->nTerms = 0; - return; - } - t = &q->pTerms[q->nTerms - 1]; - CLEAR(t); - t->pTerm = sqlite3_malloc(nTerm+1); - memcpy(t->pTerm, pTerm, nTerm); - t->pTerm[nTerm] = 0; - t->nTerm = nTerm; - t->isOr = q->nextIsOr; - t->isPrefix = 0; - q->nextIsOr = 0; - t->iColumn = q->nextColumn; - q->nextColumn = q->dfltColumn; -} - -/* -** Check to see if the string zToken[0...nToken-1] matches any -** column name in the virtual table. If it does, -** return the zero-indexed column number. If not, return -1. -*/ -static int checkColumnSpecifier( - fulltext_vtab *pVtab, /* The virtual table */ - const char *zToken, /* Text of the token */ - int nToken /* Number of characters in the token */ -){ - int i; - for(i=0; inColumn; i++){ - if( memcmp(pVtab->azColumn[i], zToken, nToken)==0 - && pVtab->azColumn[i][nToken]==0 ){ - return i; - } - } - return -1; -} - -/* -** Parse the text at pSegment[0..nSegment-1]. Add additional terms -** to the query being assemblied in pQuery. -** -** inPhrase is true if pSegment[0..nSegement-1] is contained within -** double-quotes. If inPhrase is true, then the first term -** is marked with the number of terms in the phrase less one and -** OR and "-" syntax is ignored. If inPhrase is false, then every -** term found is marked with nPhrase=0 and OR and "-" syntax is significant. -*/ -static int tokenizeSegment( - sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */ - const char *pSegment, int nSegment, /* Query expression being parsed */ - int inPhrase, /* True if within "..." */ - Query *pQuery /* Append results here */ -){ - const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCursor; - int firstIndex = pQuery->nTerms; - int iCol; - int nTerm = 1; - - int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); - if( rc!=SQLITE_OK ) return rc; - pCursor->pTokenizer = pTokenizer; - - while( 1 ){ - const char *pToken; - int nToken, iBegin, iEnd, iPos; - - rc = pModule->xNext(pCursor, - &pToken, &nToken, - &iBegin, &iEnd, &iPos); - if( rc!=SQLITE_OK ) break; - if( !inPhrase && - pSegment[iEnd]==':' && - (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ - pQuery->nextColumn = iCol; - continue; - } - if( !inPhrase && pQuery->nTerms>0 && nToken==2 - && pSegment[iBegin+0]=='O' - && pSegment[iBegin+1]=='R' - ){ - pQuery->nextIsOr = 1; - continue; - } - if( !inPhrase && pQuery->nTerms>0 && !pQuery->nextIsOr && nToken==4 - && pSegment[iBegin+0]=='N' - && pSegment[iBegin+1]=='E' - && pSegment[iBegin+2]=='A' - && pSegment[iBegin+3]=='R' - ){ - QueryTerm *pTerm = &pQuery->pTerms[pQuery->nTerms-1]; - if( (iBegin+6)='0' && pSegment[iBegin+5]<='9' - ){ - pTerm->nNear = (pSegment[iBegin+5] - '0'); - nToken += 2; - if( pSegment[iBegin+6]>='0' && pSegment[iBegin+6]<=9 ){ - pTerm->nNear = pTerm->nNear * 10 + (pSegment[iBegin+6] - '0'); - iEnd++; - } - pModule->xNext(pCursor, &pToken, &nToken, &iBegin, &iEnd, &iPos); - } else { - pTerm->nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM; - } - pTerm->nNear++; - continue; - } - - queryAdd(pQuery, pToken, nToken); - if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ - pQuery->pTerms[pQuery->nTerms-1].isNot = 1; - } - if( iEndpTerms[pQuery->nTerms-1].isPrefix = 1; - } - pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm; - if( inPhrase ){ - nTerm++; - } - } - - if( inPhrase && pQuery->nTerms>firstIndex ){ - pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1; - } - - return pModule->xClose(pCursor); -} - -/* Parse a query string, yielding a Query object pQuery. -** -** The calling function will need to queryClear() to clean up -** the dynamically allocated memory held by pQuery. -*/ -static int parseQuery( - fulltext_vtab *v, /* The fulltext index */ - const char *zInput, /* Input text of the query string */ - int nInput, /* Size of the input text */ - int dfltColumn, /* Default column of the index to match against */ - Query *pQuery /* Write the parse results here. */ -){ - int iInput, inPhrase = 0; - int ii; - QueryTerm *aTerm; - - if( zInput==0 ) nInput = 0; - if( nInput<0 ) nInput = strlen(zInput); - pQuery->nTerms = 0; - pQuery->pTerms = NULL; - pQuery->nextIsOr = 0; - pQuery->nextColumn = dfltColumn; - pQuery->dfltColumn = dfltColumn; - pQuery->pFts = v; - - for(iInput=0; iInputiInput ){ - tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase, - pQuery); - } - iInput = i; - if( ipTerms; - for(ii=0; iinTerms; ii++){ - if( aTerm[ii].nNear || aTerm[ii].nPhrase ){ - while (aTerm[ii+aTerm[ii].nPhrase].nNear) { - aTerm[ii].nPhrase += (1 + aTerm[ii+aTerm[ii].nPhrase+1].nPhrase); - } - } - } - - return SQLITE_OK; -} - -/* TODO(shess) Refactor the code to remove this forward decl. */ -static int flushPendingTerms(fulltext_vtab *v); - -/* Perform a full-text query using the search expression in -** zInput[0..nInput-1]. Return a list of matching documents -** in pResult. -** -** Queries must match column iColumn. Or if iColumn>=nColumn -** they are allowed to match against any column. -*/ -static int fulltextQuery( - fulltext_vtab *v, /* The full text index */ - int iColumn, /* Match against this column by default */ - const char *zInput, /* The query string */ - int nInput, /* Number of bytes in zInput[] */ - DataBuffer *pResult, /* Write the result doclist here */ - Query *pQuery /* Put parsed query string here */ -){ - int i, iNext, rc; - DataBuffer left, right, or, new; - int nNot = 0; - QueryTerm *aTerm; - - /* TODO(shess) Instead of flushing pendingTerms, we could query for - ** the relevant term and merge the doclist into what we receive from - ** the database. Wait and see if this is a common issue, first. - ** - ** A good reason not to flush is to not generate update-related - ** error codes from here. - */ - - /* Flush any buffered updates before executing the query. */ - rc = flushPendingTerms(v); - if( rc!=SQLITE_OK ) return rc; - - /* TODO(shess) I think that the queryClear() calls below are not - ** necessary, because fulltextClose() already clears the query. - */ - rc = parseQuery(v, zInput, nInput, iColumn, pQuery); - if( rc!=SQLITE_OK ) return rc; - - /* Empty or NULL queries return no results. */ - if( pQuery->nTerms==0 ){ - dataBufferInit(pResult, 0); - return SQLITE_OK; - } - - /* Merge AND terms. */ - /* TODO(shess) I think we can early-exit if( i>nNot && left.nData==0 ). */ - aTerm = pQuery->pTerms; - for(i = 0; inTerms; i=iNext){ - if( aTerm[i].isNot ){ - /* Handle all NOT terms in a separate pass */ - nNot++; - iNext = i + aTerm[i].nPhrase+1; - continue; - } - iNext = i + aTerm[i].nPhrase + 1; - rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); - if( rc ){ - if( i!=nNot ) dataBufferDestroy(&left); - queryClear(pQuery); - return rc; - } - while( iNextnTerms && aTerm[iNext].isOr ){ - rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or); - iNext += aTerm[iNext].nPhrase + 1; - if( rc ){ - if( i!=nNot ) dataBufferDestroy(&left); - dataBufferDestroy(&right); - queryClear(pQuery); - return rc; - } - dataBufferInit(&new, 0); - docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); - dataBufferDestroy(&right); - dataBufferDestroy(&or); - right = new; - } - if( i==nNot ){ /* first term processed. */ - left = right; - }else{ - dataBufferInit(&new, 0); - docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new); - dataBufferDestroy(&right); - dataBufferDestroy(&left); - left = new; - } - } - - if( nNot==pQuery->nTerms ){ - /* We do not yet know how to handle a query of only NOT terms */ - return SQLITE_ERROR; - } - - /* Do the EXCEPT terms */ - for(i=0; inTerms; i += aTerm[i].nPhrase + 1){ - if( !aTerm[i].isNot ) continue; - rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); - if( rc ){ - queryClear(pQuery); - dataBufferDestroy(&left); - return rc; - } - dataBufferInit(&new, 0); - docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new); - dataBufferDestroy(&right); - dataBufferDestroy(&left); - left = new; - } - - *pResult = left; - return rc; -} - -/* -** This is the xFilter interface for the virtual table. See -** the virtual table xFilter method documentation for additional -** information. -** -** If idxNum==QUERY_GENERIC then do a full table scan against -** the %_content table. -** -** If idxNum==QUERY_DOCID then do a docid lookup for a single entry -** in the %_content table. -** -** If idxNum>=QUERY_FULLTEXT then use the full text index. The -** column on the left-hand side of the MATCH operator is column -** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand -** side of the MATCH operator. -*/ -/* TODO(shess) Upgrade the cursor initialization and destruction to -** account for fulltextFilter() being called multiple times on the -** same cursor. The current solution is very fragile. Apply fix to -** fts3 as appropriate. -*/ -static int fulltextFilter( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, const char *idxStr, /* Which indexing scheme to use */ - int argc, sqlite3_value **argv /* Arguments for the indexing scheme */ -){ - fulltext_cursor *c = (fulltext_cursor *) pCursor; - fulltext_vtab *v = cursor_vtab(c); - int rc; - StringBuffer sb; - - FTSTRACE(("FTS3 Filter %p\n",pCursor)); - - initStringBuffer(&sb); - append(&sb, "SELECT docid, "); - appendList(&sb, v->nColumn, v->azContentColumn); - append(&sb, " FROM %_content"); - if( idxNum!=QUERY_GENERIC ) append(&sb, " WHERE docid = ?"); - sqlite3_finalize(c->pStmt); - rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, stringBufferData(&sb)); - stringBufferDestroy(&sb); - if( rc!=SQLITE_OK ) return rc; - - c->iCursorType = idxNum; - switch( idxNum ){ - case QUERY_GENERIC: - break; - - case QUERY_DOCID: - rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0])); - if( rc!=SQLITE_OK ) return rc; - break; - - default: /* full-text search */ - { - const char *zQuery = (const char *)sqlite3_value_text(argv[0]); - assert( idxNum<=QUERY_FULLTEXT+v->nColumn); - assert( argc==1 ); - queryClear(&c->q); - if( c->result.nData!=0 ){ - /* This case happens if the same cursor is used repeatedly. */ - dlrDestroy(&c->reader); - dataBufferReset(&c->result); - }else{ - dataBufferInit(&c->result, 0); - } - rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q); - if( rc!=SQLITE_OK ) return rc; - if( c->result.nData!=0 ){ - dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); - } - break; - } - } - - return fulltextNext(pCursor); -} - -/* This is the xEof method of the virtual table. The SQLite core -** calls this routine to find out if it has reached the end of -** a query's results set. -*/ -static int fulltextEof(sqlite3_vtab_cursor *pCursor){ - fulltext_cursor *c = (fulltext_cursor *) pCursor; - return c->eof; -} - -/* This is the xColumn method of the virtual table. The SQLite -** core calls this method during a query when it needs the value -** of a column from the virtual table. This method needs to use -** one of the sqlite3_result_*() routines to store the requested -** value back in the pContext. -*/ -static int fulltextColumn(sqlite3_vtab_cursor *pCursor, - sqlite3_context *pContext, int idxCol){ - fulltext_cursor *c = (fulltext_cursor *) pCursor; - fulltext_vtab *v = cursor_vtab(c); - - if( idxColnColumn ){ - sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); - sqlite3_result_value(pContext, pVal); - }else if( idxCol==v->nColumn ){ - /* The extra column whose name is the same as the table. - ** Return a blob which is a pointer to the cursor - */ - sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); - }else if( idxCol==v->nColumn+1 ){ - /* The docid column, which is an alias for rowid. */ - sqlite3_value *pVal = sqlite3_column_value(c->pStmt, 0); - sqlite3_result_value(pContext, pVal); - } - return SQLITE_OK; -} - -/* This is the xRowid method. The SQLite core calls this routine to -** retrieve the rowid for the current row of the result set. fts3 -** exposes %_content.docid as the rowid for the virtual table. The -** rowid should be written to *pRowid. -*/ -static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - fulltext_cursor *c = (fulltext_cursor *) pCursor; - - *pRowid = sqlite3_column_int64(c->pStmt, 0); - return SQLITE_OK; -} - -/* Add all terms in [zText] to pendingTerms table. If [iColumn] > 0, -** we also store positions and offsets in the hash table using that -** column number. -*/ -static int buildTerms(fulltext_vtab *v, sqlite_int64 iDocid, - const char *zText, int iColumn){ - sqlite3_tokenizer *pTokenizer = v->pTokenizer; - sqlite3_tokenizer_cursor *pCursor; - const char *pToken; - int nTokenBytes; - int iStartOffset, iEndOffset, iPosition; - int rc; - - rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor); - if( rc!=SQLITE_OK ) return rc; - - pCursor->pTokenizer = pTokenizer; - while( SQLITE_OK==(rc=pTokenizer->pModule->xNext(pCursor, - &pToken, &nTokenBytes, - &iStartOffset, &iEndOffset, - &iPosition)) ){ - DLCollector *p; - int nData; /* Size of doclist before our update. */ - - /* Positions can't be negative; we use -1 as a terminator - * internally. Token can't be NULL or empty. */ - if( iPosition<0 || pToken == NULL || nTokenBytes == 0 ){ - rc = SQLITE_ERROR; - break; - } - - p = fts3HashFind(&v->pendingTerms, pToken, nTokenBytes); - if( p==NULL ){ - nData = 0; - p = dlcNew(iDocid, DL_DEFAULT); - fts3HashInsert(&v->pendingTerms, pToken, nTokenBytes, p); - - /* Overhead for our hash table entry, the key, and the value. */ - v->nPendingData += sizeof(struct fts3HashElem)+sizeof(*p)+nTokenBytes; - }else{ - nData = p->b.nData; - if( p->dlw.iPrevDocid!=iDocid ) dlcNext(p, iDocid); - } - if( iColumn>=0 ){ - dlcAddPos(p, iColumn, iPosition, iStartOffset, iEndOffset); - } - - /* Accumulate data added by dlcNew or dlcNext, and dlcAddPos. */ - v->nPendingData += p->b.nData-nData; - } - - /* TODO(shess) Check return? Should this be able to cause errors at - ** this point? Actually, same question about sqlite3_finalize(), - ** though one could argue that failure there means that the data is - ** not durable. *ponder* - */ - pTokenizer->pModule->xClose(pCursor); - if( SQLITE_DONE == rc ) return SQLITE_OK; - return rc; -} - -/* Add doclists for all terms in [pValues] to pendingTerms table. */ -static int insertTerms(fulltext_vtab *v, sqlite_int64 iDocid, - sqlite3_value **pValues){ - int i; - for(i = 0; i < v->nColumn ; ++i){ - char *zText = (char*)sqlite3_value_text(pValues[i]); - int rc = buildTerms(v, iDocid, zText, i); - if( rc!=SQLITE_OK ) return rc; - } - return SQLITE_OK; -} - -/* Add empty doclists for all terms in the given row's content to -** pendingTerms. -*/ -static int deleteTerms(fulltext_vtab *v, sqlite_int64 iDocid){ - const char **pValues; - int i, rc; - - /* TODO(shess) Should we allow such tables at all? */ - if( DL_DEFAULT==DL_DOCIDS ) return SQLITE_ERROR; - - rc = content_select(v, iDocid, &pValues); - if( rc!=SQLITE_OK ) return rc; - - for(i = 0 ; i < v->nColumn; ++i) { - rc = buildTerms(v, iDocid, pValues[i], -1); - if( rc!=SQLITE_OK ) break; - } - - freeStringArray(v->nColumn, pValues); - return SQLITE_OK; -} - -/* TODO(shess) Refactor the code to remove this forward decl. */ -static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid); - -/* Insert a row into the %_content table; set *piDocid to be the ID of the -** new row. Add doclists for terms to pendingTerms. -*/ -static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestDocid, - sqlite3_value **pValues, sqlite_int64 *piDocid){ - int rc; - - rc = content_insert(v, pRequestDocid, pValues); /* execute an SQL INSERT */ - if( rc!=SQLITE_OK ) return rc; - - /* docid column is an alias for rowid. */ - *piDocid = sqlite3_last_insert_rowid(v->db); - rc = initPendingTerms(v, *piDocid); - if( rc!=SQLITE_OK ) return rc; - - return insertTerms(v, *piDocid, pValues); -} - -/* Delete a row from the %_content table; add empty doclists for terms -** to pendingTerms. -*/ -static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ - int rc = initPendingTerms(v, iRow); - if( rc!=SQLITE_OK ) return rc; - - rc = deleteTerms(v, iRow); - if( rc!=SQLITE_OK ) return rc; - - return content_delete(v, iRow); /* execute an SQL DELETE */ -} - -/* Update a row in the %_content table; add delete doclists to -** pendingTerms for old terms not in the new data, add insert doclists -** to pendingTerms for terms in the new data. -*/ -static int index_update(fulltext_vtab *v, sqlite_int64 iRow, - sqlite3_value **pValues){ - int rc = initPendingTerms(v, iRow); - if( rc!=SQLITE_OK ) return rc; - - /* Generate an empty doclist for each term that previously appeared in this - * row. */ - rc = deleteTerms(v, iRow); - if( rc!=SQLITE_OK ) return rc; - - rc = content_update(v, pValues, iRow); /* execute an SQL UPDATE */ - if( rc!=SQLITE_OK ) return rc; - - /* Now add positions for terms which appear in the updated row. */ - return insertTerms(v, iRow, pValues); -} - -/*******************************************************************/ -/* InteriorWriter is used to collect terms and block references into -** interior nodes in %_segments. See commentary at top of file for -** format. -*/ - -/* How large interior nodes can grow. */ -#define INTERIOR_MAX 2048 - -/* Minimum number of terms per interior node (except the root). This -** prevents large terms from making the tree too skinny - must be >0 -** so that the tree always makes progress. Note that the min tree -** fanout will be INTERIOR_MIN_TERMS+1. -*/ -#define INTERIOR_MIN_TERMS 7 -#if INTERIOR_MIN_TERMS<1 -# error INTERIOR_MIN_TERMS must be greater than 0. -#endif - -/* ROOT_MAX controls how much data is stored inline in the segment -** directory. -*/ -/* TODO(shess) Push ROOT_MAX down to whoever is writing things. It's -** only here so that interiorWriterRootInfo() and leafWriterRootInfo() -** can both see it, but if the caller passed it in, we wouldn't even -** need a define. -*/ -#define ROOT_MAX 1024 -#if ROOT_MAXterm, 0); - dataBufferReplace(&block->term, pTerm, nTerm); - - n = fts3PutVarint(c, iHeight); - n += fts3PutVarint(c+n, iChildBlock); - dataBufferInit(&block->data, INTERIOR_MAX); - dataBufferReplace(&block->data, c, n); - } - return block; -} - -#ifndef NDEBUG -/* Verify that the data is readable as an interior node. */ -static void interiorBlockValidate(InteriorBlock *pBlock){ - const char *pData = pBlock->data.pData; - int nData = pBlock->data.nData; - int n, iDummy; - sqlite_int64 iBlockid; - - assert( nData>0 ); - assert( pData!=0 ); - assert( pData+nData>pData ); - - /* Must lead with height of node as a varint(n), n>0 */ - n = fts3GetVarint32(pData, &iDummy); - assert( n>0 ); - assert( iDummy>0 ); - assert( n0 ); - assert( n<=nData ); - pData += n; - nData -= n; - - /* Zero or more terms of positive length */ - if( nData!=0 ){ - /* First term is not delta-encoded. */ - n = fts3GetVarint32(pData, &iDummy); - assert( n>0 ); - assert( iDummy>0 ); - assert( n+iDummy>0); - assert( n+iDummy<=nData ); - pData += n+iDummy; - nData -= n+iDummy; - - /* Following terms delta-encoded. */ - while( nData!=0 ){ - /* Length of shared prefix. */ - n = fts3GetVarint32(pData, &iDummy); - assert( n>0 ); - assert( iDummy>=0 ); - assert( n0 ); - assert( iDummy>0 ); - assert( n+iDummy>0); - assert( n+iDummy<=nData ); - pData += n+iDummy; - nData -= n+iDummy; - } - } -} -#define ASSERT_VALID_INTERIOR_BLOCK(x) interiorBlockValidate(x) -#else -#define ASSERT_VALID_INTERIOR_BLOCK(x) assert( 1 ) -#endif - -typedef struct InteriorWriter { - int iHeight; /* from 0 at leaves. */ - InteriorBlock *first, *last; - struct InteriorWriter *parentWriter; - - DataBuffer term; /* Last term written to block "last". */ - sqlite_int64 iOpeningChildBlock; /* First child block in block "last". */ -#ifndef NDEBUG - sqlite_int64 iLastChildBlock; /* for consistency checks. */ -#endif -} InteriorWriter; - -/* Initialize an interior node where pTerm[nTerm] marks the leftmost -** term in the tree. iChildBlock is the leftmost child block at the -** next level down the tree. -*/ -static void interiorWriterInit(int iHeight, const char *pTerm, int nTerm, - sqlite_int64 iChildBlock, - InteriorWriter *pWriter){ - InteriorBlock *block; - assert( iHeight>0 ); - CLEAR(pWriter); - - pWriter->iHeight = iHeight; - pWriter->iOpeningChildBlock = iChildBlock; -#ifndef NDEBUG - pWriter->iLastChildBlock = iChildBlock; -#endif - block = interiorBlockNew(iHeight, iChildBlock, pTerm, nTerm); - pWriter->last = pWriter->first = block; - ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); - dataBufferInit(&pWriter->term, 0); -} - -/* Append the child node rooted at iChildBlock to the interior node, -** with pTerm[nTerm] as the leftmost term in iChildBlock's subtree. -*/ -static void interiorWriterAppend(InteriorWriter *pWriter, - const char *pTerm, int nTerm, - sqlite_int64 iChildBlock){ - char c[VARINT_MAX+VARINT_MAX]; - int n, nPrefix = 0; - - ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); - - /* The first term written into an interior node is actually - ** associated with the second child added (the first child was added - ** in interiorWriterInit, or in the if clause at the bottom of this - ** function). That term gets encoded straight up, with nPrefix left - ** at 0. - */ - if( pWriter->term.nData==0 ){ - n = fts3PutVarint(c, nTerm); - }else{ - while( nPrefixterm.nData && - pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){ - nPrefix++; - } - - n = fts3PutVarint(c, nPrefix); - n += fts3PutVarint(c+n, nTerm-nPrefix); - } - -#ifndef NDEBUG - pWriter->iLastChildBlock++; -#endif - assert( pWriter->iLastChildBlock==iChildBlock ); - - /* Overflow to a new block if the new term makes the current block - ** too big, and the current block already has enough terms. - */ - if( pWriter->last->data.nData+n+nTerm-nPrefix>INTERIOR_MAX && - iChildBlock-pWriter->iOpeningChildBlock>INTERIOR_MIN_TERMS ){ - pWriter->last->next = interiorBlockNew(pWriter->iHeight, iChildBlock, - pTerm, nTerm); - pWriter->last = pWriter->last->next; - pWriter->iOpeningChildBlock = iChildBlock; - dataBufferReset(&pWriter->term); - }else{ - dataBufferAppend2(&pWriter->last->data, c, n, - pTerm+nPrefix, nTerm-nPrefix); - dataBufferReplace(&pWriter->term, pTerm, nTerm); - } - ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); -} - -/* Free the space used by pWriter, including the linked-list of -** InteriorBlocks, and parentWriter, if present. -*/ -static int interiorWriterDestroy(InteriorWriter *pWriter){ - InteriorBlock *block = pWriter->first; - - while( block!=NULL ){ - InteriorBlock *b = block; - block = block->next; - dataBufferDestroy(&b->term); - dataBufferDestroy(&b->data); - sqlite3_free(b); - } - if( pWriter->parentWriter!=NULL ){ - interiorWriterDestroy(pWriter->parentWriter); - sqlite3_free(pWriter->parentWriter); - } - dataBufferDestroy(&pWriter->term); - SCRAMBLE(pWriter); - return SQLITE_OK; -} - -/* If pWriter can fit entirely in ROOT_MAX, return it as the root info -** directly, leaving *piEndBlockid unchanged. Otherwise, flush -** pWriter to %_segments, building a new layer of interior nodes, and -** recursively ask for their root into. -*/ -static int interiorWriterRootInfo(fulltext_vtab *v, InteriorWriter *pWriter, - char **ppRootInfo, int *pnRootInfo, - sqlite_int64 *piEndBlockid){ - InteriorBlock *block = pWriter->first; - sqlite_int64 iBlockid = 0; - int rc; - - /* If we can fit the segment inline */ - if( block==pWriter->last && block->data.nDatadata.pData; - *pnRootInfo = block->data.nData; - return SQLITE_OK; - } - - /* Flush the first block to %_segments, and create a new level of - ** interior node. - */ - ASSERT_VALID_INTERIOR_BLOCK(block); - rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); - if( rc!=SQLITE_OK ) return rc; - *piEndBlockid = iBlockid; - - pWriter->parentWriter = sqlite3_malloc(sizeof(*pWriter->parentWriter)); - interiorWriterInit(pWriter->iHeight+1, - block->term.pData, block->term.nData, - iBlockid, pWriter->parentWriter); - - /* Flush additional blocks and append to the higher interior - ** node. - */ - for(block=block->next; block!=NULL; block=block->next){ - ASSERT_VALID_INTERIOR_BLOCK(block); - rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); - if( rc!=SQLITE_OK ) return rc; - *piEndBlockid = iBlockid; - - interiorWriterAppend(pWriter->parentWriter, - block->term.pData, block->term.nData, iBlockid); - } - - /* Parent node gets the chance to be the root. */ - return interiorWriterRootInfo(v, pWriter->parentWriter, - ppRootInfo, pnRootInfo, piEndBlockid); -} - -/****************************************************************/ -/* InteriorReader is used to read off the data from an interior node -** (see comment at top of file for the format). -*/ -typedef struct InteriorReader { - const char *pData; - int nData; - - DataBuffer term; /* previous term, for decoding term delta. */ - - sqlite_int64 iBlockid; -} InteriorReader; - -static void interiorReaderDestroy(InteriorReader *pReader){ - dataBufferDestroy(&pReader->term); - SCRAMBLE(pReader); -} - -/* TODO(shess) The assertions are great, but what if we're in NDEBUG -** and the blob is empty or otherwise contains suspect data? -*/ -static void interiorReaderInit(const char *pData, int nData, - InteriorReader *pReader){ - int n, nTerm; - - /* Require at least the leading flag byte */ - assert( nData>0 ); - assert( pData[0]!='\0' ); - - CLEAR(pReader); - - /* Decode the base blockid, and set the cursor to the first term. */ - n = fts3GetVarint(pData+1, &pReader->iBlockid); - assert( 1+n<=nData ); - pReader->pData = pData+1+n; - pReader->nData = nData-(1+n); - - /* A single-child interior node (such as when a leaf node was too - ** large for the segment directory) won't have any terms. - ** Otherwise, decode the first term. - */ - if( pReader->nData==0 ){ - dataBufferInit(&pReader->term, 0); - }else{ - n = fts3GetVarint32(pReader->pData, &nTerm); - dataBufferInit(&pReader->term, nTerm); - dataBufferReplace(&pReader->term, pReader->pData+n, nTerm); - assert( n+nTerm<=pReader->nData ); - pReader->pData += n+nTerm; - pReader->nData -= n+nTerm; - } -} - -static int interiorReaderAtEnd(InteriorReader *pReader){ - return pReader->term.nData==0; -} - -static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){ - return pReader->iBlockid; -} - -static int interiorReaderTermBytes(InteriorReader *pReader){ - assert( !interiorReaderAtEnd(pReader) ); - return pReader->term.nData; -} -static const char *interiorReaderTerm(InteriorReader *pReader){ - assert( !interiorReaderAtEnd(pReader) ); - return pReader->term.pData; -} - -/* Step forward to the next term in the node. */ -static void interiorReaderStep(InteriorReader *pReader){ - assert( !interiorReaderAtEnd(pReader) ); - - /* If the last term has been read, signal eof, else construct the - ** next term. - */ - if( pReader->nData==0 ){ - dataBufferReset(&pReader->term); - }else{ - int n, nPrefix, nSuffix; - - n = fts3GetVarint32(pReader->pData, &nPrefix); - n += fts3GetVarint32(pReader->pData+n, &nSuffix); - - /* Truncate the current term and append suffix data. */ - pReader->term.nData = nPrefix; - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); - - assert( n+nSuffix<=pReader->nData ); - pReader->pData += n+nSuffix; - pReader->nData -= n+nSuffix; - } - pReader->iBlockid++; -} - -/* Compare the current term to pTerm[nTerm], returning strcmp-style -** results. If isPrefix, equality means equal through nTerm bytes. -*/ -static int interiorReaderTermCmp(InteriorReader *pReader, - const char *pTerm, int nTerm, int isPrefix){ - const char *pReaderTerm = interiorReaderTerm(pReader); - int nReaderTerm = interiorReaderTermBytes(pReader); - int c, n = nReaderTerm0 ) return -1; - if( nTerm>0 ) return 1; - return 0; - } - - c = memcmp(pReaderTerm, pTerm, n); - if( c!=0 ) return c; - if( isPrefix && n==nTerm ) return 0; - return nReaderTerm - nTerm; -} - -/****************************************************************/ -/* LeafWriter is used to collect terms and associated doclist data -** into leaf blocks in %_segments (see top of file for format info). -** Expected usage is: -** -** LeafWriter writer; -** leafWriterInit(0, 0, &writer); -** while( sorted_terms_left_to_process ){ -** // data is doclist data for that term. -** rc = leafWriterStep(v, &writer, pTerm, nTerm, pData, nData); -** if( rc!=SQLITE_OK ) goto err; -** } -** rc = leafWriterFinalize(v, &writer); -**err: -** leafWriterDestroy(&writer); -** return rc; -** -** leafWriterStep() may write a collected leaf out to %_segments. -** leafWriterFinalize() finishes writing any buffered data and stores -** a root node in %_segdir. leafWriterDestroy() frees all buffers and -** InteriorWriters allocated as part of writing this segment. -** -** TODO(shess) Document leafWriterStepMerge(). -*/ - -/* Put terms with data this big in their own block. */ -#define STANDALONE_MIN 1024 - -/* Keep leaf blocks below this size. */ -#define LEAF_MAX 2048 - -typedef struct LeafWriter { - int iLevel; - int idx; - sqlite_int64 iStartBlockid; /* needed to create the root info */ - sqlite_int64 iEndBlockid; /* when we're done writing. */ - - DataBuffer term; /* previous encoded term */ - DataBuffer data; /* encoding buffer */ - - /* bytes of first term in the current node which distinguishes that - ** term from the last term of the previous node. - */ - int nTermDistinct; - - InteriorWriter parentWriter; /* if we overflow */ - int has_parent; -} LeafWriter; - -static void leafWriterInit(int iLevel, int idx, LeafWriter *pWriter){ - CLEAR(pWriter); - pWriter->iLevel = iLevel; - pWriter->idx = idx; - - dataBufferInit(&pWriter->term, 32); - - /* Start out with a reasonably sized block, though it can grow. */ - dataBufferInit(&pWriter->data, LEAF_MAX); -} - -#ifndef NDEBUG -/* Verify that the data is readable as a leaf node. */ -static void leafNodeValidate(const char *pData, int nData){ - int n, iDummy; - - if( nData==0 ) return; - assert( nData>0 ); - assert( pData!=0 ); - assert( pData+nData>pData ); - - /* Must lead with a varint(0) */ - n = fts3GetVarint32(pData, &iDummy); - assert( iDummy==0 ); - assert( n>0 ); - assert( n0 ); - assert( iDummy>0 ); - assert( n+iDummy>0 ); - assert( n+iDummy0 ); - assert( iDummy>0 ); - assert( n+iDummy>0 ); - assert( n+iDummy<=nData ); - ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL); - pData += n+iDummy; - nData -= n+iDummy; - - /* Verify that trailing terms and doclists also are readable. */ - while( nData!=0 ){ - n = fts3GetVarint32(pData, &iDummy); - assert( n>0 ); - assert( iDummy>=0 ); - assert( n0 ); - assert( iDummy>0 ); - assert( n+iDummy>0 ); - assert( n+iDummy0 ); - assert( iDummy>0 ); - assert( n+iDummy>0 ); - assert( n+iDummy<=nData ); - ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL); - pData += n+iDummy; - nData -= n+iDummy; - } -} -#define ASSERT_VALID_LEAF_NODE(p, n) leafNodeValidate(p, n) -#else -#define ASSERT_VALID_LEAF_NODE(p, n) assert( 1 ) -#endif - -/* Flush the current leaf node to %_segments, and adding the resulting -** blockid and the starting term to the interior node which will -** contain it. -*/ -static int leafWriterInternalFlush(fulltext_vtab *v, LeafWriter *pWriter, - int iData, int nData){ - sqlite_int64 iBlockid = 0; - const char *pStartingTerm; - int nStartingTerm, rc, n; - - /* Must have the leading varint(0) flag, plus at least some - ** valid-looking data. - */ - assert( nData>2 ); - assert( iData>=0 ); - assert( iData+nData<=pWriter->data.nData ); - ASSERT_VALID_LEAF_NODE(pWriter->data.pData+iData, nData); - - rc = block_insert(v, pWriter->data.pData+iData, nData, &iBlockid); - if( rc!=SQLITE_OK ) return rc; - assert( iBlockid!=0 ); - - /* Reconstruct the first term in the leaf for purposes of building - ** the interior node. - */ - n = fts3GetVarint32(pWriter->data.pData+iData+1, &nStartingTerm); - pStartingTerm = pWriter->data.pData+iData+1+n; - assert( pWriter->data.nData>iData+1+n+nStartingTerm ); - assert( pWriter->nTermDistinct>0 ); - assert( pWriter->nTermDistinct<=nStartingTerm ); - nStartingTerm = pWriter->nTermDistinct; - - if( pWriter->has_parent ){ - interiorWriterAppend(&pWriter->parentWriter, - pStartingTerm, nStartingTerm, iBlockid); - }else{ - interiorWriterInit(1, pStartingTerm, nStartingTerm, iBlockid, - &pWriter->parentWriter); - pWriter->has_parent = 1; - } - - /* Track the span of this segment's leaf nodes. */ - if( pWriter->iEndBlockid==0 ){ - pWriter->iEndBlockid = pWriter->iStartBlockid = iBlockid; - }else{ - pWriter->iEndBlockid++; - assert( iBlockid==pWriter->iEndBlockid ); - } - - return SQLITE_OK; -} -static int leafWriterFlush(fulltext_vtab *v, LeafWriter *pWriter){ - int rc = leafWriterInternalFlush(v, pWriter, 0, pWriter->data.nData); - if( rc!=SQLITE_OK ) return rc; - - /* Re-initialize the output buffer. */ - dataBufferReset(&pWriter->data); - - return SQLITE_OK; -} - -/* Fetch the root info for the segment. If the entire leaf fits -** within ROOT_MAX, then it will be returned directly, otherwise it -** will be flushed and the root info will be returned from the -** interior node. *piEndBlockid is set to the blockid of the last -** interior or leaf node written to disk (0 if none are written at -** all). -*/ -static int leafWriterRootInfo(fulltext_vtab *v, LeafWriter *pWriter, - char **ppRootInfo, int *pnRootInfo, - sqlite_int64 *piEndBlockid){ - /* we can fit the segment entirely inline */ - if( !pWriter->has_parent && pWriter->data.nDatadata.pData; - *pnRootInfo = pWriter->data.nData; - *piEndBlockid = 0; - return SQLITE_OK; - } - - /* Flush remaining leaf data. */ - if( pWriter->data.nData>0 ){ - int rc = leafWriterFlush(v, pWriter); - if( rc!=SQLITE_OK ) return rc; - } - - /* We must have flushed a leaf at some point. */ - assert( pWriter->has_parent ); - - /* Tenatively set the end leaf blockid as the end blockid. If the - ** interior node can be returned inline, this will be the final - ** blockid, otherwise it will be overwritten by - ** interiorWriterRootInfo(). - */ - *piEndBlockid = pWriter->iEndBlockid; - - return interiorWriterRootInfo(v, &pWriter->parentWriter, - ppRootInfo, pnRootInfo, piEndBlockid); -} - -/* Collect the rootInfo data and store it into the segment directory. -** This has the effect of flushing the segment's leaf data to -** %_segments, and also flushing any interior nodes to %_segments. -*/ -static int leafWriterFinalize(fulltext_vtab *v, LeafWriter *pWriter){ - sqlite_int64 iEndBlockid; - char *pRootInfo; - int rc, nRootInfo; - - rc = leafWriterRootInfo(v, pWriter, &pRootInfo, &nRootInfo, &iEndBlockid); - if( rc!=SQLITE_OK ) return rc; - - /* Don't bother storing an entirely empty segment. */ - if( iEndBlockid==0 && nRootInfo==0 ) return SQLITE_OK; - - return segdir_set(v, pWriter->iLevel, pWriter->idx, - pWriter->iStartBlockid, pWriter->iEndBlockid, - iEndBlockid, pRootInfo, nRootInfo); -} - -static void leafWriterDestroy(LeafWriter *pWriter){ - if( pWriter->has_parent ) interiorWriterDestroy(&pWriter->parentWriter); - dataBufferDestroy(&pWriter->term); - dataBufferDestroy(&pWriter->data); -} - -/* Encode a term into the leafWriter, delta-encoding as appropriate. -** Returns the length of the new term which distinguishes it from the -** previous term, which can be used to set nTermDistinct when a node -** boundary is crossed. -*/ -static int leafWriterEncodeTerm(LeafWriter *pWriter, - const char *pTerm, int nTerm){ - char c[VARINT_MAX+VARINT_MAX]; - int n, nPrefix = 0; - - assert( nTerm>0 ); - while( nPrefixterm.nData && - pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){ - nPrefix++; - /* Failing this implies that the terms weren't in order. */ - assert( nPrefixdata.nData==0 ){ - /* Encode the node header and leading term as: - ** varint(0) - ** varint(nTerm) - ** char pTerm[nTerm] - */ - n = fts3PutVarint(c, '\0'); - n += fts3PutVarint(c+n, nTerm); - dataBufferAppend2(&pWriter->data, c, n, pTerm, nTerm); - }else{ - /* Delta-encode the term as: - ** varint(nPrefix) - ** varint(nSuffix) - ** char pTermSuffix[nSuffix] - */ - n = fts3PutVarint(c, nPrefix); - n += fts3PutVarint(c+n, nTerm-nPrefix); - dataBufferAppend2(&pWriter->data, c, n, pTerm+nPrefix, nTerm-nPrefix); - } - dataBufferReplace(&pWriter->term, pTerm, nTerm); - - return nPrefix+1; -} - -/* Used to avoid a memmove when a large amount of doclist data is in -** the buffer. This constructs a node and term header before -** iDoclistData and flushes the resulting complete node using -** leafWriterInternalFlush(). -*/ -static int leafWriterInlineFlush(fulltext_vtab *v, LeafWriter *pWriter, - const char *pTerm, int nTerm, - int iDoclistData){ - char c[VARINT_MAX+VARINT_MAX]; - int iData, n = fts3PutVarint(c, 0); - n += fts3PutVarint(c+n, nTerm); - - /* There should always be room for the header. Even if pTerm shared - ** a substantial prefix with the previous term, the entire prefix - ** could be constructed from earlier data in the doclist, so there - ** should be room. - */ - assert( iDoclistData>=n+nTerm ); - - iData = iDoclistData-(n+nTerm); - memcpy(pWriter->data.pData+iData, c, n); - memcpy(pWriter->data.pData+iData+n, pTerm, nTerm); - - return leafWriterInternalFlush(v, pWriter, iData, pWriter->data.nData-iData); -} - -/* Push pTerm[nTerm] along with the doclist data to the leaf layer of -** %_segments. -*/ -static int leafWriterStepMerge(fulltext_vtab *v, LeafWriter *pWriter, - const char *pTerm, int nTerm, - DLReader *pReaders, int nReaders){ - char c[VARINT_MAX+VARINT_MAX]; - int iTermData = pWriter->data.nData, iDoclistData; - int i, nData, n, nActualData, nActual, rc, nTermDistinct; - - ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData); - nTermDistinct = leafWriterEncodeTerm(pWriter, pTerm, nTerm); - - /* Remember nTermDistinct if opening a new node. */ - if( iTermData==0 ) pWriter->nTermDistinct = nTermDistinct; - - iDoclistData = pWriter->data.nData; - - /* Estimate the length of the merged doclist so we can leave space - ** to encode it. - */ - for(i=0, nData=0; idata, c, n); - - docListMerge(&pWriter->data, pReaders, nReaders); - ASSERT_VALID_DOCLIST(DL_DEFAULT, - pWriter->data.pData+iDoclistData+n, - pWriter->data.nData-iDoclistData-n, NULL); - - /* The actual amount of doclist data at this point could be smaller - ** than the length we encoded. Additionally, the space required to - ** encode this length could be smaller. For small doclists, this is - ** not a big deal, we can just use memmove() to adjust things. - */ - nActualData = pWriter->data.nData-(iDoclistData+n); - nActual = fts3PutVarint(c, nActualData); - assert( nActualData<=nData ); - assert( nActual<=n ); - - /* If the new doclist is big enough for force a standalone leaf - ** node, we can immediately flush it inline without doing the - ** memmove(). - */ - /* TODO(shess) This test matches leafWriterStep(), which does this - ** test before it knows the cost to varint-encode the term and - ** doclist lengths. At some point, change to - ** pWriter->data.nData-iTermData>STANDALONE_MIN. - */ - if( nTerm+nActualData>STANDALONE_MIN ){ - /* Push leaf node from before this term. */ - if( iTermData>0 ){ - rc = leafWriterInternalFlush(v, pWriter, 0, iTermData); - if( rc!=SQLITE_OK ) return rc; - - pWriter->nTermDistinct = nTermDistinct; - } - - /* Fix the encoded doclist length. */ - iDoclistData += n - nActual; - memcpy(pWriter->data.pData+iDoclistData, c, nActual); - - /* Push the standalone leaf node. */ - rc = leafWriterInlineFlush(v, pWriter, pTerm, nTerm, iDoclistData); - if( rc!=SQLITE_OK ) return rc; - - /* Leave the node empty. */ - dataBufferReset(&pWriter->data); - - return rc; - } - - /* At this point, we know that the doclist was small, so do the - ** memmove if indicated. - */ - if( nActualdata.pData+iDoclistData+nActual, - pWriter->data.pData+iDoclistData+n, - pWriter->data.nData-(iDoclistData+n)); - pWriter->data.nData -= n-nActual; - } - - /* Replace written length with actual length. */ - memcpy(pWriter->data.pData+iDoclistData, c, nActual); - - /* If the node is too large, break things up. */ - /* TODO(shess) This test matches leafWriterStep(), which does this - ** test before it knows the cost to varint-encode the term and - ** doclist lengths. At some point, change to - ** pWriter->data.nData>LEAF_MAX. - */ - if( iTermData+nTerm+nActualData>LEAF_MAX ){ - /* Flush out the leading data as a node */ - rc = leafWriterInternalFlush(v, pWriter, 0, iTermData); - if( rc!=SQLITE_OK ) return rc; - - pWriter->nTermDistinct = nTermDistinct; - - /* Rebuild header using the current term */ - n = fts3PutVarint(pWriter->data.pData, 0); - n += fts3PutVarint(pWriter->data.pData+n, nTerm); - memcpy(pWriter->data.pData+n, pTerm, nTerm); - n += nTerm; - - /* There should always be room, because the previous encoding - ** included all data necessary to construct the term. - */ - assert( ndata.nData-iDoclistDatadata.pData+n, - pWriter->data.pData+iDoclistData, - pWriter->data.nData-iDoclistData); - pWriter->data.nData -= iDoclistData-n; - } - ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData); - - return SQLITE_OK; -} - -/* Push pTerm[nTerm] along with the doclist data to the leaf layer of -** %_segments. -*/ -/* TODO(shess) Revise writeZeroSegment() so that doclists are -** constructed directly in pWriter->data. -*/ -static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter, - const char *pTerm, int nTerm, - const char *pData, int nData){ - int rc; - DLReader reader; - - dlrInit(&reader, DL_DEFAULT, pData, nData); - rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1); - dlrDestroy(&reader); - - return rc; -} - - -/****************************************************************/ -/* LeafReader is used to iterate over an individual leaf node. */ -typedef struct LeafReader { - DataBuffer term; /* copy of current term. */ - - const char *pData; /* data for current term. */ - int nData; -} LeafReader; - -static void leafReaderDestroy(LeafReader *pReader){ - dataBufferDestroy(&pReader->term); - SCRAMBLE(pReader); -} - -static int leafReaderAtEnd(LeafReader *pReader){ - return pReader->nData<=0; -} - -/* Access the current term. */ -static int leafReaderTermBytes(LeafReader *pReader){ - return pReader->term.nData; -} -static const char *leafReaderTerm(LeafReader *pReader){ - assert( pReader->term.nData>0 ); - return pReader->term.pData; -} - -/* Access the doclist data for the current term. */ -static int leafReaderDataBytes(LeafReader *pReader){ - int nData; - assert( pReader->term.nData>0 ); - fts3GetVarint32(pReader->pData, &nData); - return nData; -} -static const char *leafReaderData(LeafReader *pReader){ - int n, nData; - assert( pReader->term.nData>0 ); - n = fts3GetVarint32(pReader->pData, &nData); - return pReader->pData+n; -} - -static void leafReaderInit(const char *pData, int nData, - LeafReader *pReader){ - int nTerm, n; - - assert( nData>0 ); - assert( pData[0]=='\0' ); - - CLEAR(pReader); - - /* Read the first term, skipping the header byte. */ - n = fts3GetVarint32(pData+1, &nTerm); - dataBufferInit(&pReader->term, nTerm); - dataBufferReplace(&pReader->term, pData+1+n, nTerm); - - /* Position after the first term. */ - assert( 1+n+nTermpData = pData+1+n+nTerm; - pReader->nData = nData-1-n-nTerm; -} - -/* Step the reader forward to the next term. */ -static void leafReaderStep(LeafReader *pReader){ - int n, nData, nPrefix, nSuffix; - assert( !leafReaderAtEnd(pReader) ); - - /* Skip previous entry's data block. */ - n = fts3GetVarint32(pReader->pData, &nData); - assert( n+nData<=pReader->nData ); - pReader->pData += n+nData; - pReader->nData -= n+nData; - - if( !leafReaderAtEnd(pReader) ){ - /* Construct the new term using a prefix from the old term plus a - ** suffix from the leaf data. - */ - n = fts3GetVarint32(pReader->pData, &nPrefix); - n += fts3GetVarint32(pReader->pData+n, &nSuffix); - assert( n+nSuffixnData ); - pReader->term.nData = nPrefix; - dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); - - pReader->pData += n+nSuffix; - pReader->nData -= n+nSuffix; - } -} - -/* strcmp-style comparison of pReader's current term against pTerm. -** If isPrefix, equality means equal through nTerm bytes. -*/ -static int leafReaderTermCmp(LeafReader *pReader, - const char *pTerm, int nTerm, int isPrefix){ - int c, n = pReader->term.nDataterm.nData : nTerm; - if( n==0 ){ - if( pReader->term.nData>0 ) return -1; - if(nTerm>0 ) return 1; - return 0; - } - - c = memcmp(pReader->term.pData, pTerm, n); - if( c!=0 ) return c; - if( isPrefix && n==nTerm ) return 0; - return pReader->term.nData - nTerm; -} - - -/****************************************************************/ -/* LeavesReader wraps LeafReader to allow iterating over the entire -** leaf layer of the tree. -*/ -typedef struct LeavesReader { - int idx; /* Index within the segment. */ - - sqlite3_stmt *pStmt; /* Statement we're streaming leaves from. */ - int eof; /* we've seen SQLITE_DONE from pStmt. */ - - LeafReader leafReader; /* reader for the current leaf. */ - DataBuffer rootData; /* root data for inline. */ -} LeavesReader; - -/* Access the current term. */ -static int leavesReaderTermBytes(LeavesReader *pReader){ - assert( !pReader->eof ); - return leafReaderTermBytes(&pReader->leafReader); -} -static const char *leavesReaderTerm(LeavesReader *pReader){ - assert( !pReader->eof ); - return leafReaderTerm(&pReader->leafReader); -} - -/* Access the doclist data for the current term. */ -static int leavesReaderDataBytes(LeavesReader *pReader){ - assert( !pReader->eof ); - return leafReaderDataBytes(&pReader->leafReader); -} -static const char *leavesReaderData(LeavesReader *pReader){ - assert( !pReader->eof ); - return leafReaderData(&pReader->leafReader); -} - -static int leavesReaderAtEnd(LeavesReader *pReader){ - return pReader->eof; -} - -/* loadSegmentLeaves() may not read all the way to SQLITE_DONE, thus -** leaving the statement handle open, which locks the table. -*/ -/* TODO(shess) This "solution" is not satisfactory. Really, there -** should be check-in function for all statement handles which -** arranges to call sqlite3_reset(). This most likely will require -** modification to control flow all over the place, though, so for now -** just punt. -** -** Note the the current system assumes that segment merges will run to -** completion, which is why this particular probably hasn't arisen in -** this case. Probably a brittle assumption. -*/ -static int leavesReaderReset(LeavesReader *pReader){ - return sqlite3_reset(pReader->pStmt); -} - -static void leavesReaderDestroy(LeavesReader *pReader){ - leafReaderDestroy(&pReader->leafReader); - dataBufferDestroy(&pReader->rootData); - SCRAMBLE(pReader); -} - -/* Initialize pReader with the given root data (if iStartBlockid==0 -** the leaf data was entirely contained in the root), or from the -** stream of blocks between iStartBlockid and iEndBlockid, inclusive. -*/ -static int leavesReaderInit(fulltext_vtab *v, - int idx, - sqlite_int64 iStartBlockid, - sqlite_int64 iEndBlockid, - const char *pRootData, int nRootData, - LeavesReader *pReader){ - CLEAR(pReader); - pReader->idx = idx; - - dataBufferInit(&pReader->rootData, 0); - if( iStartBlockid==0 ){ - /* Entire leaf level fit in root data. */ - dataBufferReplace(&pReader->rootData, pRootData, nRootData); - leafReaderInit(pReader->rootData.pData, pReader->rootData.nData, - &pReader->leafReader); - }else{ - sqlite3_stmt *s; - int rc = sql_get_leaf_statement(v, idx, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 1, iStartBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 2, iEndBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_step(s); - if( rc==SQLITE_DONE ){ - pReader->eof = 1; - return SQLITE_OK; - } - if( rc!=SQLITE_ROW ) return rc; - - pReader->pStmt = s; - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), - sqlite3_column_bytes(pReader->pStmt, 0), - &pReader->leafReader); - } - return SQLITE_OK; -} - -/* Step the current leaf forward to the next term. If we reach the -** end of the current leaf, step forward to the next leaf block. -*/ -static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){ - assert( !leavesReaderAtEnd(pReader) ); - leafReaderStep(&pReader->leafReader); - - if( leafReaderAtEnd(&pReader->leafReader) ){ - int rc; - if( pReader->rootData.pData ){ - pReader->eof = 1; - return SQLITE_OK; - } - rc = sqlite3_step(pReader->pStmt); - if( rc!=SQLITE_ROW ){ - pReader->eof = 1; - return rc==SQLITE_DONE ? SQLITE_OK : rc; - } - leafReaderDestroy(&pReader->leafReader); - leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), - sqlite3_column_bytes(pReader->pStmt, 0), - &pReader->leafReader); - } - return SQLITE_OK; -} - -/* Order LeavesReaders by their term, ignoring idx. Readers at eof -** always sort to the end. -*/ -static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){ - if( leavesReaderAtEnd(lr1) ){ - if( leavesReaderAtEnd(lr2) ) return 0; - return 1; - } - if( leavesReaderAtEnd(lr2) ) return -1; - - return leafReaderTermCmp(&lr1->leafReader, - leavesReaderTerm(lr2), leavesReaderTermBytes(lr2), - 0); -} - -/* Similar to leavesReaderTermCmp(), with additional ordering by idx -** so that older segments sort before newer segments. -*/ -static int leavesReaderCmp(LeavesReader *lr1, LeavesReader *lr2){ - int c = leavesReaderTermCmp(lr1, lr2); - if( c!=0 ) return c; - return lr1->idx-lr2->idx; -} - -/* Assume that pLr[1]..pLr[nLr] are sorted. Bubble pLr[0] into its -** sorted position. -*/ -static void leavesReaderReorder(LeavesReader *pLr, int nLr){ - while( nLr>1 && leavesReaderCmp(pLr, pLr+1)>0 ){ - LeavesReader tmp = pLr[0]; - pLr[0] = pLr[1]; - pLr[1] = tmp; - nLr--; - pLr++; - } -} - -/* Initializes pReaders with the segments from level iLevel, returning -** the number of segments in *piReaders. Leaves pReaders in sorted -** order. -*/ -static int leavesReadersInit(fulltext_vtab *v, int iLevel, - LeavesReader *pReaders, int *piReaders){ - sqlite3_stmt *s; - int i, rc = sql_get_statement(v, SEGDIR_SELECT_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int(s, 1, iLevel); - if( rc!=SQLITE_OK ) return rc; - - i = 0; - while( (rc = sqlite3_step(s))==SQLITE_ROW ){ - sqlite_int64 iStart = sqlite3_column_int64(s, 0); - sqlite_int64 iEnd = sqlite3_column_int64(s, 1); - const char *pRootData = sqlite3_column_blob(s, 2); - int nRootData = sqlite3_column_bytes(s, 2); - - assert( i0 ){ - leavesReaderDestroy(&pReaders[i]); - } - return rc; - } - - *piReaders = i; - - /* Leave our results sorted by term, then age. */ - while( i-- ){ - leavesReaderReorder(pReaders+i, *piReaders-i); - } - return SQLITE_OK; -} - -/* Merge doclists from pReaders[nReaders] into a single doclist, which -** is written to pWriter. Assumes pReaders is ordered oldest to -** newest. -*/ -/* TODO(shess) Consider putting this inline in segmentMerge(). */ -static int leavesReadersMerge(fulltext_vtab *v, - LeavesReader *pReaders, int nReaders, - LeafWriter *pWriter){ - DLReader dlReaders[MERGE_COUNT]; - const char *pTerm = leavesReaderTerm(pReaders); - int i, nTerm = leavesReaderTermBytes(pReaders); - - assert( nReaders<=MERGE_COUNT ); - - for(i=0; i0 ){ - rc = leavesReaderStep(v, lrs+i); - if( rc!=SQLITE_OK ) goto err; - - /* Reorder by term, then by age. */ - leavesReaderReorder(lrs+i, MERGE_COUNT-i); - } - } - - for(i=0; i0 ); - - for(rc=SQLITE_OK; rc==SQLITE_OK && !leavesReaderAtEnd(pReader); - rc=leavesReaderStep(v, pReader)){ - /* TODO(shess) Really want leavesReaderTermCmp(), but that name is - ** already taken to compare the terms of two LeavesReaders. Think - ** on a better name. [Meanwhile, break encapsulation rather than - ** use a confusing name.] - */ - int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix); - if( c>0 ) break; /* Past any possible matches. */ - if( c==0 ){ - const char *pData = leavesReaderData(pReader); - int iBuffer, nData = leavesReaderDataBytes(pReader); - - /* Find the first empty buffer. */ - for(iBuffer=0; iBuffer0 ){ - assert(pBuffers!=NULL); - memcpy(p, pBuffers, nBuffers*sizeof(*pBuffers)); - sqlite3_free(pBuffers); - } - pBuffers = p; - } - dataBufferInit(&(pBuffers[nBuffers]), 0); - nBuffers++; - } - - /* At this point, must have an empty at iBuffer. */ - assert(iBufferpData, p->nData); - - /* dataBufferReset() could allow a large doclist to blow up - ** our memory requirements. - */ - if( p->nCapacity<1024 ){ - dataBufferReset(p); - }else{ - dataBufferDestroy(p); - dataBufferInit(p, 0); - } - } - } - } - } - - /* Union all the doclists together into *out. */ - /* TODO(shess) What if *out is big? Sigh. */ - if( rc==SQLITE_OK && nBuffers>0 ){ - int iBuffer; - for(iBuffer=0; iBuffer0 ){ - if( out->nData==0 ){ - dataBufferSwap(out, &(pBuffers[iBuffer])); - }else{ - docListAccumulateUnion(out, pBuffers[iBuffer].pData, - pBuffers[iBuffer].nData); - } - } - } - } - - while( nBuffers-- ){ - dataBufferDestroy(&(pBuffers[nBuffers])); - } - if( pBuffers!=NULL ) sqlite3_free(pBuffers); - - return rc; -} - -/* Call loadSegmentLeavesInt() with pData/nData as input. */ -static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData, - const char *pTerm, int nTerm, int isPrefix, - DataBuffer *out){ - LeavesReader reader; - int rc; - - assert( nData>1 ); - assert( *pData=='\0' ); - rc = leavesReaderInit(v, 0, 0, 0, pData, nData, &reader); - if( rc!=SQLITE_OK ) return rc; - - rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out); - leavesReaderReset(&reader); - leavesReaderDestroy(&reader); - return rc; -} - -/* Call loadSegmentLeavesInt() with the leaf nodes from iStartLeaf to -** iEndLeaf (inclusive) as input, and merge the resulting doclist into -** out. -*/ -static int loadSegmentLeaves(fulltext_vtab *v, - sqlite_int64 iStartLeaf, sqlite_int64 iEndLeaf, - const char *pTerm, int nTerm, int isPrefix, - DataBuffer *out){ - int rc; - LeavesReader reader; - - assert( iStartLeaf<=iEndLeaf ); - rc = leavesReaderInit(v, 0, iStartLeaf, iEndLeaf, NULL, 0, &reader); - if( rc!=SQLITE_OK ) return rc; - - rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out); - leavesReaderReset(&reader); - leavesReaderDestroy(&reader); - return rc; -} - -/* Taking pData/nData as an interior node, find the sequence of child -** nodes which could include pTerm/nTerm/isPrefix. Note that the -** interior node terms logically come between the blocks, so there is -** one more blockid than there are terms (that block contains terms >= -** the last interior-node term). -*/ -/* TODO(shess) The calling code may already know that the end child is -** not worth calculating, because the end may be in a later sibling -** node. Consider whether breaking symmetry is worthwhile. I suspect -** it is not worthwhile. -*/ -static void getChildrenContaining(const char *pData, int nData, - const char *pTerm, int nTerm, int isPrefix, - sqlite_int64 *piStartChild, - sqlite_int64 *piEndChild){ - InteriorReader reader; - - assert( nData>1 ); - assert( *pData!='\0' ); - interiorReaderInit(pData, nData, &reader); - - /* Scan for the first child which could contain pTerm/nTerm. */ - while( !interiorReaderAtEnd(&reader) ){ - if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break; - interiorReaderStep(&reader); - } - *piStartChild = interiorReaderCurrentBlockid(&reader); - - /* Keep scanning to find a term greater than our term, using prefix - ** comparison if indicated. If isPrefix is false, this will be the - ** same blockid as the starting block. - */ - while( !interiorReaderAtEnd(&reader) ){ - if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break; - interiorReaderStep(&reader); - } - *piEndChild = interiorReaderCurrentBlockid(&reader); - - interiorReaderDestroy(&reader); - - /* Children must ascend, and if !prefix, both must be the same. */ - assert( *piEndChild>=*piStartChild ); - assert( isPrefix || *piStartChild==*piEndChild ); -} - -/* Read block at iBlockid and pass it with other params to -** getChildrenContaining(). -*/ -static int loadAndGetChildrenContaining( - fulltext_vtab *v, - sqlite_int64 iBlockid, - const char *pTerm, int nTerm, int isPrefix, - sqlite_int64 *piStartChild, sqlite_int64 *piEndChild -){ - sqlite3_stmt *s = NULL; - int rc; - - assert( iBlockid!=0 ); - assert( pTerm!=NULL ); - assert( nTerm!=0 ); /* TODO(shess) Why not allow this? */ - assert( piStartChild!=NULL ); - assert( piEndChild!=NULL ); - - rc = sql_get_statement(v, BLOCK_SELECT_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_bind_int64(s, 1, iBlockid); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3_step(s); - if( rc==SQLITE_DONE ) return SQLITE_ERROR; - if( rc!=SQLITE_ROW ) return rc; - - getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0), - pTerm, nTerm, isPrefix, piStartChild, piEndChild); - - /* We expect only one row. We must execute another sqlite3_step() - * to complete the iteration; otherwise the table will remain - * locked. */ - rc = sqlite3_step(s); - if( rc==SQLITE_ROW ) return SQLITE_ERROR; - if( rc!=SQLITE_DONE ) return rc; - - return SQLITE_OK; -} - -/* Traverse the tree represented by pData[nData] looking for -** pTerm[nTerm], placing its doclist into *out. This is internal to -** loadSegment() to make error-handling cleaner. -*/ -static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData, - sqlite_int64 iLeavesEnd, - const char *pTerm, int nTerm, int isPrefix, - DataBuffer *out){ - /* Special case where root is a leaf. */ - if( *pData=='\0' ){ - return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out); - }else{ - int rc; - sqlite_int64 iStartChild, iEndChild; - - /* Process pData as an interior node, then loop down the tree - ** until we find the set of leaf nodes to scan for the term. - */ - getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, - &iStartChild, &iEndChild); - while( iStartChild>iLeavesEnd ){ - sqlite_int64 iNextStart, iNextEnd; - rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix, - &iNextStart, &iNextEnd); - if( rc!=SQLITE_OK ) return rc; - - /* If we've branched, follow the end branch, too. */ - if( iStartChild!=iEndChild ){ - sqlite_int64 iDummy; - rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix, - &iDummy, &iNextEnd); - if( rc!=SQLITE_OK ) return rc; - } - - assert( iNextStart<=iNextEnd ); - iStartChild = iNextStart; - iEndChild = iNextEnd; - } - assert( iStartChild<=iLeavesEnd ); - assert( iEndChild<=iLeavesEnd ); - - /* Scan through the leaf segments for doclists. */ - return loadSegmentLeaves(v, iStartChild, iEndChild, - pTerm, nTerm, isPrefix, out); - } -} - -/* Call loadSegmentInt() to collect the doclist for pTerm/nTerm, then -** merge its doclist over *out (any duplicate doclists read from the -** segment rooted at pData will overwrite those in *out). -*/ -/* TODO(shess) Consider changing this to determine the depth of the -** leaves using either the first characters of interior nodes (when -** ==1, we're one level above the leaves), or the first character of -** the root (which will describe the height of the tree directly). -** Either feels somewhat tricky to me. -*/ -/* TODO(shess) The current merge is likely to be slow for large -** doclists (though it should process from newest/smallest to -** oldest/largest, so it may not be that bad). It might be useful to -** modify things to allow for N-way merging. This could either be -** within a segment, with pairwise merges across segments, or across -** all segments at once. -*/ -static int loadSegment(fulltext_vtab *v, const char *pData, int nData, - sqlite_int64 iLeavesEnd, - const char *pTerm, int nTerm, int isPrefix, - DataBuffer *out){ - DataBuffer result; - int rc; - - assert( nData>1 ); - - /* This code should never be called with buffered updates. */ - assert( v->nPendingData<0 ); - - dataBufferInit(&result, 0); - rc = loadSegmentInt(v, pData, nData, iLeavesEnd, - pTerm, nTerm, isPrefix, &result); - if( rc==SQLITE_OK && result.nData>0 ){ - if( out->nData==0 ){ - DataBuffer tmp = *out; - *out = result; - result = tmp; - }else{ - DataBuffer merged; - DLReader readers[2]; - - dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); - dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); - dataBufferInit(&merged, out->nData+result.nData); - docListMerge(&merged, readers, 2); - dataBufferDestroy(out); - *out = merged; - dlrDestroy(&readers[0]); - dlrDestroy(&readers[1]); - } - } - dataBufferDestroy(&result); - return rc; -} - -/* Scan the database and merge together the posting lists for the term -** into *out. -*/ -static int termSelect(fulltext_vtab *v, int iColumn, - const char *pTerm, int nTerm, int isPrefix, - DocListType iType, DataBuffer *out){ - DataBuffer doclist; - sqlite3_stmt *s; - int rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s); - if( rc!=SQLITE_OK ) return rc; - - /* This code should never be called with buffered updates. */ - assert( v->nPendingData<0 ); - - dataBufferInit(&doclist, 0); - - /* Traverse the segments from oldest to newest so that newer doclist - ** elements for given docids overwrite older elements. - */ - while( (rc = sqlite3_step(s))==SQLITE_ROW ){ - const char *pData = sqlite3_column_blob(s, 0); - const int nData = sqlite3_column_bytes(s, 0); - const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1); - rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix, - &doclist); - if( rc!=SQLITE_OK ) goto err; - } - if( rc==SQLITE_DONE ){ - if( doclist.nData!=0 ){ - /* TODO(shess) The old term_select_all() code applied the column - ** restrict as we merged segments, leading to smaller buffers. - ** This is probably worthwhile to bring back, once the new storage - ** system is checked in. - */ - if( iColumn==v->nColumn) iColumn = -1; - docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, - iColumn, iType, out); - } - rc = SQLITE_OK; - } - - err: - dataBufferDestroy(&doclist); - return rc; -} - -/****************************************************************/ -/* Used to hold hashtable data for sorting. */ -typedef struct TermData { - const char *pTerm; - int nTerm; - DLCollector *pCollector; -} TermData; - -/* Orders TermData elements in strcmp fashion ( <0 for less-than, 0 -** for equal, >0 for greater-than). -*/ -static int termDataCmp(const void *av, const void *bv){ - const TermData *a = (const TermData *)av; - const TermData *b = (const TermData *)bv; - int n = a->nTermnTerm ? a->nTerm : b->nTerm; - int c = memcmp(a->pTerm, b->pTerm, n); - if( c!=0 ) return c; - return a->nTerm-b->nTerm; -} - -/* Order pTerms data by term, then write a new level 0 segment using -** LeafWriter. -*/ -static int writeZeroSegment(fulltext_vtab *v, fts3Hash *pTerms){ - fts3HashElem *e; - int idx, rc, i, n; - TermData *pData; - LeafWriter writer; - DataBuffer dl; - - /* Determine the next index at level 0, merging as necessary. */ - rc = segdirNextIndex(v, 0, &idx); - if( rc!=SQLITE_OK ) return rc; - - n = fts3HashCount(pTerms); - pData = sqlite3_malloc(n*sizeof(TermData)); - - for(i = 0, e = fts3HashFirst(pTerms); e; i++, e = fts3HashNext(e)){ - assert( i1 ) qsort(pData, n, sizeof(*pData), termDataCmp); - - /* TODO(shess) Refactor so that we can write directly to the segment - ** DataBuffer, as happens for segment merges. - */ - leafWriterInit(0, idx, &writer); - dataBufferInit(&dl, 0); - for(i=0; inPendingData>=0 ){ - fts3HashElem *e; - for(e=fts3HashFirst(&v->pendingTerms); e; e=fts3HashNext(e)){ - dlcDelete(fts3HashData(e)); - } - fts3HashClear(&v->pendingTerms); - v->nPendingData = -1; - } - return SQLITE_OK; -} - -/* If pendingTerms has data, flush it to a level-zero segment, and -** free it. -*/ -static int flushPendingTerms(fulltext_vtab *v){ - if( v->nPendingData>=0 ){ - int rc = writeZeroSegment(v, &v->pendingTerms); - if( rc==SQLITE_OK ) clearPendingTerms(v); - return rc; - } - return SQLITE_OK; -} - -/* If pendingTerms is "too big", or docid is out of order, flush it. -** Regardless, be certain that pendingTerms is initialized for use. -*/ -static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid){ - /* TODO(shess) Explore whether partially flushing the buffer on - ** forced-flush would provide better performance. I suspect that if - ** we ordered the doclists by size and flushed the largest until the - ** buffer was half empty, that would let the less frequent terms - ** generate longer doclists. - */ - if( iDocid<=v->iPrevDocid || v->nPendingData>kPendingThreshold ){ - int rc = flushPendingTerms(v); - if( rc!=SQLITE_OK ) return rc; - } - if( v->nPendingData<0 ){ - fts3HashInit(&v->pendingTerms, FTS3_HASH_STRING, 1); - v->nPendingData = 0; - } - v->iPrevDocid = iDocid; - return SQLITE_OK; -} - -/* This function implements the xUpdate callback; it is the top-level entry - * point for inserting, deleting or updating a row in a full-text table. */ -static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, - sqlite_int64 *pRowid){ - fulltext_vtab *v = (fulltext_vtab *) pVtab; - int rc; - - FTSTRACE(("FTS3 Update %p\n", pVtab)); - - if( nArg<2 ){ - rc = index_delete(v, sqlite3_value_int64(ppArg[0])); - } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){ - /* An update: - * ppArg[0] = old rowid - * ppArg[1] = new rowid - * ppArg[2..2+v->nColumn-1] = values - * ppArg[2+v->nColumn] = value for magic column (we ignore this) - * ppArg[2+v->nColumn+1] = value for docid - */ - sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]); - if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER || - sqlite3_value_int64(ppArg[1]) != rowid ){ - rc = SQLITE_ERROR; /* we don't allow changing the rowid */ - }else if( sqlite3_value_type(ppArg[2+v->nColumn+1]) != SQLITE_INTEGER || - sqlite3_value_int64(ppArg[2+v->nColumn+1]) != rowid ){ - rc = SQLITE_ERROR; /* we don't allow changing the docid */ - }else{ - assert( nArg==2+v->nColumn+2); - rc = index_update(v, rowid, &ppArg[2]); - } - } else { - /* An insert: - * ppArg[1] = requested rowid - * ppArg[2..2+v->nColumn-1] = values - * ppArg[2+v->nColumn] = value for magic column (we ignore this) - * ppArg[2+v->nColumn+1] = value for docid - */ - sqlite3_value *pRequestDocid = ppArg[2+v->nColumn+1]; - assert( nArg==2+v->nColumn+2); - if( SQLITE_NULL != sqlite3_value_type(pRequestDocid) && - SQLITE_NULL != sqlite3_value_type(ppArg[1]) ){ - /* TODO(shess) Consider allowing this to work if the values are - ** identical. I'm inclined to discourage that usage, though, - ** given that both rowid and docid are special columns. Better - ** would be to define one or the other as the default winner, - ** but should it be fts3-centric (docid) or SQLite-centric - ** (rowid)? - */ - rc = SQLITE_ERROR; - }else{ - if( SQLITE_NULL == sqlite3_value_type(pRequestDocid) ){ - pRequestDocid = ppArg[1]; - } - rc = index_insert(v, pRequestDocid, &ppArg[2], pRowid); - } - } - - return rc; -} - -static int fulltextSync(sqlite3_vtab *pVtab){ - FTSTRACE(("FTS3 xSync()\n")); - return flushPendingTerms((fulltext_vtab *)pVtab); -} - -static int fulltextBegin(sqlite3_vtab *pVtab){ - fulltext_vtab *v = (fulltext_vtab *) pVtab; - FTSTRACE(("FTS3 xBegin()\n")); - - /* Any buffered updates should have been cleared by the previous - ** transaction. - */ - assert( v->nPendingData<0 ); - return clearPendingTerms(v); -} - -static int fulltextCommit(sqlite3_vtab *pVtab){ - fulltext_vtab *v = (fulltext_vtab *) pVtab; - FTSTRACE(("FTS3 xCommit()\n")); - - /* Buffered updates should have been cleared by fulltextSync(). */ - assert( v->nPendingData<0 ); - return clearPendingTerms(v); -} - -static int fulltextRollback(sqlite3_vtab *pVtab){ - FTSTRACE(("FTS3 xRollback()\n")); - return clearPendingTerms((fulltext_vtab *)pVtab); -} - -/* -** Implementation of the snippet() function for FTS3 -*/ -static void snippetFunc( - sqlite3_context *pContext, - int argc, - sqlite3_value **argv -){ - fulltext_cursor *pCursor; - if( argc<1 ) return; - if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || - sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ - sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1); - }else{ - const char *zStart = ""; - const char *zEnd = ""; - const char *zEllipsis = "..."; - memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); - if( argc>=2 ){ - zStart = (const char*)sqlite3_value_text(argv[1]); - if( argc>=3 ){ - zEnd = (const char*)sqlite3_value_text(argv[2]); - if( argc>=4 ){ - zEllipsis = (const char*)sqlite3_value_text(argv[3]); - } - } - } - snippetAllOffsets(pCursor); - snippetText(pCursor, zStart, zEnd, zEllipsis); - sqlite3_result_text(pContext, pCursor->snippet.zSnippet, - pCursor->snippet.nSnippet, SQLITE_STATIC); - } -} - -/* -** Implementation of the offsets() function for FTS3 -*/ -static void snippetOffsetsFunc( - sqlite3_context *pContext, - int argc, - sqlite3_value **argv -){ - fulltext_cursor *pCursor; - if( argc<1 ) return; - if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || - sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ - sqlite3_result_error(pContext, "illegal first argument to offsets",-1); - }else{ - memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); - snippetAllOffsets(pCursor); - snippetOffsetText(&pCursor->snippet); - sqlite3_result_text(pContext, - pCursor->snippet.zOffset, pCursor->snippet.nOffset, - SQLITE_STATIC); - } -} - -/* -** This routine implements the xFindFunction method for the FTS3 -** virtual table. -*/ -static int fulltextFindFunction( - sqlite3_vtab *pVtab, - int nArg, - const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg -){ - if( strcmp(zName,"snippet")==0 ){ - *pxFunc = snippetFunc; - return 1; - }else if( strcmp(zName,"offsets")==0 ){ - *pxFunc = snippetOffsetsFunc; - return 1; - } - return 0; -} - -/* -** Rename an fts3 table. -*/ -static int fulltextRename( - sqlite3_vtab *pVtab, - const char *zName -){ - fulltext_vtab *p = (fulltext_vtab *)pVtab; - int rc = SQLITE_NOMEM; - char *zSql = sqlite3_mprintf( - "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';" - "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';" - "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';" - , p->zDb, p->zName, zName - , p->zDb, p->zName, zName - , p->zDb, p->zName, zName - ); - if( zSql ){ - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } - return rc; -} - -static const sqlite3_module fts3Module = { - /* iVersion */ 0, - /* xCreate */ fulltextCreate, - /* xConnect */ fulltextConnect, - /* xBestIndex */ fulltextBestIndex, - /* xDisconnect */ fulltextDisconnect, - /* xDestroy */ fulltextDestroy, - /* xOpen */ fulltextOpen, - /* xClose */ fulltextClose, - /* xFilter */ fulltextFilter, - /* xNext */ fulltextNext, - /* xEof */ fulltextEof, - /* xColumn */ fulltextColumn, - /* xRowid */ fulltextRowid, - /* xUpdate */ fulltextUpdate, - /* xBegin */ fulltextBegin, - /* xSync */ fulltextSync, - /* xCommit */ fulltextCommit, - /* xRollback */ fulltextRollback, - /* xFindFunction */ fulltextFindFunction, - /* xRename */ fulltextRename, -}; - -static void hashDestroy(void *p){ - fts3Hash *pHash = (fts3Hash *)p; - sqlite3Fts3HashClear(pHash); - sqlite3_free(pHash); -} - -/* -** The fts3 built-in tokenizers - "simple" and "porter" - are implemented -** in files fts3_tokenizer1.c and fts3_porter.c respectively. The following -** two forward declarations are for functions declared in these files -** used to retrieve the respective implementations. -** -** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed -** to by the argument to point a the "simple" tokenizer implementation. -** Function ...PorterTokenizerModule() sets *pModule to point to the -** porter tokenizer/stemmer implementation. -*/ -void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); -void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); -void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); - -int sqlite3Fts3InitHashTable(sqlite3 *, fts3Hash *, const char *); - -/* -** Initialise the fts3 extension. If this extension is built as part -** of the sqlite library, then this function is called directly by -** SQLite. If fts3 is built as a dynamically loadable extension, this -** function is called by the sqlite3_extension_init() entry point. -*/ -int sqlite3Fts3Init(sqlite3 *db){ - int rc = SQLITE_OK; - fts3Hash *pHash = 0; - const sqlite3_tokenizer_module *pSimple = 0; - const sqlite3_tokenizer_module *pPorter = 0; - const sqlite3_tokenizer_module *pIcu = 0; - - sqlite3Fts3SimpleTokenizerModule(&pSimple); - sqlite3Fts3PorterTokenizerModule(&pPorter); -#ifdef SQLITE_ENABLE_ICU - sqlite3Fts3IcuTokenizerModule(&pIcu); -#endif - - /* Allocate and initialise the hash-table used to store tokenizers. */ - pHash = sqlite3_malloc(sizeof(fts3Hash)); - if( !pHash ){ - rc = SQLITE_NOMEM; - }else{ - sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); - } - - /* Load the built-in tokenizers into the hash table */ - if( rc==SQLITE_OK ){ - if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) - || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) - || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) - ){ - rc = SQLITE_NOMEM; - } - } - - /* Create the virtual table wrapper around the hash-table and overload - ** the two scalar functions. If this is successful, register the - ** module with sqlite. - */ - if( SQLITE_OK==rc - && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1)) - ){ - return sqlite3_create_module_v2( - db, "fts3", &fts3Module, (void *)pHash, hashDestroy - ); - } - - /* An error has occured. Delete the hash table and return the error code. */ - assert( rc!=SQLITE_OK ); - if( pHash ){ - sqlite3Fts3HashClear(pHash); - sqlite3_free(pHash); - } - return rc; -} - -#if !SQLITE_CORE -int sqlite3_extension_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3Fts3Init(db); -} -#endif - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3.c ************************************************/ -/************** Begin file fts3_hash.c ***************************************/ -/* -** 2001 September 22 -** -** 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 is the implementation of generic hash-tables used in SQLite. -** We've modified it slightly to serve as a standalone hash table -** implementation for the full-text indexing module. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - - -/************** Include sqlite3.h in the middle of fts3_hash.c ***************/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3_hash.c ******************/ -/************** Include fts3_hash.h in the middle of fts3_hash.c *************/ -/************** Begin file fts3_hash.h ***************************************/ -/* -** 2001 September 22 -** -** 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 is the header file for the generic hash-table implemenation -** used in SQLite. We've modified it slightly to serve as a standalone -** hash table implementation for the full-text indexing module. -** -*/ -#ifndef _FTS3_HASH_H_ -#define _FTS3_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct fts3Hash fts3Hash; -typedef struct fts3HashElem fts3HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct fts3Hash { - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - fts3HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _fts3ht { /* the hash table */ - int count; /* Number of entries with this hash */ - fts3HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct fts3HashElem { - fts3HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 2 different modes of operation for a hash table: -** -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is respected in comparisons. -** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. -*/ -#define FTS3_HASH_STRING 1 -#define FTS3_HASH_BINARY 2 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -void sqlite3Fts3HashInit(fts3Hash*, int keytype, int copyKey); -void *sqlite3Fts3HashInsert(fts3Hash*, const void *pKey, int nKey, void *pData); -void *sqlite3Fts3HashFind(const fts3Hash*, const void *pKey, int nKey); -void sqlite3Fts3HashClear(fts3Hash*); - -/* -** Shorthand for the functions above -*/ -#define fts3HashInit sqlite3Fts3HashInit -#define fts3HashInsert sqlite3Fts3HashInsert -#define fts3HashFind sqlite3Fts3HashFind -#define fts3HashClear sqlite3Fts3HashClear - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** fts3Hash h; -** fts3HashElem *p; -** ... -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ -** SomeStructure *pData = fts3HashData(p); -** // do something with pData -** } -*/ -#define fts3HashFirst(H) ((H)->first) -#define fts3HashNext(E) ((E)->next) -#define fts3HashData(E) ((E)->data) -#define fts3HashKey(E) ((E)->pKey) -#define fts3HashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define fts3HashCount(H) ((H)->count) - -#endif /* _FTS3_HASH_H_ */ - -/************** End of fts3_hash.h *******************************************/ -/************** Continuing where we left off in fts3_hash.c ******************/ - -/* -** Malloc and Free functions -*/ -static void *fts3HashMalloc(int n){ - void *p = sqlite3_malloc(n); - if( p ){ - memset(p, 0, n); - } - return p; -} -static void fts3HashFree(void *p){ - sqlite3_free(p); -} - -/* Turn bulk memory into a hash table object by initializing the -** fields of the Hash structure. -** -** "pNew" is a pointer to the hash table that is to be initialized. -** keyClass is one of the constants -** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass -** determines what kind of key the hash table will use. "copyKey" is -** true if the hash table should make its own private copy of keys and -** false if it should just use the supplied pointer. -*/ -void sqlite3Fts3HashInit(fts3Hash *pNew, int keyClass, int copyKey){ - assert( pNew!=0 ); - assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); - pNew->keyClass = keyClass; - pNew->copyKey = copyKey; - pNew->first = 0; - pNew->count = 0; - pNew->htsize = 0; - pNew->ht = 0; -} - -/* Remove all entries from a hash table. Reclaim all memory. -** Call this routine to delete a hash table or to reset a hash table -** to the empty state. -*/ -void sqlite3Fts3HashClear(fts3Hash *pH){ - fts3HashElem *elem; /* For looping over all elements of the table */ - - assert( pH!=0 ); - elem = pH->first; - pH->first = 0; - fts3HashFree(pH->ht); - pH->ht = 0; - pH->htsize = 0; - while( elem ){ - fts3HashElem *next_elem = elem->next; - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree(elem); - elem = next_elem; - } - pH->count = 0; -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_STRING -*/ -static int fts3StrHash(const void *pKey, int nKey){ - const char *z = (const char *)pKey; - int h = 0; - if( nKey<=0 ) nKey = (int) strlen(z); - while( nKey > 0 ){ - h = (h<<3) ^ h ^ *z++; - nKey--; - } - return h & 0x7fffffff; -} -static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return strncmp((const char*)pKey1,(const char*)pKey2,n1); -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_BINARY -*/ -static int fts3BinHash(const void *pKey, int nKey){ - int h = 0; - const char *z = (const char *)pKey; - while( nKey-- > 0 ){ - h = (h<<3) ^ h ^ *(z++); - } - return h & 0x7fffffff; -} -static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return memcmp(pKey1,pKey2,n1); -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** The C syntax in this function definition may be unfamilar to some -** programmers, so we provide the following additional explanation: -** -** The name of the function is "ftsHashFunction". The function takes a -** single parameter "keyClass". The return value of ftsHashFunction() -** is a pointer to another function. Specifically, the return value -** of ftsHashFunction() is a pointer to a function that takes two parameters -** with types "const void*" and "int" and returns an "int". -*/ -static int (*ftsHashFunction(int keyClass))(const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrHash; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinHash; - } -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** For help in interpreted the obscure C code in the function definition, -** see the header comment on the previous function. -*/ -static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrCompare; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinCompare; - } -} - -/* Link an element into the hash table -*/ -static void fts3HashInsertElement( - fts3Hash *pH, /* The complete hash table */ - struct _fts3ht *pEntry, /* The entry into which pNew is inserted */ - fts3HashElem *pNew /* The element to be inserted */ -){ - fts3HashElem *pHead; /* First element already in pEntry */ - pHead = pEntry->chain; - if( pHead ){ - pNew->next = pHead; - pNew->prev = pHead->prev; - if( pHead->prev ){ pHead->prev->next = pNew; } - else { pH->first = pNew; } - pHead->prev = pNew; - }else{ - pNew->next = pH->first; - if( pH->first ){ pH->first->prev = pNew; } - pNew->prev = 0; - pH->first = pNew; - } - pEntry->count++; - pEntry->chain = pNew; -} - - -/* Resize the hash table so that it cantains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail -** to resize if sqliteMalloc() fails. -*/ -static void fts3Rehash(fts3Hash *pH, int new_size){ - struct _fts3ht *new_ht; /* The new hash table */ - fts3HashElem *elem, *next_elem; /* For looping over existing elements */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( (new_size & (new_size-1))==0 ); - new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); - if( new_ht==0 ) return; - fts3HashFree(pH->ht); - pH->ht = new_ht; - pH->htsize = new_size; - xHash = ftsHashFunction(pH->keyClass); - for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); - next_elem = elem->next; - fts3HashInsertElement(pH, &new_ht[h], elem); - } -} - -/* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. -*/ -static fts3HashElem *fts3FindElementByHash( - const fts3Hash *pH, /* The pH to be searched */ - const void *pKey, /* The key we are searching for */ - int nKey, - int h /* The hash for this key. */ -){ - fts3HashElem *elem; /* Used to loop thru the element list */ - int count; /* Number of elements left to test */ - int (*xCompare)(const void*,int,const void*,int); /* comparison function */ - - if( pH->ht ){ - struct _fts3ht *pEntry = &pH->ht[h]; - elem = pEntry->chain; - count = pEntry->count; - xCompare = ftsCompareFunction(pH->keyClass); - while( count-- && elem ){ - if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ - return elem; - } - elem = elem->next; - } - } - return 0; -} - -/* Remove a single entry from the hash table given a pointer to that -** element and a hash on the element's key. -*/ -static void fts3RemoveElementByHash( - fts3Hash *pH, /* The pH containing "elem" */ - fts3HashElem* elem, /* The element to be removed from the pH */ - int h /* Hash value for the element */ -){ - struct _fts3ht *pEntry; - if( elem->prev ){ - elem->prev->next = elem->next; - }else{ - pH->first = elem->next; - } - if( elem->next ){ - elem->next->prev = elem->prev; - } - pEntry = &pH->ht[h]; - if( pEntry->chain==elem ){ - pEntry->chain = elem->next; - } - pEntry->count--; - if( pEntry->count<=0 ){ - pEntry->chain = 0; - } - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree( elem ); - pH->count--; - if( pH->count<=0 ){ - assert( pH->first==0 ); - assert( pH->count==0 ); - fts3HashClear(pH); - } -} - -/* Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is -** found, or NULL if there is no match. -*/ -void *sqlite3Fts3HashFind(const fts3Hash *pH, const void *pKey, int nKey){ - int h; /* A hash on key */ - fts3HashElem *elem; /* The element that matches key */ - int (*xHash)(const void*,int); /* The hash function */ - - if( pH==0 || pH->ht==0 ) return 0; - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - h = (*xHash)(pKey,nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - elem = fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1)); - return elem ? elem->data : 0; -} - -/* Insert an element into the hash table pH. The key is pKey,nKey -** and the data is "data". -** -** If no element exists with a matching key, then a new -** element is created. A copy of the key is made if the copyKey -** flag is set. NULL is returned. -** -** If another element already exists with the same key, then the -** new data replaces the old data and the old data is returned. -** The key is not copied in this instance. If a malloc fails, then -** the new data is returned and the hash table is unchanged. -** -** If the "data" parameter to this function is NULL, then the -** element corresponding to "key" is removed from the hash table. -*/ -void *sqlite3Fts3HashInsert( - fts3Hash *pH, /* The hash table to insert into */ - const void *pKey, /* The key */ - int nKey, /* Number of bytes in the key */ - void *data /* The data */ -){ - int hraw; /* Raw hash value of the key */ - int h; /* the hash of the key modulo hash table size */ - fts3HashElem *elem; /* Used to loop thru the element list */ - fts3HashElem *new_elem; /* New element added to the pH */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( pH!=0 ); - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - hraw = (*xHash)(pKey, nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - elem = fts3FindElementByHash(pH,pKey,nKey,h); - if( elem ){ - void *old_data = elem->data; - if( data==0 ){ - fts3RemoveElementByHash(pH,elem,h); - }else{ - elem->data = data; - } - return old_data; - } - if( data==0 ) return 0; - new_elem = (fts3HashElem*)fts3HashMalloc( sizeof(fts3HashElem) ); - if( new_elem==0 ) return data; - if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = fts3HashMalloc( nKey ); - if( new_elem->pKey==0 ){ - fts3HashFree(new_elem); - return data; - } - memcpy((void*)new_elem->pKey, pKey, nKey); - }else{ - new_elem->pKey = (void*)pKey; - } - new_elem->nKey = nKey; - pH->count++; - if( pH->htsize==0 ){ - fts3Rehash(pH,8); - if( pH->htsize==0 ){ - pH->count = 0; - fts3HashFree(new_elem); - return data; - } - } - if( pH->count > pH->htsize ){ - fts3Rehash(pH,pH->htsize*2); - } - assert( pH->htsize>0 ); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - fts3HashInsertElement(pH, &pH->ht[h], new_elem); - new_elem->data = data; - return 0; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_hash.c *******************************************/ -/************** Begin file fts3_porter.c *************************************/ -/* -** 2006 September 30 -** -** 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. -** -************************************************************************* -** Implementation of the full-text-search tokenizer that implements -** a Porter stemmer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - - - -/************** Include fts3_tokenizer.h in the middle of fts3_porter.c ******/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -/************** Include sqlite3.h in the middle of fts3_tokenizer.h **********/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3_tokenizer.h *************/ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialised by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3_porter.c ****************/ - -/* -** Class derived from sqlite3_tokenizer -*/ -typedef struct porter_tokenizer { - sqlite3_tokenizer base; /* Base class */ -} porter_tokenizer; - -/* -** Class derived from sqlit3_tokenizer_cursor -*/ -typedef struct porter_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *zInput; /* input we are tokenizing */ - int nInput; /* size of the input */ - int iOffset; /* current position in zInput */ - int iToken; /* index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAllocated; /* space allocated to zToken buffer */ -} porter_tokenizer_cursor; - - -/* Forward declaration */ -static const sqlite3_tokenizer_module porterTokenizerModule; - - -/* -** Create a new tokenizer instance. -*/ -static int porterCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - porter_tokenizer *t; - t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int porterDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is zInput[0..nInput-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int porterOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, int nInput, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - porter_tokenizer_cursor *c; - - c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->zInput = zInput; - if( zInput==0 ){ - c->nInput = 0; - }else if( nInput<0 ){ - c->nInput = (int)strlen(zInput); - }else{ - c->nInput = nInput; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->zToken = NULL; /* no space allocated, yet. */ - c->nAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** porterOpen() above. -*/ -static int porterClose(sqlite3_tokenizer_cursor *pCursor){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - sqlite3_free(c->zToken); - sqlite3_free(c); - return SQLITE_OK; -} -/* -** Vowel or consonant -*/ -static const char cType[] = { - 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 2, 1 -}; - -/* -** isConsonant() and isVowel() determine if their first character in -** the string they point to is a consonant or a vowel, according -** to Porter ruls. -** -** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. -** 'Y' is a consonant unless it follows another consonant, -** in which case it is a vowel. -** -** In these routine, the letters are in reverse order. So the 'y' rule -** is that 'y' is a consonant unless it is followed by another -** consonent. -*/ -static int isVowel(const char*); -static int isConsonant(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return j; - return z[1]==0 || isVowel(z + 1); -} -static int isVowel(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return 1-j; - return isConsonant(z + 1); -} - -/* -** Let any sequence of one or more vowels be represented by V and let -** C be sequence of one or more consonants. Then every word can be -** represented as: -** -** [C] (VC){m} [V] -** -** In prose: A word is an optional consonant followed by zero or -** vowel-consonant pairs followed by an optional vowel. "m" is the -** number of vowel consonant pairs. This routine computes the value -** of m for the first i bytes of a word. -** -** Return true if the m-value for z is 1 or more. In other words, -** return true if z contains at least one vowel that is followed -** by a consonant. -** -** In this routine z[] is in reverse order. So we are really looking -** for an instance of of a consonant followed by a vowel. -*/ -static int m_gt_0(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* Like mgt0 above except we are looking for a value of m which is -** exactly 1 -*/ -static int m_eq_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 1; - while( isConsonant(z) ){ z++; } - return *z==0; -} - -/* Like mgt0 above except we are looking for a value of m>1 instead -** or m>0 -*/ -static int m_gt_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if there is a vowel anywhere within z[0..n-1] -*/ -static int hasVowel(const char *z){ - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if the word ends in a double consonant. -** -** The text is reversed here. So we are really looking at -** the first two characters of z[]. -*/ -static int doubleConsonant(const char *z){ - return isConsonant(z) && z[0]==z[1] && isConsonant(z+1); -} - -/* -** Return TRUE if the word ends with three letters which -** are consonant-vowel-consonent and where the final consonant -** is not 'w', 'x', or 'y'. -** -** The word is reversed here. So we are really checking the -** first three letters and the first one cannot be in [wxy]. -*/ -static int star_oh(const char *z){ - return - z[0]!=0 && isConsonant(z) && - z[0]!='w' && z[0]!='x' && z[0]!='y' && - z[1]!=0 && isVowel(z+1) && - z[2]!=0 && isConsonant(z+2); -} - -/* -** If the word ends with zFrom and xCond() is true for the stem -** of the word that preceeds the zFrom ending, then change the -** ending to zTo. -** -** The input word *pz and zFrom are both in reverse order. zTo -** is in normal order. -** -** Return TRUE if zFrom matches. Return FALSE if zFrom does not -** match. Not that TRUE is returned even if xCond() fails and -** no substitution occurs. -*/ -static int stem( - char **pz, /* The word being stemmed (Reversed) */ - const char *zFrom, /* If the ending matches this... (Reversed) */ - const char *zTo, /* ... change the ending to this (not reversed) */ - int (*xCond)(const char*) /* Condition that must be true */ -){ - char *z = *pz; - while( *zFrom && *zFrom==*z ){ z++; zFrom++; } - if( *zFrom!=0 ) return 0; - if( xCond && !xCond(z) ) return 1; - while( *zTo ){ - *(--z) = *(zTo++); - } - *pz = z; - return 1; -} - -/* -** This is the fallback stemmer used when the porter stemmer is -** inappropriate. The input word is copied into the output with -** US-ASCII case folding. If the input word is too long (more -** than 20 bytes if it contains no digits or more than 6 bytes if -** it contains digits) then word is truncated to 20 or 6 bytes -** by taking 10 or 3 bytes from the beginning and end. -*/ -static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ - int i, mx, j; - int hasDigit = 0; - for(i=0; i='A' && c<='Z' ){ - zOut[i] = c - 'A' + 'a'; - }else{ - if( c>='0' && c<='9' ) hasDigit = 1; - zOut[i] = c; - } - } - mx = hasDigit ? 3 : 10; - if( nIn>mx*2 ){ - for(j=mx, i=nIn-mx; i=sizeof(zReverse)-7 ){ - /* The word is too big or too small for the porter stemmer. - ** Fallback to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ - zReverse[j] = c + 'a' - 'A'; - }else if( c>='a' && c<='z' ){ - zReverse[j] = c; - }else{ - /* The use of a character not in [a-zA-Z] means that we fallback - ** to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - } - memset(&zReverse[sizeof(zReverse)-5], 0, 5); - z = &zReverse[j+1]; - - - /* Step 1a */ - if( z[0]=='s' ){ - if( - !stem(&z, "sess", "ss", 0) && - !stem(&z, "sei", "i", 0) && - !stem(&z, "ss", "ss", 0) - ){ - z++; - } - } - - /* Step 1b */ - z2 = z; - if( stem(&z, "dee", "ee", m_gt_0) ){ - /* Do nothing. The work was all in the test */ - }else if( - (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) - && z!=z2 - ){ - if( stem(&z, "ta", "ate", 0) || - stem(&z, "lb", "ble", 0) || - stem(&z, "zi", "ize", 0) ){ - /* Do nothing. The work was all in the test */ - }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ - z++; - }else if( m_eq_1(z) && star_oh(z) ){ - *(--z) = 'e'; - } - } - - /* Step 1c */ - if( z[0]=='y' && hasVowel(z+1) ){ - z[0] = 'i'; - } - - /* Step 2 */ - switch( z[1] ){ - case 'a': - stem(&z, "lanoita", "ate", m_gt_0) || - stem(&z, "lanoit", "tion", m_gt_0); - break; - case 'c': - stem(&z, "icne", "ence", m_gt_0) || - stem(&z, "icna", "ance", m_gt_0); - break; - case 'e': - stem(&z, "rezi", "ize", m_gt_0); - break; - case 'g': - stem(&z, "igol", "log", m_gt_0); - break; - case 'l': - stem(&z, "ilb", "ble", m_gt_0) || - stem(&z, "illa", "al", m_gt_0) || - stem(&z, "iltne", "ent", m_gt_0) || - stem(&z, "ile", "e", m_gt_0) || - stem(&z, "ilsuo", "ous", m_gt_0); - break; - case 'o': - stem(&z, "noitazi", "ize", m_gt_0) || - stem(&z, "noita", "ate", m_gt_0) || - stem(&z, "rota", "ate", m_gt_0); - break; - case 's': - stem(&z, "msila", "al", m_gt_0) || - stem(&z, "ssenevi", "ive", m_gt_0) || - stem(&z, "ssenluf", "ful", m_gt_0) || - stem(&z, "ssensuo", "ous", m_gt_0); - break; - case 't': - stem(&z, "itila", "al", m_gt_0) || - stem(&z, "itivi", "ive", m_gt_0) || - stem(&z, "itilib", "ble", m_gt_0); - break; - } - - /* Step 3 */ - switch( z[0] ){ - case 'e': - stem(&z, "etaci", "ic", m_gt_0) || - stem(&z, "evita", "", m_gt_0) || - stem(&z, "ezila", "al", m_gt_0); - break; - case 'i': - stem(&z, "itici", "ic", m_gt_0); - break; - case 'l': - stem(&z, "laci", "ic", m_gt_0) || - stem(&z, "luf", "", m_gt_0); - break; - case 's': - stem(&z, "ssen", "", m_gt_0); - break; - } - - /* Step 4 */ - switch( z[1] ){ - case 'a': - if( z[0]=='l' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'c': - if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'e': - if( z[0]=='r' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'i': - if( z[0]=='c' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'l': - if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'n': - if( z[0]=='t' ){ - if( z[2]=='a' ){ - if( m_gt_1(z+3) ){ - z += 3; - } - }else if( z[2]=='e' ){ - stem(&z, "tneme", "", m_gt_1) || - stem(&z, "tnem", "", m_gt_1) || - stem(&z, "tne", "", m_gt_1); - } - } - break; - case 'o': - if( z[0]=='u' ){ - if( m_gt_1(z+2) ){ - z += 2; - } - }else if( z[3]=='s' || z[3]=='t' ){ - stem(&z, "noi", "", m_gt_1); - } - break; - case 's': - if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 't': - stem(&z, "eta", "", m_gt_1) || - stem(&z, "iti", "", m_gt_1); - break; - case 'u': - if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 'v': - case 'z': - if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - } - - /* Step 5a */ - if( z[0]=='e' ){ - if( m_gt_1(z+1) ){ - z++; - }else if( m_eq_1(z+1) && !star_oh(z+1) ){ - z++; - } - } - - /* Step 5b */ - if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ - z++; - } - - /* z[] is now the stemmed word in reverse order. Flip it back - ** around into forward order and return. - */ - *pnOut = i = strlen(z); - zOut[i] = 0; - while( *z ){ - zOut[--i] = *(z++); - } -} - -/* -** Characters that can be part of a token. We assume any character -** whose value is greater than 0x80 (any UTF character) can be -** part of a token. In other words, delimiters all must have -** values of 0x7f or lower. -*/ -static const char porterIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ -}; -#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30])) - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to porterOpen(). -*/ -static int porterNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ - const char **pzToken, /* OUT: *pzToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - const char *z = c->zInput; - - while( c->iOffsetnInput ){ - int iStartOffset, ch; - - /* Scan past delimiter characters */ - while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int n = c->iOffset-iStartOffset; - if( n>c->nAllocated ){ - c->nAllocated = n+20; - c->zToken = sqlite3_realloc(c->zToken, c->nAllocated); - if( c->zToken==NULL ) return SQLITE_NOMEM; - } - porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); - *pzToken = c->zToken; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the porter-stemmer tokenizer -*/ -static const sqlite3_tokenizer_module porterTokenizerModule = { - 0, - porterCreate, - porterDestroy, - porterOpen, - porterClose, - porterNext, -}; - -/* -** Allocate a new porter tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -void sqlite3Fts3PorterTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &porterTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_porter.c *****************************************/ -/************** Begin file fts3_tokenizer.c **********************************/ -/* -** 2007 June 22 -** -** 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 is part of an SQLite module implementing full-text search. -** This particular file implements the generic tokenizer interface. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/************** Include sqlite3ext.h in the middle of fts3_tokenizer.c *******/ -/************** Begin file sqlite3ext.h **************************************/ -/* -** 2006 June 7 -** -** 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 header file defines the SQLite interface for use by -** shared libraries that want to be imported as extensions into -** an SQLite instance. Shared libraries that intend to be loaded -** as extensions by SQLite should #include this file instead of -** sqlite3.h. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3EXT_H_ -#define _SQLITE3EXT_H_ -/************** Include sqlite3.h in the middle of sqlite3ext.h **************/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in sqlite3ext.h *****************/ - -typedef struct sqlite3_api_routines sqlite3_api_routines; - -/* -** The following structure hold pointers to all of the SQLite API -** routines. -** -** WARNING: In order to maintain backwards compatibility, add new -** interfaces to the end of this structure only. If you insert new -** interfaces in the middle of this structure, then older different -** versions of SQLite will not be able to load each others shared -** libraries! -*/ -struct sqlite3_api_routines { - void * (*aggregate_context)(sqlite3_context*,int nBytes); - int (*aggregate_count)(sqlite3_context*); - int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); - int (*bind_double)(sqlite3_stmt*,int,double); - int (*bind_int)(sqlite3_stmt*,int,int); - int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); - int (*bind_null)(sqlite3_stmt*,int); - int (*bind_parameter_count)(sqlite3_stmt*); - int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); - const char * (*bind_parameter_name)(sqlite3_stmt*,int); - int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); - int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); - int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); - int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); - int (*busy_timeout)(sqlite3*,int ms); - int (*changes)(sqlite3*); - int (*close)(sqlite3*); - int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*)); - int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*)); - const void * (*column_blob)(sqlite3_stmt*,int iCol); - int (*column_bytes)(sqlite3_stmt*,int iCol); - int (*column_bytes16)(sqlite3_stmt*,int iCol); - int (*column_count)(sqlite3_stmt*pStmt); - const char * (*column_database_name)(sqlite3_stmt*,int); - const void * (*column_database_name16)(sqlite3_stmt*,int); - const char * (*column_decltype)(sqlite3_stmt*,int i); - const void * (*column_decltype16)(sqlite3_stmt*,int); - double (*column_double)(sqlite3_stmt*,int iCol); - int (*column_int)(sqlite3_stmt*,int iCol); - sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); - const char * (*column_name)(sqlite3_stmt*,int); - const void * (*column_name16)(sqlite3_stmt*,int); - const char * (*column_origin_name)(sqlite3_stmt*,int); - const void * (*column_origin_name16)(sqlite3_stmt*,int); - const char * (*column_table_name)(sqlite3_stmt*,int); - const void * (*column_table_name16)(sqlite3_stmt*,int); - const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); - const void * (*column_text16)(sqlite3_stmt*,int iCol); - int (*column_type)(sqlite3_stmt*,int iCol); - sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); - void * (*commit_hook)(sqlite3*,int(*)(void*),void*); - int (*complete)(const char*sql); - int (*complete16)(const void*sql); - int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); - int (*create_collation16)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); - int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); - int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); - int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); - int (*data_count)(sqlite3_stmt*pStmt); - sqlite3 * (*db_handle)(sqlite3_stmt*); - int (*declare_vtab)(sqlite3*,const char*); - int (*enable_shared_cache)(int); - int (*errcode)(sqlite3*db); - const char * (*errmsg)(sqlite3*); - const void * (*errmsg16)(sqlite3*); - int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); - int (*expired)(sqlite3_stmt*); - int (*finalize)(sqlite3_stmt*pStmt); - void (*free)(void*); - void (*free_table)(char**result); - int (*get_autocommit)(sqlite3*); - void * (*get_auxdata)(sqlite3_context*,int); - int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); - int (*global_recover)(void); - void (*interruptx)(sqlite3*); - sqlite_int64 (*last_insert_rowid)(sqlite3*); - const char * (*libversion)(void); - int (*libversion_number)(void); - void *(*malloc)(int); - char * (*mprintf)(const char*,...); - int (*open)(const char*,sqlite3**); - int (*open16)(const void*,sqlite3**); - int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); - void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); - void *(*realloc)(void*,int); - int (*reset)(sqlite3_stmt*pStmt); - void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_double)(sqlite3_context*,double); - void (*result_error)(sqlite3_context*,const char*,int); - void (*result_error16)(sqlite3_context*,const void*,int); - void (*result_int)(sqlite3_context*,int); - void (*result_int64)(sqlite3_context*,sqlite_int64); - void (*result_null)(sqlite3_context*); - void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); - void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_value)(sqlite3_context*,sqlite3_value*); - void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); - int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*); - void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); - char * (*snprintf)(int,char*,const char*,...); - int (*step)(sqlite3_stmt*); - int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*); - void (*thread_cleanup)(void); - int (*total_changes)(sqlite3*); - void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); - int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); - void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*); - void * (*user_data)(sqlite3_context*); - const void * (*value_blob)(sqlite3_value*); - int (*value_bytes)(sqlite3_value*); - int (*value_bytes16)(sqlite3_value*); - double (*value_double)(sqlite3_value*); - int (*value_int)(sqlite3_value*); - sqlite_int64 (*value_int64)(sqlite3_value*); - int (*value_numeric_type)(sqlite3_value*); - const unsigned char * (*value_text)(sqlite3_value*); - const void * (*value_text16)(sqlite3_value*); - const void * (*value_text16be)(sqlite3_value*); - const void * (*value_text16le)(sqlite3_value*); - int (*value_type)(sqlite3_value*); - char *(*vmprintf)(const char*,va_list); - /* Added ??? */ - int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); - /* Added by 3.3.13 */ - int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - int (*clear_bindings)(sqlite3_stmt*); - /* Added by 3.4.1 */ - int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *)); - /* Added by 3.5.0 */ - int (*bind_zeroblob)(sqlite3_stmt*,int,int); - int (*blob_bytes)(sqlite3_blob*); - int (*blob_close)(sqlite3_blob*); - int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**); - int (*blob_read)(sqlite3_blob*,void*,int,int); - int (*blob_write)(sqlite3_blob*,const void*,int,int); - int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*)); - int (*file_control)(sqlite3*,const char*,int,void*); - sqlite3_int64 (*memory_highwater)(int); - sqlite3_int64 (*memory_used)(void); - sqlite3_mutex *(*mutex_alloc)(int); - void (*mutex_enter)(sqlite3_mutex*); - void (*mutex_free)(sqlite3_mutex*); - void (*mutex_leave)(sqlite3_mutex*); - int (*mutex_try)(sqlite3_mutex*); - int (*open_v2)(const char*,sqlite3**,int,const char*); - int (*release_memory)(int); - void (*result_error_nomem)(sqlite3_context*); - void (*result_error_toobig)(sqlite3_context*); - int (*sleep)(int); - void (*soft_heap_limit)(int); - sqlite3_vfs *(*vfs_find)(const char*); - int (*vfs_register)(sqlite3_vfs*,int); - int (*vfs_unregister)(sqlite3_vfs*); -}; - -/* -** The following macros redefine the API routines so that they are -** redirected throught the global sqlite3_api structure. -** -** This header file is also used by the loadext.c source file -** (part of the main SQLite library - not an extension) so that -** it can get access to the sqlite3_api_routines structure -** definition. But the main library does not want to redefine -** the API. So the redefinition macros are only valid if the -** SQLITE_CORE macros is undefined. -*/ -#ifndef SQLITE_CORE -#define sqlite3_aggregate_context sqlite3_api->aggregate_context -#define sqlite3_aggregate_count sqlite3_api->aggregate_count -#define sqlite3_bind_blob sqlite3_api->bind_blob -#define sqlite3_bind_double sqlite3_api->bind_double -#define sqlite3_bind_int sqlite3_api->bind_int -#define sqlite3_bind_int64 sqlite3_api->bind_int64 -#define sqlite3_bind_null sqlite3_api->bind_null -#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count -#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index -#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name -#define sqlite3_bind_text sqlite3_api->bind_text -#define sqlite3_bind_text16 sqlite3_api->bind_text16 -#define sqlite3_bind_value sqlite3_api->bind_value -#define sqlite3_busy_handler sqlite3_api->busy_handler -#define sqlite3_busy_timeout sqlite3_api->busy_timeout -#define sqlite3_changes sqlite3_api->changes -#define sqlite3_close sqlite3_api->close -#define sqlite3_collation_needed sqlite3_api->collation_needed -#define sqlite3_collation_needed16 sqlite3_api->collation_needed16 -#define sqlite3_column_blob sqlite3_api->column_blob -#define sqlite3_column_bytes sqlite3_api->column_bytes -#define sqlite3_column_bytes16 sqlite3_api->column_bytes16 -#define sqlite3_column_count sqlite3_api->column_count -#define sqlite3_column_database_name sqlite3_api->column_database_name -#define sqlite3_column_database_name16 sqlite3_api->column_database_name16 -#define sqlite3_column_decltype sqlite3_api->column_decltype -#define sqlite3_column_decltype16 sqlite3_api->column_decltype16 -#define sqlite3_column_double sqlite3_api->column_double -#define sqlite3_column_int sqlite3_api->column_int -#define sqlite3_column_int64 sqlite3_api->column_int64 -#define sqlite3_column_name sqlite3_api->column_name -#define sqlite3_column_name16 sqlite3_api->column_name16 -#define sqlite3_column_origin_name sqlite3_api->column_origin_name -#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 -#define sqlite3_column_table_name sqlite3_api->column_table_name -#define sqlite3_column_table_name16 sqlite3_api->column_table_name16 -#define sqlite3_column_text sqlite3_api->column_text -#define sqlite3_column_text16 sqlite3_api->column_text16 -#define sqlite3_column_type sqlite3_api->column_type -#define sqlite3_column_value sqlite3_api->column_value -#define sqlite3_commit_hook sqlite3_api->commit_hook -#define sqlite3_complete sqlite3_api->complete -#define sqlite3_complete16 sqlite3_api->complete16 -#define sqlite3_create_collation sqlite3_api->create_collation -#define sqlite3_create_collation16 sqlite3_api->create_collation16 -#define sqlite3_create_function sqlite3_api->create_function -#define sqlite3_create_function16 sqlite3_api->create_function16 -#define sqlite3_create_module sqlite3_api->create_module -#define sqlite3_create_module_v2 sqlite3_api->create_module_v2 -#define sqlite3_data_count sqlite3_api->data_count -#define sqlite3_db_handle sqlite3_api->db_handle -#define sqlite3_declare_vtab sqlite3_api->declare_vtab -#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache -#define sqlite3_errcode sqlite3_api->errcode -#define sqlite3_errmsg sqlite3_api->errmsg -#define sqlite3_errmsg16 sqlite3_api->errmsg16 -#define sqlite3_exec sqlite3_api->exec -#define sqlite3_expired sqlite3_api->expired -#define sqlite3_finalize sqlite3_api->finalize -#define sqlite3_free sqlite3_api->free -#define sqlite3_free_table sqlite3_api->free_table -#define sqlite3_get_autocommit sqlite3_api->get_autocommit -#define sqlite3_get_auxdata sqlite3_api->get_auxdata -#define sqlite3_get_table sqlite3_api->get_table -#define sqlite3_global_recover sqlite3_api->global_recover -#define sqlite3_interrupt sqlite3_api->interruptx -#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid -#define sqlite3_libversion sqlite3_api->libversion -#define sqlite3_libversion_number sqlite3_api->libversion_number -#define sqlite3_malloc sqlite3_api->malloc -#define sqlite3_mprintf sqlite3_api->mprintf -#define sqlite3_open sqlite3_api->open -#define sqlite3_open16 sqlite3_api->open16 -#define sqlite3_prepare sqlite3_api->prepare -#define sqlite3_prepare16 sqlite3_api->prepare16 -#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 -#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 -#define sqlite3_profile sqlite3_api->profile -#define sqlite3_progress_handler sqlite3_api->progress_handler -#define sqlite3_realloc sqlite3_api->realloc -#define sqlite3_reset sqlite3_api->reset -#define sqlite3_result_blob sqlite3_api->result_blob -#define sqlite3_result_double sqlite3_api->result_double -#define sqlite3_result_error sqlite3_api->result_error -#define sqlite3_result_error16 sqlite3_api->result_error16 -#define sqlite3_result_int sqlite3_api->result_int -#define sqlite3_result_int64 sqlite3_api->result_int64 -#define sqlite3_result_null sqlite3_api->result_null -#define sqlite3_result_text sqlite3_api->result_text -#define sqlite3_result_text16 sqlite3_api->result_text16 -#define sqlite3_result_text16be sqlite3_api->result_text16be -#define sqlite3_result_text16le sqlite3_api->result_text16le -#define sqlite3_result_value sqlite3_api->result_value -#define sqlite3_rollback_hook sqlite3_api->rollback_hook -#define sqlite3_set_authorizer sqlite3_api->set_authorizer -#define sqlite3_set_auxdata sqlite3_api->set_auxdata -#define sqlite3_snprintf sqlite3_api->snprintf -#define sqlite3_step sqlite3_api->step -#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata -#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup -#define sqlite3_total_changes sqlite3_api->total_changes -#define sqlite3_trace sqlite3_api->trace -#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings -#define sqlite3_update_hook sqlite3_api->update_hook -#define sqlite3_user_data sqlite3_api->user_data -#define sqlite3_value_blob sqlite3_api->value_blob -#define sqlite3_value_bytes sqlite3_api->value_bytes -#define sqlite3_value_bytes16 sqlite3_api->value_bytes16 -#define sqlite3_value_double sqlite3_api->value_double -#define sqlite3_value_int sqlite3_api->value_int -#define sqlite3_value_int64 sqlite3_api->value_int64 -#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type -#define sqlite3_value_text sqlite3_api->value_text -#define sqlite3_value_text16 sqlite3_api->value_text16 -#define sqlite3_value_text16be sqlite3_api->value_text16be -#define sqlite3_value_text16le sqlite3_api->value_text16le -#define sqlite3_value_type sqlite3_api->value_type -#define sqlite3_vmprintf sqlite3_api->vmprintf -#define sqlite3_overload_function sqlite3_api->overload_function -#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 -#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 -#define sqlite3_clear_bindings sqlite3_api->clear_bindings -#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob -#define sqlite3_blob_bytes sqlite3_api->blob_bytes -#define sqlite3_blob_close sqlite3_api->blob_close -#define sqlite3_blob_open sqlite3_api->blob_open -#define sqlite3_blob_read sqlite3_api->blob_read -#define sqlite3_blob_write sqlite3_api->blob_write -#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 -#define sqlite3_file_control sqlite3_api->file_control -#define sqlite3_memory_highwater sqlite3_api->memory_highwater -#define sqlite3_memory_used sqlite3_api->memory_used -#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc -#define sqlite3_mutex_enter sqlite3_api->mutex_enter -#define sqlite3_mutex_free sqlite3_api->mutex_free -#define sqlite3_mutex_leave sqlite3_api->mutex_leave -#define sqlite3_mutex_try sqlite3_api->mutex_try -#define sqlite3_open_v2 sqlite3_api->open_v2 -#define sqlite3_release_memory sqlite3_api->release_memory -#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem -#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig -#define sqlite3_sleep sqlite3_api->sleep -#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit -#define sqlite3_vfs_find sqlite3_api->vfs_find -#define sqlite3_vfs_register sqlite3_api->vfs_register -#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister -#endif /* SQLITE_CORE */ - -#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; -#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; - -#endif /* _SQLITE3EXT_H_ */ - -/************** End of sqlite3ext.h ******************************************/ -/************** Continuing where we left off in fts3_tokenizer.c *************/ -SQLITE_EXTENSION_INIT1 - -/************** Include fts3_hash.h in the middle of fts3_tokenizer.c ********/ -/************** Begin file fts3_hash.h ***************************************/ -/* -** 2001 September 22 -** -** 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 is the header file for the generic hash-table implemenation -** used in SQLite. We've modified it slightly to serve as a standalone -** hash table implementation for the full-text indexing module. -** -*/ -#ifndef _FTS3_HASH_H_ -#define _FTS3_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct fts3Hash fts3Hash; -typedef struct fts3HashElem fts3HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct fts3Hash { - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - fts3HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _fts3ht { /* the hash table */ - int count; /* Number of entries with this hash */ - fts3HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct fts3HashElem { - fts3HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 2 different modes of operation for a hash table: -** -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is respected in comparisons. -** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. -*/ -#define FTS3_HASH_STRING 1 -#define FTS3_HASH_BINARY 2 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -void sqlite3Fts3HashInit(fts3Hash*, int keytype, int copyKey); -void *sqlite3Fts3HashInsert(fts3Hash*, const void *pKey, int nKey, void *pData); -void *sqlite3Fts3HashFind(const fts3Hash*, const void *pKey, int nKey); -void sqlite3Fts3HashClear(fts3Hash*); - -/* -** Shorthand for the functions above -*/ -#define fts3HashInit sqlite3Fts3HashInit -#define fts3HashInsert sqlite3Fts3HashInsert -#define fts3HashFind sqlite3Fts3HashFind -#define fts3HashClear sqlite3Fts3HashClear - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** fts3Hash h; -** fts3HashElem *p; -** ... -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ -** SomeStructure *pData = fts3HashData(p); -** // do something with pData -** } -*/ -#define fts3HashFirst(H) ((H)->first) -#define fts3HashNext(E) ((E)->next) -#define fts3HashData(E) ((E)->data) -#define fts3HashKey(E) ((E)->pKey) -#define fts3HashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define fts3HashCount(H) ((H)->count) - -#endif /* _FTS3_HASH_H_ */ - -/************** End of fts3_hash.h *******************************************/ -/************** Continuing where we left off in fts3_tokenizer.c *************/ -/************** Include fts3_tokenizer.h in the middle of fts3_tokenizer.c ***/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -/************** Include sqlite3.h in the middle of fts3_tokenizer.h **********/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3_tokenizer.h *************/ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialised by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3_tokenizer.c *************/ - -/* -** Implementation of the SQL scalar function for accessing the underlying -** hash table. This function may be called as follows: -** -** SELECT (); -** SELECT (, ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer'). -** -** If the argument is specified, it must be a blob value -** containing a pointer to be stored as the hash data corresponding -** to the string . If is not specified, then -** the string must already exist in the has table. Otherwise, -** an error is returned. -** -** Whether or not the argument is specified, the value returned -** is a blob containing the pointer stored as the hash data corresponding -** to string (after the hash-table is updated, if applicable). -*/ -static void scalarFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3Hash *pHash; - void *pPtr = 0; - const unsigned char *zName; - int nName; - - assert( argc==1 || argc==2 ); - - pHash = (fts3Hash *)sqlite3_user_data(context); - - zName = sqlite3_value_text(argv[0]); - nName = sqlite3_value_bytes(argv[0])+1; - - if( argc==2 ){ - void *pOld; - int n = sqlite3_value_bytes(argv[1]); - if( n!=sizeof(pPtr) ){ - sqlite3_result_error(context, "argument type mismatch", -1); - return; - } - pPtr = *(void **)sqlite3_value_blob(argv[1]); - pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); - if( pOld==pPtr ){ - sqlite3_result_error(context, "out of memory", -1); - return; - } - }else{ - pPtr = sqlite3Fts3HashFind(pHash, zName, nName); - if( !pPtr ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - } - - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); -} - -#ifdef SQLITE_TEST - -#include - -/* -** Implementation of a special SQL scalar function for testing tokenizers -** designed to be used in concert with the Tcl testing framework. This -** function must be called with two arguments: -** -** SELECT (, ); -** SELECT (, ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') -** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test'). -** -** The return value is a string that may be interpreted as a Tcl -** list. For each token in the , three elements are -** added to the returned list. The first is the token position, the -** second is the token text (folded, stemmed, etc.) and the third is the -** substring of associated with the token. For example, -** using the built-in "simple" tokenizer: -** -** SELECT fts_tokenizer_test('simple', 'I don't see how'); -** -** will return the string: -** -** "{0 i I 1 dont don't 2 see see 3 how how}" -** -*/ -static void testFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3Hash *pHash; - sqlite3_tokenizer_module *p; - sqlite3_tokenizer *pTokenizer = 0; - sqlite3_tokenizer_cursor *pCsr = 0; - - const char *zErr = 0; - - const char *zName; - int nName; - const char *zInput; - int nInput; - - const char *zArg = 0; - - const char *zToken; - int nToken; - int iStart; - int iEnd; - int iPos; - - Tcl_Obj *pRet; - - assert( argc==2 || argc==3 ); - - nName = sqlite3_value_bytes(argv[0]); - zName = (const char *)sqlite3_value_text(argv[0]); - nInput = sqlite3_value_bytes(argv[argc-1]); - zInput = (const char *)sqlite3_value_text(argv[argc-1]); - - if( argc==3 ){ - zArg = (const char *)sqlite3_value_text(argv[1]); - } - - pHash = (fts3Hash *)sqlite3_user_data(context); - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - - if( !p ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - - if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ - zErr = "error in xCreate()"; - goto finish; - } - pTokenizer->pModule = p; - if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){ - zErr = "error in xOpen()"; - goto finish; - } - pCsr->pTokenizer = pTokenizer; - - while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ - Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - zToken = &zInput[iStart]; - nToken = iEnd-iStart; - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - } - - if( SQLITE_OK!=p->xClose(pCsr) ){ - zErr = "error in xClose()"; - goto finish; - } - if( SQLITE_OK!=p->xDestroy(pTokenizer) ){ - zErr = "error in xDestroy()"; - goto finish; - } - -finish: - if( zErr ){ - sqlite3_result_error(context, zErr, -1); - }else{ - sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); - } - Tcl_DecrRefCount(pRet); -} - -static -int registerTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module *p -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; - - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); - sqlite3_step(pStmt); - - return sqlite3_finalize(pStmt); -} - -static -int queryTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ - memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - -void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); - -/* -** Implementation of the scalar function fts3_tokenizer_internal_test(). -** This function is used for testing only, it is not included in the -** build unless SQLITE_TEST is defined. -** -** The purpose of this is to test that the fts3_tokenizer() function -** can be used as designed by the C-code in the queryTokenizer and -** registerTokenizer() functions above. These two functions are repeated -** in the README.tokenizer file as an example, so it is important to -** test them. -** -** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar -** function with no arguments. An assert() will fail if a problem is -** detected. i.e.: -** -** SELECT fts3_tokenizer_internal_test(); -** -*/ -static void intTestFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int rc; - const sqlite3_tokenizer_module *p1; - const sqlite3_tokenizer_module *p2; - sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); - - /* Test the query function */ - sqlite3Fts3SimpleTokenizerModule(&p1); - rc = queryTokenizer(db, "simple", &p2); - assert( rc==SQLITE_OK ); - assert( p1==p2 ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_ERROR ); - assert( p2==0 ); - assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); - - /* Test the storage function */ - rc = registerTokenizer(db, "nosuchtokenizer", p1); - assert( rc==SQLITE_OK ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_OK ); - assert( p2==p1 ); - - sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); -} - -#endif - -/* -** Set up SQL objects in database db used to access the contents of -** the hash table pointed to by argument pHash. The hash table must -** been initialised to use string keys, and to take a private copy -** of the key when a value is inserted. i.e. by a call similar to: -** -** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); -** -** This function adds a scalar function (see header comment above -** scalarFunc() in this file for details) and, if ENABLE_TABLE is -** defined at compilation time, a temporary virtual table (see header -** comment above struct HashTableVtab) to the database schema. Both -** provide read/write access to the contents of *pHash. -** -** The third argument to this function, zName, is used as the name -** of both the scalar and, if created, the virtual table. -*/ -int sqlite3Fts3InitHashTable( - sqlite3 *db, - fts3Hash *pHash, - const char *zName -){ - int rc = SQLITE_OK; - void *p = (void *)pHash; - const int any = SQLITE_ANY; - char *zTest = 0; - char *zTest2 = 0; - -#ifdef SQLITE_TEST - void *pdb = (void *)db; - zTest = sqlite3_mprintf("%s_test", zName); - zTest2 = sqlite3_mprintf("%s_internal_test", zName); - if( !zTest || !zTest2 ){ - rc = SQLITE_NOMEM; - } -#endif - - if( rc!=SQLITE_OK - || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) - || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) -#ifdef SQLITE_TEST - || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) - || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) - || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) -#endif - ); - - sqlite3_free(zTest); - sqlite3_free(zTest2); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenizer.c **************************************/ -/************** Begin file fts3_tokenizer1.c *********************************/ -/* -** 2006 Oct 10 -** -** 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. -** -****************************************************************************** -** -** Implementation of the "simple" full-text-search tokenizer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - - - -/************** Include fts3_tokenizer.h in the middle of fts3_tokenizer1.c **/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -/************** Include sqlite3.h in the middle of fts3_tokenizer.h **********/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3_tokenizer.h *************/ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialised by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3_tokenizer1.c ************/ - -typedef struct simple_tokenizer { - sqlite3_tokenizer base; - char delim[128]; /* flag ASCII delimiters */ -} simple_tokenizer; - -typedef struct simple_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *pInput; /* input we are tokenizing */ - int nBytes; /* size of the input */ - int iOffset; /* current position in pInput */ - int iToken; /* index of next token to be returned */ - char *pToken; /* storage for current token */ - int nTokenAllocated; /* space allocated to zToken buffer */ -} simple_tokenizer_cursor; - - -/* Forward declaration */ -static const sqlite3_tokenizer_module simpleTokenizerModule; - -static int simpleDelim(simple_tokenizer *t, unsigned char c){ - return c<0x80 && t->delim[c]; -} - -/* -** Create a new tokenizer instance. -*/ -static int simpleCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - simple_tokenizer *t; - - t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - - /* TODO(shess) Delimiters need to remain the same from run to run, - ** else we need to reindex. One solution would be a meta-table to - ** track such information in the database, then we'd only want this - ** information on the initial create. - */ - if( argc>1 ){ - int i, n = strlen(argv[1]); - for(i=0; i=0x80 ){ - sqlite3_free(t); - return SQLITE_ERROR; - } - t->delim[ch] = 1; - } - } else { - /* Mark non-alphanumeric ASCII characters as delimiters */ - int i; - for(i=1; i<0x80; i++){ - t->delim[i] = !isalnum(i); - } - } - - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int simpleOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *pInput, int nBytes, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - simple_tokenizer_cursor *c; - - c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->pInput = pInput; - if( pInput==0 ){ - c->nBytes = 0; - }else if( nBytes<0 ){ - c->nBytes = (int)strlen(pInput); - }else{ - c->nBytes = nBytes; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->pToken = NULL; /* no space allocated, yet. */ - c->nTokenAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - sqlite3_free(c->pToken); - sqlite3_free(c); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int simpleNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; - unsigned char *p = (unsigned char *)c->pInput; - - while( c->iOffsetnBytes ){ - int iStartOffset; - - /* Scan past delimiter characters */ - while( c->iOffsetnBytes && simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnBytes && !simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int i, n = c->iOffset-iStartOffset; - if( n>c->nTokenAllocated ){ - c->nTokenAllocated = n+20; - c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated); - if( c->pToken==NULL ) return SQLITE_NOMEM; - } - for(i=0; ipToken[i] = ch<0x80 ? tolower(ch) : ch; - } - *ppToken = c->pToken; - *pnBytes = n; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module simpleTokenizerModule = { - 0, - simpleCreate, - simpleDestroy, - simpleOpen, - simpleClose, - simpleNext, -}; - -/* -** Allocate a new simple tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -void sqlite3Fts3SimpleTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &simpleTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenizer1.c *************************************/ -/************** Begin file fts3_icu.c ****************************************/ -/* -** 2007 June 22 -** -** 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 a tokenizer for fts3 based on the ICU library. -** -** $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) -#ifdef SQLITE_ENABLE_ICU - -/************** Include fts3_tokenizer.h in the middle of fts3_icu.c *********/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -/************** Include sqlite3.h in the middle of fts3_tokenizer.h **********/ -/************** Begin file sqlite3.h *****************************************/ -/* -** 2001 September 15 -** -** 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 header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve to make minor changes if -** experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -** -** @(#) $Id: sqlite3.c,v 1.11 2008/01/11 09:12:24 dwitte%stanford.edu Exp $ -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ - -/* -** Make sure we can call this stuff from C++. -*/ -#if 0 -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -/* -** Make sure these symbols where not defined by some previous header -** file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers {F10010} -** -** {F10011} The #define in the sqlite3.h header file named -** SQLITE_VERSION resolves to a string literal that identifies -** the version of the SQLite library in the format "X.Y.Z", where -** X is the major version number, Y is the minor version number and Z -** is the release number. The X.Y.Z might be followed by "alpha" or "beta". -** {END} For example "3.1.1beta". -** -** The X value is always 3 in SQLite. The X value only changes when -** backwards compatibility is broken and we intend to never break -** backwards compatibility. The Y value only changes when -** there are major feature enhancements that are forwards compatible -** but not backwards compatible. The Z value is incremented with -** each release but resets back to 0 when Y is incremented. -** -** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are as -** with SQLITE_VERSION. {END} For example, for version "3.1.1beta", -** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using -** version 3.1.1 or greater at compile time, programs may use the test -** (SQLITE_VERSION_NUMBER>=3001001). -** -** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. -*/ -#define SQLITE_VERSION "3.5.4" -#define SQLITE_VERSION_NUMBER 3005004 - -/* -** CAPI3REF: Run-Time Library Version Numbers {F10020} -** -** {F10021} The sqlite3_libversion_number() interface returns an integer -** equal to [SQLITE_VERSION_NUMBER]. {END} The value returned -** by this routine should only be different from the header values -** if the application is compiled using an sqlite3.h header from a -** different version of SQLite than library. Cautious programmers might -** include a check in their application to verify that -** sqlite3_libversion_number() always returns the value -** [SQLITE_VERSION_NUMBER]. -** -** {F10022} The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] string. {F10023} The sqlite3_libversion() function returns -** a pointer to the sqlite3_version[] string constant. {END} The -** sqlite3_libversion() function -** is provided for DLL users who can only access functions and not -** constants within the DLL. -*/ -SQLITE_EXTERN const char sqlite3_version[]; -const char *sqlite3_libversion(void); -int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} -** -** {F10101} The sqlite3_threadsafe() routine returns nonzero -** if SQLite was compiled with its mutexes enabled or zero if -** SQLite was compiled with mutexes disabled. {END} If this -** routine returns false, then it is not safe for simultaneously -** running threads to both invoke SQLite interfaces. -** -** Really all this routine does is return true if SQLite was -** compiled with the -DSQLITE_THREADSAFE=1 option and false if -** compiled with -DSQLITE_THREADSAFE=0. If SQLite uses an -** application-defined mutex subsystem, malloc subsystem, collating -** sequence, VFS, SQL function, progress callback, commit hook, -** extension, or other accessories and these add-ons are not -** threadsafe, then clearly the combination will not be threadsafe -** either. Hence, this routine never reports that the library -** is guaranteed to be threadsafe, only when it is guaranteed not -** to be. -*/ -int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle {F12000} -** -** Each open SQLite database is represented by pointer to an instance of the -** opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors -** and [sqlite3_close()] is its destructor. There are many other interfaces -** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on this -** object. -*/ -typedef struct sqlite3 sqlite3; - - -/* -** CAPI3REF: 64-Bit Integer Types {F10200} -** -** Because there is no cross-platform way to specify such types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** {F10201} The sqlite_int64 and sqlite3_int64 types specify a -** 64-bit signed integer. {F10202} The sqlite_uint64 and -** sqlite3_uint64 types specify a 64-bit unsigned integer. {END} -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type -** definitions. The sqlite_int64 and sqlite_uint64 types are -** supported for backwards compatibility only. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection {F12010} -** -** {F12011} The sqlite3_close() interfaces destroys an [sqlite3] object -** allocated by a prior call to [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()]. {F12012} Sqlite3_close() releases all -** memory used by the connection and closes all open files. {END}. -** -** {F12013} If the database connection contains -** [sqlite3_stmt | prepared statements] that have not been finalized -** by [sqlite3_finalize()], then sqlite3_close() returns SQLITE_BUSY -** and leaves the connection open. {F12014} Giving sqlite3_close() -** a NULL pointer is a harmless no-op. {END} -** -** {U12015} Passing this routine a database connection that has already been -** closed results in undefined behavior. {U12016} If other interfaces that -** reference the same database connection are pending (either in the -** same thread or in different threads) when this routine is called, -** then the behavior is undefined and is almost certainly undesirable. -*/ -int sqlite3_close(sqlite3 *); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface {F12100} -** -** {F12101} The sqlite3_exec() interface evaluates zero or more -** UTF-8 encoded, semicolon-separated SQL statements in the zero-terminated -** string of its second argument. {F12102} The SQL -** statements are evaluated in the context of the database connection -** specified by in the first argument. -** {F12103} SQL statements are prepared one by one using -** [sqlite3_prepare()] or the equivalent, evaluated -** using one or more calls to [sqlite3_step()], then destroyed -** using [sqlite3_finalize()]. {F12104} The return value of -** sqlite3_exec() is SQLITE_OK if all SQL statement run -** successfully. -** -** {F12105} If one or more of the SQL statements handed to -** sqlite3_exec() are queries, then -** the callback function specified by the 3rd parameter is -** invoked once for each row of the query result. {F12106} -** If the callback returns a non-zero value then the query -** is aborted, all subsequent SQL statements -** are skipped and the sqlite3_exec() function returns the [SQLITE_ABORT]. -** -** {F12107} The 4th parameter to sqlite3_exec() is an arbitrary pointer -** that is passed through to the callback function as its first parameter. -** -** {F12108} The 2nd parameter to the callback function is the number of -** columns in the query result. {F12109} The 3rd parameter to the callback -** is an array of pointers to strings holding the values for each column -** as extracted using [sqlite3_column_text()]. NULL values in the result -** set result in a NULL pointer. All other value are in their UTF-8 -** string representation. {F12117} -** The 4th parameter to the callback is an array of strings -** obtained using [sqlite3_column_name()] and holding -** the names of each column, also in UTF-8. -** -** {F12110} The callback function may be NULL, even for queries. A NULL -** callback is not an error. It just means that no callback -** will be invoked. -** -** {F12112} If an error occurs while parsing or evaluating the SQL -** then an appropriate error message is written into memory obtained -** from [sqlite3_malloc()] and *errmsg is made to point to that message -** assuming errmsg is not NULL. -** {U12113} The calling function is responsible for freeing the memory -** using [sqlite3_free()]. -** {F12116} If [sqlite3_malloc()] fails while attempting to generate -** the error message, *errmsg is set to NULL. -** {F12114} If errmsg is NULL then no attempt is made to generate an -** error message. Is the return code SQLITE_NOMEM or the original -** error code? What happens if there are multiple errors? -** Do we get code for the first error, or is the choice of reported -** error arbitrary? -** -** {F12115} The return value is is SQLITE_OK if there are no errors and -** some other [SQLITE_OK | return code] if there is an error. -** The particular return value depends on the type of error. {END} -*/ -int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluted */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes {F10210} -** KEYWORDS: SQLITE_OK -** -** Many SQLite functions return an integer result code from the set shown -** above in order to indicates success or failure. -** -** {F10211} The result codes shown here are the only ones returned -** by SQLite in its default configuration. {F10212} However, the -** [sqlite3_extended_result_codes()] API can be used to set a database -** connectoin to return more detailed result codes. {END} -** -** See also: [SQLITE_IOERR_READ | extended result codes] -** -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes {F10220} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that -** many of these result codes are too course-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. {F10221} The extended result codes are enabled or disabled -** for each database connection using the [sqlite3_extended_result_codes()] -** API. {END} -** -** Some of the available extended result codes are listed above. -** We expect the number of extended result codes will be expand -** over time. {U10422} Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. {END} -** -** {F10223} The symbolic name for an extended result code always contains -** a related primary result code as a prefix. {F10224} Primary result -** codes contain a single "_" character. {F10225} Extended result codes -** contain two or more "_" characters. {F10226} The numeric value of an -** extended result code can be converted to its -** corresponding primary result code by masking off the lower 8 bytes. {END} -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) - -/* -** CAPI3REF: Flags For File Open Operations {F10230} -** -** {F10231} Some combination of the these bit values are used as the -** third argument to the [sqlite3_open_v2()] interface and -** as fourth argument to the xOpen method of the -** [sqlite3_vfs] object. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 - -/* -** CAPI3REF: Device Characteristics {F10240} -** -** {F10241} The xDeviceCapabilities method of the [sqlite3_io_methods] -** object returns an integer which is a vector of the these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. {END} -** -** {F10242} The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. {F10243} The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. {F10244} The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. {F10245} The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 - -/* -** CAPI3REF: File Locking Levels {F10250} -** -** {F10251} SQLite uses one of the following integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. {END} -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags {F10260} -** -** {F10261} When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of the -** these integer values as the second argument. -** -** {F10262} When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. {F10263} The SQLITE_SYNC_NORMAL means -** to use normal fsync() semantics. {F10264} The SQLITE_SYNC_FULL flag means -** to use Mac OS-X style fullsync instead of fsync(). -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - - -/* -** CAPI3REF: OS Interface Open File Handle {F11110} -** -** An [sqlite3_file] object represents an open file in the OS -** interface layer. Individual OS interface implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object {F11120} -** -** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to -** an instance of the this object. This object defines the -** methods used to perform various operations against the open file. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -* The second choice is an -** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to -** indicate that only the data of the file and not its inode needs to be -** synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method looks -** to see if any database connection, either in this -** process or in some other process, is holding an RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false if not. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument -** is an integer opcode. The third -** argument is a generic pointer which is intended to be a pointer -** to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes {F11310} -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] -** interface. -** -** {F11311} The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode cases the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. {F11312} This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -*/ -#define SQLITE_FCNTL_LOCKSTATE 1 - -/* -** CAPI3REF: Mutex Handle {F17110} -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. {F17111} The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. {END} It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object {F11140} -** -** An instance of this object defines the interface between the -** SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". -** -** The iVersion field is initially 1 but may be larger for future -** versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered vfs modules are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. -** -** The pNext field is the only fields in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** {F11141} SQLite will guarantee that the zFilename string passed to -** xOpen() is a full pathname as generated by xFullPathname() and -** that the string will be valid and unchanged until xClose() is -** called. {END} So the [sqlite3_file] can store a pointer to the -** filename if it needs to remember the filename for some reason. -** -** {F11142} The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be -** set. -** -** {F11143} SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
{END} -** -** The file I/O implementation can use the object type flags to -** changes the way it deals with files. For example, an application -** that does not care about crash recovery or rollback, might make -** the open of a journal file a no-op. Writes to this journal are -** also a no-op. Any attempt to read the journal return SQLITE_IOERR. -** Or the implementation might recognize the a database file will -** be doing page-aligned sector reads and writes in a random order -** and set up its I/O subsystem accordingly. -** -** {F11144} SQLite might also add one of the following flags to the xOpen -** method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases, journals and for subjournals. -** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened -** for exclusive access. This flag is set for all files except -** for the main database file. {END} -** -** {F11148} At least szOsFile bytes of memory is allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. {END} The xOpen method does not have to -** allocate the structure; it should just fill it in. -** -** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existance of a file, -** or [SQLITE_ACCESS_READWRITE] to test to see -** if a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test to see if a file is at least readable. {END} The file can be a -** directory. -** -** {F11150} SQLite will always allocate at least mxPathname+1 byte for -** the output buffers for xGetTempname and xFullPathname. {F11151} The exact -** size of the output buffer is also passed as a parameter to both -** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN -** should be returned. As this is handled as a fatal error by SQLite, -** vfs implementations should endeavor to prevent this by setting -** mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), and xCurrentTime() interfaces -** are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. The -** xSleep() method cause the calling thread to sleep for at -** least the number of microseconds given. The xCurrentTime() -** method returns a Julian Day Number for the current date and -** time. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -struct sqlite3_vfs { - int iVersion; /* Structure version number */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); - int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - /* New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method {F11190} -** -** {F11191} These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. {END} They determine -** the kind of what kind of permissions the xAccess method is -** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks to see if the file exists. {F11193} With -** SQLITE_ACCESS_READWRITE, the xAccess method checks to see -** if the file is both readable and writable. {F11194} With -** SQLITE_ACCESS_READ the xAccess method -** checks to see if the file is readable. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 -#define SQLITE_ACCESS_READ 2 - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} -** -** {F12201} The sqlite3_extended_result_codes() routine enables or disables the -** [SQLITE_IOERR_READ | extended result codes] feature on a database -** connection if its 2nd parameter is -** non-zero or zero, respectively. {F12202} -** By default, SQLite API routines return one of only 26 integer -** [SQLITE_OK | result codes]. {F12203} When extended result codes -** are enabled by this routine, the repetoire of result codes can be -** much larger and can (hopefully) provide more detailed information -** about the cause of an error. -** -** {F12204} The second argument is a boolean value that turns extended result -** codes on and off. {F12205} Extended result codes are off by default for -** backwards compatibility with older versions of SQLite. -*/ -int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid {F12220} -** -** {F12221} Each entry in an SQLite table has a unique 64-bit signed -** integer key called the "rowid". {F12222} The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. {F12223} If -** the table has a column of type INTEGER PRIMARY KEY then that column -** is another an alias for the rowid. -** -** {F12224} This routine returns the rowid of the most recent -** successful INSERT into the database from the database connection -** shown in the first argument. {F12225} If no successful inserts -** have ever occurred on this database connection, zero is returned. -** -** {F12226} If an INSERT occurs within a trigger, then the rowid of the -** inserted row is returned by this routine as long as the trigger -** is running. {F12227} But once the trigger terminates, the value returned -** by this routine reverts to the last value inserted before the -** trigger fired. -** -** {F12228} An INSERT that fails due to a constraint violation is not a -** successful insert and does not change the value returned by this -** routine. {F12229} Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. {F12231} When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface. -** -** {UF12232} If another thread does a new insert on the same database connection -** while this routine is running and thus changes the last insert rowid, -** then the return value of this routine is undefined. -*/ -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified {F12240} -** -** {F12241} This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the connection specified by the first parameter. {F12242} Only -** changes that are directly specified by the INSERT, UPDATE, or -** DELETE statement are counted. Auxiliary changes caused by -** triggers are not counted. {F12243} Use the [sqlite3_total_changes()] function -** to find the total number of changes including changes caused by triggers. -** -** {F12244} Within the body of a trigger, the sqlite3_changes() interface -** can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** -** {F12245} All changes are counted, even if they are later undone by a -** ROLLBACK or ABORT. {F12246} Except, changes associated with creating and -** dropping tables are not counted. -** -** {F12247} If a callback invokes [sqlite3_exec()] or [sqlite3_step()] -** recursively, then the changes in the inner, recursive call are -** counted together with the changes in the outer call. -** -** {F12248} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going through and deleting individual elements from the -** table.) Because of this optimization, the change count for -** "DELETE FROM table" will be zero regardless of the number of elements -** that were originally in the table. {F12251} To get an accurate count -** of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {UF12252} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. -*/ -int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified {F12260} -*** -** {F12261} This function returns the number of database rows that have been -** modified by INSERT, UPDATE or DELETE statements since the database handle -** was opened. {F12262} The count includes UPDATE, INSERT and DELETE -** statements executed as part of trigger programs. {F12263} All changes -** are counted as soon as the statement that makes them is completed -** (when the statement handle is passed to [sqlite3_reset()] or -** [sqlite3_finalize()]). {END} -** -** See also the [sqlite3_change()] interface. -** -** {F12265} SQLite implements the command "DELETE FROM table" without -** a WHERE clause by dropping and recreating the table. (This is much -** faster than going -** through and deleting individual elements form the table.) Because of -** this optimization, the change count for "DELETE FROM table" will be -** zero regardless of the number of elements that were originally in the -** table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. -** -** {U12264} If another thread makes changes on the same database connection -** while this routine is running then the return value of this routine -** is undefined. {END} -*/ -int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query {F12270} -** -** {F12271} This function causes any pending database operation to abort and -** return at its earliest opportunity. {END} This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** {F12272} It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. {U12273} But it -** is not safe to call this routine with a database connection that -** is closed or might close before sqlite3_interrupt() returns. -** -** If an SQL is very nearly finished at the time when sqlite3_interrupt() -** is called, then it might not have an opportunity to be interrupted. -** It might continue to completion. -** {F12274} The SQL operation that is interrupted will return -** [SQLITE_INTERRUPT]. {F12275} If the interrupted SQL operation is an -** INSERT, UPDATE, or DELETE that is inside an explicit transaction, -** then the entire transaction will be rolled back automatically. -** {F12276} A call to sqlite3_interrupt() has no effect on SQL statements -** that are started after sqlite3_interrupt() returns. -*/ -void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} -** -** These routines are useful for command-line input to determine if the -** currently entered text seems to form complete a SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. These routines return true if the input string -** appears to be a complete SQL statement. A statement is judged to be -** complete if it ends with a semicolon and is not a fragment of a -** CREATE TRIGGER statement. These routines do not parse the SQL and -** so will not detect syntactically incorrect SQL. -** -** {F10511} These functions return true if the given input string -** ends with a semicolon optionally followed by whitespace or -** comments. {F10512} For sqlite3_complete(), -** the parameter must be a zero-terminated UTF-8 string. {F10513} For -** sqlite3_complete16(), a zero-terminated machine byte order UTF-16 string -** is required. {F10514} These routines return false if the terminal -** semicolon is within a comment, a string literal or a quoted identifier -** (in other words if the final semicolon is not really a separate token -** but part of a larger token) or if the final semicolon is -** in between the BEGIN and END keywords of a CREATE TRIGGER statement. -** {END} -*/ -int sqlite3_complete(const char *sql); -int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} -** -** {F12311} This routine identifies a callback function that might be -** invoked whenever an attempt is made to open a database table -** that another thread or process has locked. -** {F12312} If the busy callback is NULL, then [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. -** {F12313} If the busy callback is not NULL, then the -** callback will be invoked with two arguments. {F12314} The -** first argument to the handler is a copy of the void* pointer which -** is the third argument to this routine. {F12315} The second argument to -** the handler is the number of times that the busy handler has -** been invoked for this locking event. {F12316} If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** {F12317} If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that -** it will be invoked when there is lock contention. {F12319} -** If SQLite determines that invoking the busy handler could result in -** a deadlock, it will go ahead and return [SQLITE_BUSY] or -** [SQLITE_IOERR_BLOCKED] instead of invoking the -** busy handler. {END} -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** {F12321} The default busy callback is NULL. {END} -** -** {F12322} The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. {F12323} SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. {F12324} If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. {F12325} This error code promotion -** forces an automatic rollback of the changes. {END} See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** {F12326} Sqlite is re-entrant, so the busy handler may start a new -** query. {END} (It is not clear why anyone would every want to do this, -** but it is allowed, in theory.) {U12327} But the busy handler may not -** close the database. Closing the database from a busy handler will delete -** data structures out from under the executing query and will -** probably result in a segmentation fault or other runtime error. {END} -** -** {F12328} There can only be a single busy handler defined for each database -** connection. Setting a new busy handler clears any previous one. -** {F12329} Note that calling [sqlite3_busy_timeout()] will also set or clear -** the busy handler. -** -** {F12331} When operating in [sqlite3_enable_shared_cache | shared cache mode], -** only a single busy handler can be defined for each database file. -** So if two database connections share a single cache, then changing -** the busy handler on one connection will also change the busy -** handler in the other connection. {F12332} The busy handler is invoked -** in the thread that was running when the lock contention occurs. -*/ -int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout {F12340} -** -** {F12341} This routine sets a [sqlite3_busy_handler | busy handler] -** that sleeps for a while when a -** table is locked. {F12342} The handler will sleep multiple times until -** at least "ms" milliseconds of sleeping have been done. {F12343} After -** "ms" milliseconds of sleeping, the handler returns 0 which -** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** {F12344} Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** {F12345} There can only be a single busy handler for a particular database -** connection. If another busy handler was defined -** (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared. -*/ -int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries {F12370} -** -** This next routine is a convenience wrapper around [sqlite3_exec()]. -** {F12371} Instead of invoking a user-supplied callback for each row of the -** result, this routine remembers each row of the result in memory -** obtained from [sqlite3_malloc()], then returns all of the result after the -** query has finished. {F12372} -** -** As an example, suppose the query result where this table: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** If the 3rd argument were &azResult then after the function returns -** azResult will contain the following data: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
-** -** Notice that there is an extra row of data containing the column -** headers. But the *nrow return value is still 3. *ncolumn is -** set to 2. In general, the number of values inserted into azResult -** will be ((*nrow) + 1)*(*ncolumn). -** -** {U12374} After the calling function has finished using the result, it should -** pass the result data pointer to sqlite3_free_table() in order to -** release the memory that was malloc-ed. Because of the way the -** [sqlite3_malloc()] happens, the calling function must not try to call -** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release -** the memory properly and safely. {END} -** -** {F12373} The return value of this routine is the same as -** from [sqlite3_exec()]. -*/ -int sqlite3_get_table( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be executed */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg /* Error msg written here */ -); -void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions {F17400} -** -** These routines are workalikes of the "printf()" family of functions -** from the standard C library. -** -** {F17401} The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** {U17402} The strings returned by these two routines should be -** released by [sqlite3_free()]. {F17403} Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** {F17404} In sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. {END} Note that the order of the -** first two parameters is reversed from snprintf(). This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. {F17405} Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer. {END} We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** {F17406} As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. {F17407} The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. {END} So the longest string that can be completely -** written will be n-1 characters. -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** {F17410} The %q option works like %s in that it substitutes a null-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal. {END} By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, so some string variable contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you -** should always use %q instead of %s when inserting text into a string -** literal. -** -** {F17411} The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Or if the parameter in the argument -** list is a NULL pointer, %Q substitutes the text "NULL" (without single -** quotes) in place of the %Q option. {END} So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** {F17412} The "%z" formatting option works exactly like "%s" with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string. {END} -*/ -char *sqlite3_mprintf(const char*,...); -char *sqlite3_vmprintf(const char*, va_list); -char *sqlite3_snprintf(int,char*,const char*, ...); - -/* -** CAPI3REF: Memory Allocation Subsystem {F17300} -** -** {F17301} The SQLite core uses these three routines for all of its own -** internal memory allocation needs. {END} "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** windows VFS uses native malloc and free for some operations. -** -** {F17302} The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** {F17303} If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. {F17304} If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** {F17305} Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. {F17306} The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. {U17307} After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** {U17309} Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_free(). -** -** {F17310} The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter. {F17311} If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** {F17312} If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** {F17313} Sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** {F17314} If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** {F17315} If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** {F17316} The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary. {END} -** -** {F17381} The default implementation -** of the memory allocation subsystem uses the malloc(), realloc() -** and free() provided by the standard C library. {F17382} However, if -** SQLite is compiled with the following C preprocessor macro -** -**
SQLITE_MEMORY_SIZE=NNN
-** -** where NNN is an integer, then SQLite create a static -** array of at least NNN bytes in size and use that array -** for all of its dynamic memory allocation needs. {END} Additional -** memory allocator options may be added in future releases. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be -** used. -** -** The windows OS interface layer calls -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -*/ -void *sqlite3_malloc(int); -void *sqlite3_realloc(void*, int); -void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics {F17370} -** -** In addition to the basic three allocation routines -** [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()], -** the memory allocation subsystem included with the SQLite -** sources provides the interfaces shown here. -** -** {F17371} The sqlite3_memory_used() routine returns the -** number of bytes of memory currently outstanding (malloced but not freed). -** {F17372} The value returned by sqlite3_memory_used() includes -** any overhead added by SQLite, but not overhead added by the -** library malloc() that backs the sqlite3_malloc() implementation. -** {F17373} The sqlite3_memory_highwater() routines returns the -** maximum number of bytes that have been outstanding at any time -** since the highwater mark was last reset. -** {F17374} The byte count returned by sqlite3_memory_highwater() -** uses the same byte counting rules as sqlite3_memory_used(). {END} -** In other words, overhead added internally by SQLite is counted, -** but overhead from the underlying system malloc is not. -** {F17375} If the parameter to sqlite3_memory_highwater() is true, -** then the highwater mark is reset to the current value of -** sqlite3_memory_used() and the prior highwater mark (before the -** reset) is returned. {F17376} If the parameter to -** sqlite3_memory_highwater() is zero, then the highwater mark is -** unchanged. -*/ -sqlite3_int64 sqlite3_memory_used(void); -sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks {F12500} -** -** {F12501} This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. {F12502} -** The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. {F12503} At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. {F12504} If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer shall -** fail with an SQLITE_ERROR error code and an appropriate error message. {END} -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. {F12505} When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer shall fail -** with an SQLITE_ERROR error code and an error message explaining that -** access is denied. {F12506} If the authorizer code (the 2nd parameter -** to the authorizer callback is anything other than [SQLITE_READ], then -** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. -** If the authorizer code is [SQLITE_READ] and the callback returns -** [SQLITE_IGNORE] then the prepared statement is constructed to -** insert a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. {END} -** -** {F12510} The first parameter to the authorizer callback is a copy of -** the third parameter to the sqlite3_set_authorizer() interface. -** {F12511} The second parameter to the callback is an integer -** [SQLITE_COPY | action code] that specifies the particular action -** to be authorized. {END} The available action codes are -** [SQLITE_COPY | documented separately]. {F12512} The third through sixth -** parameters to the callback are zero-terminated strings that contain -** additional details about the action to be authorized. {END} -** -** An authorizer is used when preparing SQL statements from an untrusted -** source, to ensure that the SQL statements do not try to access data -** that they are not allowed to see, or that they do not try to -** execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. -** -** {F12520} Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call. {F12521} A NULL authorizer means that no authorization -** callback is invoked. {F12522} The default authorizer is NULL. {END} -** -** Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. {F12523} Authorization is not -** performed during statement evaluation in [sqlite3_step()]. {END} -*/ -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes {F12590} -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes {F12550} -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorizer certain SQL statement actions. {F12551} The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. {END} -** -** These action code values signify what kind of operation is to be -** authorized. {F12552} The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. {F12553} The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable. {F12554} The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* NULL NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* Function Name NULL */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions {F12280} -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** {F12281} The callback function registered by sqlite3_trace() is invoked -** at the first [sqlite3_step()] for the evaluation of an SQL statement. -** {F12282} Only a single trace callback can be registered at a time. -** Each call to sqlite3_trace() overrides the previous. {F12283} A -** NULL callback for sqlite3_trace() disables tracing. {F12284} The -** first argument to the trace callback is a copy of the pointer which -** was the 3rd argument to sqlite3_trace. {F12285} The second argument -** to the trace callback is a zero-terminated UTF8 string containing -** the original text of the SQL statement as it was passed into -** [sqlite3_prepare_v2()] or the equivalent. {END} Note that the -** host parameter are not expanded in the SQL statement text. -** -** {F12287} The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. {F12288} The first parameter to the -** profile callback is a copy of the 3rd parameter to sqlite3_profile(). -** {F12289} The second parameter to the profile callback is a -** zero-terminated UTF-8 string that contains the complete text of -** the SQL statement as it was processed by [sqlite3_prepare_v2()] or -** the equivalent. {F12290} The third parameter to the profile -** callback is an estimate of the number of nanoseconds of -** wall-clock time required to run the SQL statement from start -** to finish. {END} -** -** The sqlite3_profile() API is currently considered experimental and -** is subject to change. -*/ -void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks {F12910} -** -** {F12911} This routine configures a callback function - the -** progress callback - that is invoked periodically during long -** running calls to [sqlite3_exec()], [sqlite3_step()] and -** [sqlite3_get_table()]. {END} An example use for this -** interface is to keep a GUI updated during a large query. -** -** {F12912} The progress callback is invoked once for every N virtual -** machine opcodes, where N is the second argument to this function. -** {F12913} The progress callback itself is identified by the third -** argument to this function. {F12914} The fourth argument to this -** function is a void pointer passed to the progress callback -** function each time it is invoked. {END} -** -** {F12915} If a call to [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] results in fewer than N opcodes being executed, -** then the progress callback is never invoked. {END} -** -** {F12916} Only a single progress callback function may be registered for each -** open database connection. Every call to sqlite3_progress_handler() -** overwrites the results of the previous call. {F12917} -** To remove the progress callback altogether, pass NULL as the third -** argument to this function. {END} -** -** {F12918} If the progress callback returns a result other than 0, then -** the current query is immediately terminated and any database changes -** rolled back. {F12919} -** The containing [sqlite3_exec()], [sqlite3_step()], or -** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. {END} This feature -** can be used, for example, to implement the "Cancel" button on a -** progress dialog box in a GUI. -*/ -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection {F12700} -** -** {F12701} These routines open an SQLite database file whose name -** is given by the filename argument. -** {F12702} The filename argument is interpreted as UTF-8 -** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 -** in the native byte order for [sqlite3_open16()]. -** {F12703} An [sqlite3*] handle is returned in *ppDb, even -** if an error occurs. {F12723} (Exception: if SQLite is unable -** to allocate memory to hold the [sqlite3] object, a NULL will -** be written into *ppDb instead of a pointer to the [sqlite3] object.) -** {F12704} If the database is opened (and/or created) -** successfully, then [SQLITE_OK] is returned. {F12705} Otherwise an -** error code is returned. {F12706} The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error. -** -** {F12707} The default encoding for the database will be UTF-8 if -** [sqlite3_open()] or [sqlite3_open_v2()] is called and -** UTF-16 in the native byte order if [sqlite3_open16()] is used. -** -** {F12708} Whether or not an error occurs when it is opened, resources -** associated with the [sqlite3*] handle should be released by passing it -** to [sqlite3_close()] when it is no longer required. -** -** {F12709} The [sqlite3_open_v2()] interface works like [sqlite3_open()] -** except that it acccepts two additional parameters for additional control -** over the new database connection. {F12710} The flags parameter can be -** one of: -** -**
    -**
  1. [SQLITE_OPEN_READONLY] -**
  2. [SQLITE_OPEN_READWRITE] -**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] -**
-** -** {F12711} The first value opens the database read-only. -** {F12712} If the database does not previously exist, an error is returned. -** {F12713} The second option opens -** the database for reading and writing if possible, or reading only if -** if the file is write protected. {F12714} In either case the database -** must already exist or an error is returned. {F12715} The third option -** opens the database for reading and writing and creates it if it does -** not already exist. {F12716} -** The third options is behavior that is always used for [sqlite3_open()] -** and [sqlite3_open16()]. -** -** {F12717} If the filename is ":memory:", then an private -** in-memory database is created for the connection. {F12718} This in-memory -** database will vanish when the database connection is closed. {END} Future -** version of SQLite might make use of additional special filenames -** that begin with the ":" character. It is recommended that -** when a database filename really does begin with -** ":" that you prefix the filename with a pathname like "./" to -** avoid ambiguity. -** -** {F12719} If the filename is an empty string, then a private temporary -** on-disk database will be created. {F12720} This private database will be -** automatically deleted as soon as the database connection is closed. -** -** {F12721} The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system -** interface that the new database connection should use. {F12722} If the -** fourth parameter is a NULL pointer then the default [sqlite3_vfs] -** object is used. {END} -** -** Note to windows users: The encoding used for the filename argument -** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** [sqlite3_open()] or [sqlite3_open_v2()]. -*/ -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Error Codes And Messages {F12800} -** -** {F12801} The sqlite3_errcode() interface returns the numeric -** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] -** for the most recent failed sqlite3_* API call associated -** with [sqlite3] handle 'db'. {U12802} If a prior API call failed but the -** most recent API call succeeded, the return value from sqlite3_errcode() -** is undefined. {END} -** -** {F12803} The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF8 or UTF16 respectively. -** {F12804} Memory to hold the error message string is managed internally. -** {U12805} The -** string may be overwritten or deallocated by subsequent calls to SQLite -** interface functions. {END} -** -** {F12806} Calls to many sqlite3_* functions set the error code and -** string returned by [sqlite3_errcode()], [sqlite3_errmsg()], and -** [sqlite3_errmsg16()] overwriting the previous values. {F12807} -** Except, calls to [sqlite3_errcode()], -** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the -** results of future invocations. {F12808} Calls to API routines that -** do not return an error code (example: [sqlite3_data_count()]) do not -** change the error code returned by this routine. {F12809} Interfaces that -** are not associated with a specific database connection (examples: -** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] do not change -** the return code. {END} -** -** {F12810} Assuming no other intervening sqlite3_* API calls are made, -** the error code returned by this function is associated with the same -** error as the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. -*/ -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -const void *sqlite3_errmsg16(sqlite3*); - -/* -** CAPI3REF: SQL Statement Object {F13000} -** -** An instance of this object represent single SQL statements. This -** object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to host parameters using -** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Compiling An SQL Statement {F13010} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** {F13011} The first argument "db" is an [sqlite3 | SQLite database handle] -** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] -** or [sqlite3_open16()]. {F13012} -** The second argument "zSql" is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. {END} -** -** {F13013} If the nByte argument is less -** than zero, then zSql is read up to the first zero terminator. -** {F13014} If nByte is non-negative, then it is the maximum number of -** bytes read from zSql. When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} -** -** {F13015} *pzTail is made to point to the first byte past the end of the -** first SQL statement in zSql. These routines only compiles the first -** statement in zSql, so *pzTail is left pointing to what remains -** uncompiled. {END} -** -** {F13016} *ppStmt is left pointing to a compiled -** [sqlite3_stmt | SQL statement structure] that can be -** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be -** set to NULL. {F13017} If the input text contains no SQL (if the input -** is and empty string or a comment) then *ppStmt is set to NULL. -** {U13018} The calling procedure is responsible for deleting the -** compiled SQL statement -** using [sqlite3_finalize()] after it has finished with it. -** -** {F13019} On success, [SQLITE_OK] is returned. Otherwise an -** [SQLITE_ERROR | error code] is returned. {END} -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** {F13020} In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. {END} This causes the [sqlite3_step()] interface to -** behave a differently in two ways: -** -**
    -**
  1. {F13022} -** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. {F12023} If the schema has changed in -** a way that makes the statement no longer valid, [sqlite3_step()] will still -** return [SQLITE_SCHEMA]. {END} But unlike the legacy behavior, -** [SQLITE_SCHEMA] is now a fatal error. {F12024} Calling -** [sqlite3_prepare_v2()] again will not make the -** error go away. {F12025} Note: use [sqlite3_errmsg()] to find the text -** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} -**
  2. -** -**
  3. -** {F13030} When an error occurs, -** [sqlite3_step()] will return one of the detailed -** [SQLITE_ERROR | result codes] or -** [SQLITE_IOERR_READ | extended result codes]. {F13031} -** The legacy behavior was that [sqlite3_step()] would only return a generic -** [SQLITE_ERROR] result code and you would have to make a second call to -** [sqlite3_reset()] in order to find the underlying cause of the problem. -** {F13032} -** With the "v2" prepare interfaces, the underlying reason for the error is -** returned immediately. {END} -**
  4. -**
-*/ -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPIREF: Retrieving Statement SQL {F13100} -** -** {F13101} If the compiled SQL statement passed as an argument was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()], -** then this function returns a pointer to a zero-terminated string -** containing a copy of the original SQL statement. {F13102} The -** pointer is valid until the statement -** is deleted using sqlite3_finalize(). -** {F13103} The string returned by sqlite3_sql() is always UTF8 even -** if a UTF16 string was originally entered using [sqlite3_prepare16_v2()] -** or the equivalent. -** -** {F13104} If the statement was compiled using either of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this -** function returns NULL. -*/ -const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Dynamically Typed Value Object {F15000} -** -** {F15001} SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. {END} -** SQLite uses dynamic typing for the values it stores. -** {F15002} Values stored in sqlite3_value objects can be -** be integers, floating point values, strings, BLOBs, or NULL. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object {F16001} -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. {F16002} A pointer to an sqlite3_context -** object is always first parameter to application-defined SQL functions. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements {F13500} -** -** {F13501} In the SQL strings input to [sqlite3_prepare_v2()] and its -** variants, literals may be replace by a parameter in one -** of these forms: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :AAA -**
  • @AAA -**
  • $VVV -**
-** -** In the parameter forms shown above NNN is an integer literal, -** AAA is an alphanumeric identifier and VVV is a variable name according -** to the syntax rules of the TCL programming language. {END} -** The values of these parameters (also called "host parameter names") -** can be set using the sqlite3_bind_*() routines defined here. -** -** {F13502} The first argument to the sqlite3_bind_*() routines always -** is a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. {F13503} The second -** argument is the index of the parameter to be set. {F13504} The -** first parameter has an index of 1. {F13505} When the same named -** parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** {F13506} The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_name()] API if desired. {F13507} The index -** for "?NNN" parameters is the value of NNN. -** {F13508} The NNN value must be between 1 and the compile-time -** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). {END} -** See limits.html for additional information. -** -** {F13509} The third argument is the value to bind to the parameter. {END} -** -** {F13510} In those -** routines that have a fourth argument, its value is the number of bytes -** in the parameter. To be clear: the value is the number of bytes in the -** string, not the number of characters. {F13511} The number -** of bytes does not include the zero-terminator at the end of strings. -** {F13512} -** If the fourth parameter is negative, the length of the string is -** number of bytes up to the first zero terminator. {END} -** -** {F13513} -** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** text after SQLite has finished with it. {F13514} If the fifth argument is -** the special value [SQLITE_STATIC], then the library assumes that the -** information is in static, unmanaged space and does not need to be freed. -** {F13515} If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. {END} -** -** {F13520} The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeros. {F13521} A zeroblob uses a fixed amount of memory -** (just an integer to hold it size) while it is being processed. {END} -** Zeroblobs are intended to serve as place-holders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | increment BLOB I/O] routines. {F13522} A negative -** value for the zeroblob results in a zero-length BLOB. {END} -** -** {F13530} The sqlite3_bind_*() routines must be called after -** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and -** before [sqlite3_step()]. {F13531} -** Bindings are not cleared by the [sqlite3_reset()] routine. -** {F13532} Unbound parameters are interpreted as NULL. {END} -** -** {F13540} These routines return [SQLITE_OK] on success or an error code if -** anything goes wrong. {F13541} [SQLITE_RANGE] is returned if the parameter -** index is out of range. {F13542} [SQLITE_NOMEM] is returned if malloc fails. -** {F13543} [SQLITE_MISUSE] is returned if these routines are called on a -** virtual machine that is the wrong state or which has already been finalized. -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of Host Parameters {F13600} -** -** {F13601} Return the largest host parameter index in the precompiled -** statement given as the argument. {F13602} When the host parameters -** are of the forms like ":AAA", "$VVV", "@AAA", or "?", -** then they are assigned sequential increasing numbers beginning -** with one, so the value returned is the number of parameters. -** {F13603} However -** if the same host parameter name is used multiple times, each occurrance -** is given the same number, so the value returned in that case is the number -** of unique host parameter names. {F13604} If host parameters of the -** form "?NNN" are used (where NNN is an integer) then there might be -** gaps in the numbering and the value returned by this interface is -** the index of the host parameter with the largest index value. {END} -** -** {U13605} The prepared statement must not be [sqlite3_finalize | finalized] -** prior to this routine returning. Otherwise the results are undefined -** and probably undesirable. -*/ -int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter {F13620} -** -** {F13621} This routine returns a pointer to the name of the n-th -** parameter in a [sqlite3_stmt | prepared statement]. {F13622} -** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" -** is included as part of the name. {F13626} -** Parameters of the form "?" or "?NNN" have no name. -** -** {F13623} The first host parameter has an index of 1, not 0. -** -** {F13624} If the value n is out of range or if the n-th parameter is -** nameless, then NULL is returned. {F13625} The returned string is -** always in the UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -*/ -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name {F13640} -** -** {F13641} This routine returns the index of a host parameter with the -** given name. {F13642} The name must match exactly. {F13643} -** If no parameter with the given name is found, return 0. -** {F13644} Parameter names must be UTF8. -*/ -int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} -** -** {F13661} Contrary to the intuition of many, [sqlite3_reset()] does not -** reset the [sqlite3_bind_blob | bindings] on a -** [sqlite3_stmt | prepared statement]. {F13662} Use this routine to -** reset all host parameters to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set {F13710} -** -** {F13711} Return the number of columns in the result set returned by the -** [sqlite3_stmt | compiled SQL statement]. {F13712} This routine returns 0 -** if pStmt is an SQL statement that does not return data (for -** example an UPDATE). -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set {F13720} -** -** {F13721} These routines return the name assigned to a particular column -** in the result set of a SELECT statement. {F13722} The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF16 string. {F13723} The first parameter is the -** [sqlite3_stmt | prepared statement] that implements the SELECT statement. -** The second parameter is the column number. The left-most column is -** number 0. -** -** {F13724} The returned string pointer is valid until either the -** [sqlite3_stmt | prepared statement] is destroyed by [sqlite3_finalize()] -** or until the next call sqlite3_column_name() or sqlite3_column_name16() -** on the same column. -** -** {F13725} If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -*/ -const char *sqlite3_column_name(sqlite3_stmt*, int N); -const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result {F13740} -** -** {F13741} These routines provide a means to determine what column of what -** table in which database a result of a SELECT statement comes from. -** {F13742} The name of the database or table or column can be returned as -** either a UTF8 or UTF16 string. {F13743} The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. {F13744} -** The returned string is valid until -** the [sqlite3_stmt | prepared statement] is destroyed using -** [sqlite3_finalize()] or until the same information is requested -** again in a different encoding. -** -** {F13745} The names returned are the original un-aliased names of the -** database, table, and column. -** -** {F13746} The first argument to the following calls is a -** [sqlite3_stmt | compiled SQL statement]. -** {F13747} These functions return information about the Nth column returned by -** the statement, where N is the second function argument. -** -** {F13748} If the Nth column returned by the statement is an expression -** or subquery and is not a column value, then all of these functions -** return NULL. {F13749} Otherwise, they return the -** name of the attached database, table and column that query result -** column was extracted from. -** -** {F13750} As with all other SQLite APIs, those postfixed with "16" return -** UTF-16 encoded strings, the other functions return UTF-8. {END} -** -** These APIs are only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -** -** {U13751} -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -*/ -const char *sqlite3_column_database_name(sqlite3_stmt*,int); -const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -const char *sqlite3_column_table_name(sqlite3_stmt*,int); -const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result {F13760} -** -** The first parameter is a [sqlite3_stmt | compiled SQL statement]. -** {F13761} If this statement is a SELECT statement and the Nth column of the -** returned result set of that SELECT is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned. {F13762} If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** {F13763} The returned string is always UTF-8 encoded. {END} -** For example, in the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** And the following statement compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** Then this routine would return the string "VARIANT" for the second -** result column (i==1), and a NULL pointer for the first result column -** (i==0). -** -** SQLite uses dynamic run-time typing. So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *, int i); -const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement {F13200} -** -** After an [sqlite3_stmt | SQL statement] has been prepared with a call -** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of -** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], -** then this function must be called one or more times to evaluate the -** statement. -** -** The details of the behavior of this sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** With the "v2" interface, any of the other [SQLITE_OK | result code] -** or [SQLITE_IOERR_READ | extended result code] might be returned as -** well. -** -** [SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. If the statement is a COMMIT -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a COMMIT and occurs within a -** explicit transaction then you should rollback the transaction before -** continuing. -** -** [SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** If the SQL statement being executed returns any data, then -** [SQLITE_ROW] is returned each time a new row of data is ready -** for processing by the caller. The values may be accessed using -** the [sqlite3_column_int | column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** [SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** With the legacy interface, a more specific error code (example: -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [sqlite3_stmt | prepared statement]. In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [sqlite3_stmt | prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** Goofy Interface Alert: -** In the legacy interface, -** the sqlite3_step() API always returns a generic error code, -** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] -** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or -** [sqlite3_finalize()] in order to find one of the specific -** [SQLITE_ERROR | result codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the -** more specific [SQLITE_ERROR | result codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set {F13770} -** -** Return the number of values in the current row of the result set. -** -** {F13771} After a call to [sqlite3_step()] that returns [SQLITE_ROW], -** this routine -** will return the same value as the [sqlite3_column_count()] function. -** {F13772} -** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or -** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been -** called on the [sqlite3_stmt | prepared statement] for the first time, -** this routine returns zero. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes {F10265} -** -** {F10266}Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
{END} -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Results Values From A Query {F13800} -** -** These routines return information about -** a single column of the current result row of a query. In every -** case the first argument is a pointer to the -** [sqlite3_stmt | SQL statement] that is being -** evaluated (the [sqlite3_stmt*] that was returned from -** [sqlite3_prepare_v2()] or one of its variants) and -** the second argument is the index of the column for which information -** should be returned. The left-most column of the result set -** has an index of 0. -** -** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** The sqlite3_column_type() routine returns -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** The value returned does not include the zero terminator at the end -** of the string. For clarity: the value returned is the number of -** bytes in the string, not the number of characters. -** -** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even zero-length strings, are always zero terminated. The return -** value from sqlite3_column_blob() for a zero-length blob is an arbitrary -** pointer, possibly even a NULL pointer. -** -** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() -** but leaves the result in UTF-16 instead of UTF-8. -** The zero terminator is not included in this count. -** -** These routines attempt to convert the value where appropriate. For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to do the conversion -** automatically. The following table details the conversions that -** are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as for INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
-** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** on equavalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() -** or sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.

  • -** -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.

  • -** -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.

  • -**
-** -** Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer points to will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometime it is -** not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), -** or sqlite3_column_text16() first to force the result into the desired -** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to -** find the size of the result. Do not mix call to sqlite3_column_text() or -** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not -** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). -** -** The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. The memory space used to hold strings -** and blobs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM]. -*/ -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object {F13300} -** -** The sqlite3_finalize() function is called to delete a -** [sqlite3_stmt | compiled SQL statement]. If the statement was -** executed successfully, or not executed at all, then SQLITE_OK is returned. -** If execution of the statement failed then an -** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] -** is returned. -** -** This routine can be called at any point during the execution of the -** [sqlite3_stmt | virtual machine]. If the virtual machine has not -** completed execution when this routine is called, that is like -** encountering an error or an interrupt. (See [sqlite3_interrupt()].) -** Incomplete updates may be rolled back and transactions cancelled, -** depending on the circumstances, and the -** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. -*/ -int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object {F13330} -** -** The sqlite3_reset() function is called to reset a -** [sqlite3_stmt | compiled SQL statement] object. -** back to its initial state, ready to be re-executed. -** Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -*/ -int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions {F16100} -** -** The following two functions are used to add SQL functions or aggregates -** or to redefine the behavior of existing SQL functions or aggregates. The -** difference only between the two is that the second parameter, the -** name of the (scalar) function or aggregate, is encoded in UTF-8 for -** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). -** -** The first argument is the [sqlite3 | database handle] that holds the -** SQL function or aggregate is to be added or redefined. If a single -** program uses more than one database handle internally, then SQL -** functions or aggregates must be added individually to each database -** handle with which they will be used. -** -** The second parameter is the name of the SQL function to be created -** or redefined. -** The length of the name is limited to 255 bytes, exclusive of the -** zero-terminator. Note that the name length limit is in bytes, not -** characters. Any attempt to create a function with a longer name -** will result in an SQLITE_ERROR error. -** -** The third parameter is the number of arguments that the SQL function or -** aggregate takes. If this parameter is negative, then the SQL function or -** aggregate may take any number of arguments. -** -** The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Any SQL function implementation should be able to work -** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. It is allowed to -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what -** text encoding is used, then the fourth argument should be -** [SQLITE_ANY]. -** -** The fifth parameter is an arbitrary pointer. The implementation -** of the function can gain access to this pointer using -** [sqlite3_user_data()]. -** -** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL -** function or aggregate. A scalar SQL function requires an implementation of -** the xFunc callback only, NULL pointers should be passed as the xStep -** and xFinal parameters. An aggregate SQL function requires an implementation -** of xStep and xFinal and NULL should be passed for xFunc. To delete an -** existing SQL function or aggregate, pass NULL for all three function -** callback. -** -** It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing perferred text encodings. SQLite will use -** the implementation most closely matches the way in which the -** SQL function is used. -*/ -int sqlite3_create_function( - sqlite3 *, - const char *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -int sqlite3_create_function16( - sqlite3*, - const void *zFunctionName, - int nArg, - int eTextRep, - void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); - -/* -** CAPI3REF: Text Encodings {F10267} -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Obsolete Functions -** -** These functions are all now obsolete. In order to maintain -** backwards compatibility with older code, we continue to support -** these functions. However, new development projects should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you want they do. -*/ -int sqlite3_aggregate_count(sqlite3_context*); -int sqlite3_expired(sqlite3_stmt*); -int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -int sqlite3_global_recover(void); -void sqlite3_thread_cleanup(void); -int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work just like the corresponding -** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. -** -** The sqlite3_value_text16() interface extracts a UTF16 string -** in the native byte-order of the host machine. The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF16 strings as big-endian and little-endian respectively. -** -** The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words if the value is a string that looks like a number) -** then the conversion is done. Otherwise no conversion occurs. The -** [SQLITE_INTEGER | datatype] after conversion is returned. -** -** Please pay particular attention to the fact that the pointer that -** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. -** -*/ -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context {F16210} -** -** The implementation of aggregate SQL functions use this routine to allocate -** a structure for storing their state. -** {F16211} The first time the sqlite3_aggregate_context() routine is -** is called for a particular aggregate, SQLite allocates nBytes of memory -** zeros that memory, and returns a pointer to it. -** {F16212} On second and subsequent calls to sqlite3_aggregate_context() -** for the same aggregate function index, the same buffer is returned. {END} -** The implementation -** of the aggregate can use the returned buffer to accumulate data. -** -** {F16213} SQLite automatically frees the allocated buffer when the aggregate -** query concludes. {END} -** -** The first parameter should be a copy of the -** [sqlite3_context | SQL function context] that is the first -** parameter to the callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions {F16240} -** -** {F16241} The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. {END} -** -** {U16243} This routine must be called from the same thread in which -** the application-defined function is running. -*/ -void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data {F16270} -** -** The following two functions may be used by scalar SQL functions to -** associate meta-data with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated meta-data may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** meta-data associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** {F16271} -** The sqlite3_get_auxdata() interface returns a pointer to the meta-data -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. -** {F16272} If no meta-data has been ever been set for the Nth -** argument of the function, or if the cooresponding function parameter -** has changed since the meta-data was set, then sqlite3_get_auxdata() -** returns a NULL pointer. -** -** {F16275} The sqlite3_set_auxdata() interface saves the meta-data -** pointed to by its 3rd parameter as the meta-data for the N-th -** argument of the application-defined function. {END} Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** {F16277} If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the meta-data when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. {END} -** -** In practice, meta-data is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and SQL variables. -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -void *sqlite3_get_auxdata(sqlite3_context*, int N); -void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} -** -** These are special value for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function {F16400} -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the -** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used -** to bind values to host parameters in prepared statements. -** Refer to the -** [sqlite3_bind_blob | sqlite3_bind_* documentation] for -** additional information. -** -** {F16402} The sqlite3_result_blob() interface sets the result from -** an application defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of -** the application defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** {F16407} The sqlite3_result_double() interface sets the result from -** an application defined function to be a floating point value specified -** by its 2nd argument. -** -** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** {F16411} SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. {F16412} SQLite interprets the error -** message string from sqlite3_result_error() as UTF8. {F16413} SQLite -** interprets the string from sqlite3_result_error16() as UTF16 in native -** byte order. {F16414} If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** {F16415} If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** {F16417} The sqlite3_result_error() and sqlite3_result_error16() -** routines make a copy private copy of the error message text before -** they return. {END} Hence, the calling function can deallocate or -** modify the text after they return without harm. -** -** {F16421} The sqlite3_result_toobig() interface causes SQLite -** to throw an error indicating that a string or BLOB is to long -** to represent. {F16422} The sqlite3_result_nomem() interface -** causes SQLite to throw an exception indicating that the a -** memory allocation failed. -** -** {F16431} The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** {F16432} The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** {F16437} The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** {F16442} SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. -** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or blob result when it has -** finished using that result. -** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_STATIC, then -** SQLite assumes that the text or blob result is constant space and -** does not copy the space or call a destructor when it has -** finished using that result. -** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** {F16461} The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. {F16463} The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** -** {U16491} These routines are called from within the different thread -** than the one containing the application-defined function that recieved -** the [sqlite3_context] pointer, the results are undefined. -*/ -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences {F16600} -** -** {F16601} -** These functions are used to add new collation sequences to the -** [sqlite3*] handle specified as the first argument. -** -** {F16602} -** The name of the new collation sequence is specified as a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases -** the name is passed as the second function argument. -** -** {F16604} -** The third argument may be one of the constants [SQLITE_UTF8], -** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied -** routine expects to be passed pointers to strings encoded using UTF-8, -** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The -** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that -** the routine expects pointers to 16-bit word aligned strings -** of UTF16 in the native byte order of the host computer. -** -** {F16607} -** A pointer to the user supplied routine must be passed as the fifth -** argument. {F16609} If it is NULL, this is the same as deleting the collation -** sequence (so that SQLite cannot call it anymore). -** {F16611} Each time the application -** supplied function is invoked, it is passed a copy of the void* passed as -** the fourth argument to sqlite3_create_collation() or -** sqlite3_create_collation16() as its first parameter. -** -** {F16612} -** The remaining arguments to the application-supplied routine are two strings, -** each represented by a [length, data] pair and encoded in the encoding -** that was passed as the third argument when the collation sequence was -** registered. {END} The application defined collation routine should -** return negative, zero or positive if -** the first string is less than, equal to, or greater than the second -** string. i.e. (STRING1 - STRING2). -** -** {F16615} -** The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** excapt that it takes an extra argument which is a destructor for -** the collation. {F16617} The destructor is called when the collation is -** destroyed and is passed a copy of the fourth parameter void* pointer -** of the sqlite3_create_collation_v2(). -** {F16618} Collations are destroyed when -** they are overridden by later calls to the collation creation functions -** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. -*/ -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -int sqlite3_create_collation16( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks {F16700} -** -** {F16701} -** To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** database handle to be called whenever an undefined collation sequence is -** required. -** -** {F16702} -** If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names -** are passed as UTF-16 in machine native byte order. {F16704} A call to either -** function replaces any existing callback. -** -** {F16705} When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). {F16706} The second argument is the database -** handle. {F16707} The third argument is one of [SQLITE_UTF8], -** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most -** desirable form of the collation sequence function required. -** {F16708} The fourth parameter is the name of the -** required collation sequence. {END} -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** CAPI3REF: Suspend Execution For A Short Time {F10530} -** -** {F10531} The sqlite3_sleep() function -** causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** {F10532} If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. {F10533} The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** {F10534} SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. {END} -*/ -int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} -** -** If this global variable is made to point to a string which is -** the name of a folder (a.ka. directory), then all temporary files -** created by SQLite will be placed in that directory. If this variable -** is NULL pointer, then SQLite does a search for an appropriate temporary -** file directory. -** -** It is not safe to modify this variable once a database connection -** has been opened. It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been call and remain unchanged thereafter. -*/ -SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} -** -** {F12931} The sqlite3_get_autocommit() interfaces returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. {F12932} Autocommit mode is on -** by default. {F12933} Autocommit mode is disabled by a BEGIN statement. -** {F12934} Autocommit mode is reenabled by a COMMIT or ROLLBACK. {END} -** -** If certain kinds of errors occur on a statement within a multi-statement -** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. {F12935} The only way to -** find out if SQLite automatically rolled back the transaction after -** an error is to use this function. {END} -** -** {U12936} If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. {END} -*/ -int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} -** -** {F13121} The sqlite3_db_handle interface -** returns the [sqlite3*] database handle to which a -** [sqlite3_stmt | prepared statement] belongs. -** {F13122} the database handle returned by sqlite3_db_handle -** is the same database handle that was -** the first argument to the [sqlite3_prepare_v2()] or its variants -** that was used to create the statement in the first place. -*/ -sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} -** -** {F12951} The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12952} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12953} The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is committed. -** {F12954} Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** {F12956} The pArg argument is passed through -** to the callback. {F12957} If the callback on a commit hook function -** returns non-zero, then the commit is converted into a rollback. -** -** {F12958} If another function was previously registered, its -** pArg value is returned. Otherwise NULL is returned. -** -** {F12959} Registering a NULL function disables the callback. -** -** {F12961} For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** {F12962} The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** {F12964} The rollback callback is not invoked if a transaction is -** rolled back because a commit callback returned non-zero. -** Check on this {END} -** -** These are experimental interfaces and are subject to change. -*/ -void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks {F12970} -** -** {F12971} The sqlite3_update_hook() interface -** registers a callback function with the database connection identified by the -** first argument to be invoked whenever a row is updated, inserted or deleted. -** {F12972} Any callback set by a previous call to this function for the same -** database connection is overridden. -** -** {F12974} The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** {F12976} The first argument to the callback is -** a copy of the third argument to sqlite3_update_hook(). -** {F12977} The second callback -** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], -** depending on the operation that caused the callback to be invoked. -** {F12978} The third and -** fourth arguments to the callback contain pointers to the database and -** table name containing the affected row. -** {F12979} The final callback parameter is -** the rowid of the row. -** {F12981} In the case of an update, this is the rowid after -** the update takes place. -** -** {F12983} The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence). -** -** {F12984} If another function was previously registered, its pArg value -** is returned. {F12985} Otherwise NULL is returned. -*/ -void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} -** -** {F10331} -** This routine enables or disables the sharing of the database cache -** and schema data structures between connections to the same database. -** {F10332} -** Sharing is enabled if the argument is true and disabled if the argument -** is false. -** -** {F10333} Cache sharing is enabled and disabled -** for an entire process. {END} This is a change as of SQLite version 3.5.0. -** In prior versions of SQLite, sharing was -** enabled or disabled for each thread separately. -** -** {F10334} -** The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** {F10335} Existing database connections continue use the sharing mode -** that was in effect at the time they were opened. {END} -** -** Virtual tables cannot be used with a shared cache. {F10336} When shared -** cache is enabled, the [sqlite3_create_module()] API used to register -** virtual tables will always return an error. {END} -** -** {F10337} This routine returns [SQLITE_OK] if shared cache was -** enabled or disabled successfully. {F10338} An [SQLITE_ERROR | error code] -** is returned otherwise. {END} -** -** {F10339} Shared cache is disabled by default. {END} But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -*/ -int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory {F17340} -** -** {F17341} The sqlite3_release_memory() interface attempts to -** free N bytes of heap memory by deallocating non-essential memory -** allocations held by the database labrary. {END} Memory used -** to cache database pages to improve performance is an example of -** non-essential memory. {F16342} sqlite3_release_memory() returns -** the number of bytes actually freed, which might be more or less -** than the amount requested. -*/ -int sqlite3_release_memory(int); - -/* -** CAPI3REF: Impose A Limit On Heap Size {F17350} -** -** {F16351} The sqlite3_soft_heap_limit() interface -** places a "soft" limit on the amount of heap memory that may be allocated -** by SQLite. {F16352} If an internal allocation is requested -** that would exceed the soft heap limit, [sqlite3_release_memory()] is -** invoked one or more times to free up some space before the allocation -** is made. {END} -** -** {F16353} The limit is called "soft", because if -** [sqlite3_release_memory()] cannot -** free sufficient memory to prevent the limit from being exceeded, -** the memory is allocated anyway and the current operation proceeds. -** -** {F16354} -** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhausted. -** {F16355} The default value for the soft heap limit is zero. -** -** SQLite makes a best effort to honor the soft heap limit. -** {F16356} But if the soft heap limit cannot honored, execution will -** continue without error or notification. {END} This is why the limit is -** called a "soft" limit. It is advisory only. -** -** Prior to SQLite version 3.5.0, this routine only constrained the memory -** allocated by a single thread - the same thread in which this routine -** runs. Beginning with SQLite version 3.5.0, the soft heap limit is -** applied to all threads. {F16357} The value specified for the soft heap limit -** is an upper bound on the total memory allocation for all threads. {END} In -** version 3.5.0 there is no mechanism for limiting the heap usage for -** individual threads. -*/ -void sqlite3_soft_heap_limit(int); - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} -** -** This routine -** returns meta-data about a specific column of a specific database -** table accessible using the connection handle passed as the first function -** argument. -** -** The column is identified by the second, third and fourth parameters to -** this function. The second parameter is either the name of the database -** (i.e. "main", "temp" or an attached database) containing the specified -** table or NULL. If it is NULL, then all attached databases are searched -** for the table using the same algorithm as the database engine uses to -** resolve unqualified table references. -** -** The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** Meta information is returned by writing to the memory locations passed as -** the 5th and subsequent parameters to this function. Any of these -** arguments may be NULL, in which case the corresponding element of meta -** information is ommitted. -** -**
-** Parameter     Output Type      Description
-** -----------------------------------
-**
-**   5th         const char*      Data type
-**   6th         const char*      Name of the default collation sequence 
-**   7th         int              True if the column has a NOT NULL constraint
-**   8th         int              True if the column is part of the PRIMARY KEY
-**   9th         int              True if the column is AUTOINCREMENT
-** 
-** -** -** The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any sqlite API function. -** -** If the specified table is actually a view, then an error is returned. -** -** If the specified column is "rowid", "oid" or "_rowid_" and an -** INTEGER PRIMARY KEY column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. If there is no -** explicitly declared IPK column, then the output parameters are set as -** follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
-** -** This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an SQLITE error code is returned and an error message -** left in the database handle (to be retrieved using sqlite3_errmsg()). -** -** This API is only available if the library was compiled with the -** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. -*/ -int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension {F12600} -** -** {F12601} The sqlite3_load_extension() interface -** attempts to load an SQLite extension library contained in the file -** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 -** in which case the name of the entry point defaults -** to "sqlite3_extension_init". -** -** {F12604} The sqlite3_load_extension() interface shall -** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** -** {F12605} -** If an error occurs and pzErrMsg is not 0, then the -** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with -** error message text stored in memory obtained from [sqlite3_malloc()]. -** {END} The calling function should free this memory -** by calling [sqlite3_free()]. -** -** {F12606} -** Extension loading must be enabled using [sqlite3_enable_load_extension()] -** prior to calling this API or an error will be returned. -*/ -int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading {F12620} -** -** So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following -** API is provided to turn the [sqlite3_load_extension()] mechanism on and -** off. {F12622} It is off by default. {END} See ticket #1863. -** -** {F12621} Call the sqlite3_enable_load_extension() routine -** with onoff==1 to turn extension loading on -** and call it with onoff==0 to turn it back off again. {END} -*/ -int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} -** -** {F12641} This function -** registers an extension entry point that is automatically invoked -** whenever a new database connection is opened using -** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} -** -** This API can be invoked at program startup in order to register -** one or more statically linked extensions that will be available -** to all new database connections. -** -** {F12642} Duplicate extensions are detected so calling this routine multiple -** times with the same extension is harmless. -** -** {F12643} This routine stores a pointer to the extension in an array -** that is obtained from sqlite_malloc(). {END} If you run a memory leak -** checker on your program and it reports a leak because of this -** array, then invoke [sqlite3_reset_auto_extension()] prior -** to shutdown to free the memory. -** -** {F12644} Automatic extensions apply across all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -int sqlite3_auto_extension(void *xEntryPoint); - - -/* -** CAPI3REF: Reset Automatic Extension Loading {F12660} -** -** {F12661} This function disables all previously registered -** automatic extensions. {END} This -** routine undoes the effect of all prior [sqlite3_automatic_extension()] -** calls. -** -** {F12662} This call disabled automatic extensions in all threads. {END} -** -** This interface is experimental and is subject to change or -** removal in future releases of SQLite. -*/ -void sqlite3_reset_auto_extension(void); - - -/* -****** EXPERIMENTAL - subject to change without notice ************** -** -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stablizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** A module is a class of virtual tables. Each module is defined -** by an instance of the following structure. This structure consists -** mostly of methods for the module. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); -}; - -/* -** The sqlite3_index_info structure and its substructures is used to -** pass information into and receive the reply from the xBestIndex -** method of an sqlite3_module. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** The aConstraint[] array records WHERE clause constraints of the -** form: -** -** column OP expr -** -** Where OP is =, <, <=, >, or >=. -** The particular operator is stored -** in aConstraint[].op. The index of the column is stored in -** aConstraint[].iColumn. aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot. -** -** The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** The aConstraint[] array only reports WHERE clause terms in the correct -** form that refer to the particular virtual table being queried. -** -** Information about the ORDER BY clause is stored in aOrderBy[]. -** Each term of aOrderBy records a column of the ORDER BY clause. -** -** The xBestIndex method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite. -** -** The idxNum and idxPtr values are recorded and passed into xFilter. -** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. -** -** The orderByConsumed means that output from xFilter will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** This routine is used to register a new module name with an SQLite -** connection. Module names must be registered before creating new -** virtual tables on the module, or before using preexisting virtual -** tables of the module. -*/ -int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void * /* Client data for xCreate/xConnect */ -); - -/* -** This routine is identical to the sqlite3_create_module() method above, -** except that it allows a destructor function to be specified. It is -** even more experimental than the rest of the virtual tables API. -*/ -int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *, /* Methods for the module */ - void *, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** Every module implementation uses a subclass of the following structure -** to describe a particular instance of the module. Each subclass will -** be tailored to the specific needs of the module implementation. The -** purpose of this superclass is to define certain fields that are common -** to all module implementations. -** -** Virtual tables methods can set an error message by assigning a -** string obtained from sqlite3_mprintf() to zErrMsg. The method should -** take care that any prior string is freed by a call to sqlite3_free() -** prior to assigning a new string to zErrMsg. After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note -** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field -** since virtual tables are commonly implemented in loadable extensions which -** do not have access to sqlite3MPrintf() or sqlite3Free(). -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Used internally */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* Every module implementation uses a subclass of the following structure -** to describe cursors that point into the virtual table and are used -** to loop through the virtual table. Cursors are created using the -** xOpen method of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** The xCreate and xConnect methods of a module use the following API -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); - -/* -** Virtual tables can provide alternative implementations of functions -** using the xFindFunction method. But global versions of those functions -** must exist in order to be overloaded. -** -** This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created. The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a place-holder function that can be overloaded -** by virtual tables. -** -** This API should be considered part of the virtual table interface, -** which is experimental and subject to change. -*/ -int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -** -****** EXPERIMENTAL - subject to change without notice ************** -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB {F17800} -** -** An instance of the following opaque structure is used to -** represent an blob-handle. A blob-handle is created by -** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. -** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the blob. -** The [sqlite3_blob_bytes()] interface returns the size of the -** blob in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O {F17810} -** -** {F17811} This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; -** in other words, the same blob that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
-** 
{END} -** -** {F17812} If the flags parameter is non-zero, the blob is opened for -** read and write access. If it is zero, the blob is opened for read -** access. {END} -** -** {F17813} On success, [SQLITE_OK] is returned and the new -** [sqlite3_blob | blob handle] is written to *ppBlob. -** {F17814} Otherwise an error code is returned and -** any value written to *ppBlob should not be used by the caller. -** {F17815} This function sets the database-handle error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. -** We should go through and mark all interfaces that behave this -** way with a similar statement -*/ -int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Close A BLOB Handle {F17830} -** -** Close an open [sqlite3_blob | blob handle]. -** -** {F17831} Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in autocommit mode. -** {F17832} If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. {END} -** Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. {F17833} Any errors that occur during -** closing are reported as a non-zero return value. -** -** {F17839} The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed. -*/ -int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB {F17805} -** -** {F16806} Return the size in bytes of the blob accessible via the open -** [sqlite3_blob | blob-handle] passed as an argument. -*/ -int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally {F17850} -** -** This function is used to read data from an open -** [sqlite3_blob | blob-handle] into a caller supplied buffer. -** {F17851} n bytes of data are copied into buffer -** z from the open blob, starting at offset iOffset. -** -** {F17852} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is -** less than zero [SQLITE_ERROR] is returned and no data is read. -** -** {F17854} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} -** -** This function is used to write data into an open -** [sqlite3_blob | blob-handle] from a user supplied buffer. -** {F17871} n bytes of data are copied from the buffer -** pointed to by z into the open blob, starting at offset iOffset. -** -** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument -** was not opened for writing (the flags parameter to [sqlite3_blob_open()] -*** was zero), this function returns [SQLITE_READONLY]. -** -** {F17873} This function may only modify the contents of the blob; it is -** not possible to increase the size of a blob using this API. -** {F17874} If offset iOffset is less than n bytes from the end of the blob, -** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** -** {F17876} On success, SQLITE_OK is returned. Otherwise, an -** [SQLITE_ERROR | SQLite error code] or an -** [SQLITE_IOERR_READ | extended error code] is returned. -*/ -int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects {F11200} -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** {F11201} The sqlite3_vfs_find() interface returns a pointer to -** a VFS given its name. {F11202} Names are case sensitive. -** {F11203} Names are zero-terminated UTF-8 strings. -** {F11204} If there is no match, a NULL -** pointer is returned. {F11205} If zVfsName is NULL then the default -** VFS is returned. {END} -** -** {F11210} New VFSes are registered with sqlite3_vfs_register(). -** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. -** {F11212} The same VFS can be registered multiple times without injury. -** {F11213} To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. {U11214} If two different VFSes with the -** same name are registered, the behavior is undefined. {U11215} If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. -** {F11221} If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary. -*/ -sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes {F17000} -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_OS2 -**
  • SQLITE_MUTEX_PTHREAD -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
-** -** The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_OS2, -** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations -** are appropriate for use on os/2, unix, and windows. -** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. The -** mutex interface routines defined here become external -** references in the SQLite library for which implementations -** must be provided by the application. This facility allows an -** application that links against SQLite to provide its own mutex -** implementation without having to modify the SQLite core. -** -** {F17011} The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. {F17012} If it returns NULL -** that means that a mutex could not be allocated. {F17013} SQLite -** will unwind its stack and return an error. {F17014} The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
{END} -** -** {F17015} The first two constants cause sqlite3_mutex_alloc() to create -** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. {F17016} But SQLite will only request a recursive mutex in -** cases where it really needs one. {END} If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return -** a pointer to a static preexisting mutex. {END} Four static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. {F17034} But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. {END} -** -** {F17019} The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every -** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in -** use when they are deallocated. {U17022} Attempting to deallocate a static -** mutex results in undefined behavior. {F17023} SQLite never deallocates -** a static mutex. {END} -** -** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. {F17024} If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK -** upon successful entry. {F17026} Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** {F17027} In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter. {U17028} If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** {F17029} SQLite will never exhibit -** such behavior in its own use of mutexes. {END} -** -** Some systems (ex: windows95) do not the operation implemented by -** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will -** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} -** -** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. {U17032} The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. {F17033} SQLite will -** never do either. {END} -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -sqlite3_mutex *sqlite3_mutex_alloc(int); -void sqlite3_mutex_free(sqlite3_mutex*); -void sqlite3_mutex_enter(sqlite3_mutex*); -int sqlite3_mutex_try(sqlite3_mutex*); -void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Verifcation Routines {F17080} -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. {F17081} The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. {F17082} The core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. {U17087} External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** {F17083} These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. {END} -** -** {X17084} The implementation is not required to provided versions of these -** routines that actually work. -** If the implementation does not provide working -** versions of these routines, it should at least provide stubs -** that always return true so that one does not get spurious -** assertion failures. {END} -** -** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. {END} This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But the -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -int sqlite3_mutex_held(sqlite3_mutex*); -int sqlite3_mutex_notheld(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Types {F17001} -** -** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. {END} -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ - -/* -** CAPI3REF: Low-Level Control Of Database Files {F11300} -** -** {F11301} The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. {F11302} The -** name of the database is the name assigned to the database by the -** ATTACH SQL command that opened the -** database. {F11303} To control the main database file, use the name "main" -** or a NULL pointer. {F11304} The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. {F11305} The return value of the xFileControl -** method becomes the return value of this routine. -** -** {F11306} If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. {F11307} This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might -** also return SQLITE_ERROR. {U11309} There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. {END} -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#if 0 -} /* End of the 'extern "C"' block */ -#endif -#endif - -/************** End of sqlite3.h *********************************************/ -/************** Continuing where we left off in fts3_tokenizer.h *************/ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialised by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3_icu.c *******************/ - -#include -#include -#include -#include - -typedef struct IcuTokenizer IcuTokenizer; -typedef struct IcuCursor IcuCursor; - -struct IcuTokenizer { - sqlite3_tokenizer base; - char *zLocale; -}; - -struct IcuCursor { - sqlite3_tokenizer_cursor base; - - UBreakIterator *pIter; /* ICU break-iterator object */ - int nChar; /* Number of UChar elements in pInput */ - UChar *aChar; /* Copy of input using utf-16 encoding */ - int *aOffset; /* Offsets of each character in utf-8 input */ - - int nBuffer; - char *zBuffer; - - int iToken; -}; - -/* -** Create a new tokenizer instance. -*/ -static int icuCreate( - int argc, /* Number of entries in argv[] */ - const char * const *argv, /* Tokenizer creation arguments */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ -){ - IcuTokenizer *p; - int n = 0; - - if( argc>0 ){ - n = strlen(argv[0])+1; - } - p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n); - if( !p ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(IcuTokenizer)); - - if( n ){ - p->zLocale = (char *)&p[1]; - memcpy(p->zLocale, argv[0], n); - } - - *ppTokenizer = (sqlite3_tokenizer *)p; - - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int icuDestroy(sqlite3_tokenizer *pTokenizer){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int icuOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, /* Input string */ - int nInput, /* Length of zInput in bytes */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - IcuCursor *pCsr; - - const int32_t opt = U_FOLD_CASE_DEFAULT; - UErrorCode status = U_ZERO_ERROR; - int nChar; - - UChar32 c; - int iInput = 0; - int iOut = 0; - - *ppCursor = 0; - - if( -1 == nInput ) nInput = strlen(nInput); - nChar = nInput+1; - pCsr = (IcuCursor *)sqlite3_malloc( - sizeof(IcuCursor) + /* IcuCursor */ - nChar * sizeof(UChar) + /* IcuCursor.aChar[] */ - (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ - ); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(IcuCursor)); - pCsr->aChar = (UChar *)&pCsr[1]; - pCsr->aOffset = (int *)&pCsr->aChar[nChar]; - - pCsr->aOffset[iOut] = iInput; - U8_NEXT(zInput, iInput, nInput, c); - while( c>0 ){ - int isError = 0; - c = u_foldCase(c, opt); - U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); - if( isError ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->aOffset[iOut] = iInput; - - if( iInputpIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status); - if( !U_SUCCESS(status) ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->nChar = iOut; - - ubrk_first(pCsr->pIter); - *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to icuOpen(). -*/ -static int icuClose(sqlite3_tokenizer_cursor *pCursor){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - ubrk_close(pCsr->pIter); - sqlite3_free(pCsr->zBuffer); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. -*/ -static int icuNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - - int iStart = 0; - int iEnd = 0; - int nByte = 0; - - while( iStart==iEnd ){ - UChar32 c; - - iStart = ubrk_current(pCsr->pIter); - iEnd = ubrk_next(pCsr->pIter); - if( iEnd==UBRK_DONE ){ - return SQLITE_DONE; - } - - while( iStartaChar, iWhite, pCsr->nChar, c); - if( u_isspace(c) ){ - iStart = iWhite; - }else{ - break; - } - } - assert(iStart<=iEnd); - } - - do { - UErrorCode status = U_ZERO_ERROR; - if( nByte ){ - char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte); - if( !zNew ){ - return SQLITE_NOMEM; - } - pCsr->zBuffer = zNew; - pCsr->nBuffer = nByte; - } - - u_strToUTF8( - pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */ - &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */ - &status /* Output success/failure */ - ); - } while( nByte>pCsr->nBuffer ); - - *ppToken = pCsr->zBuffer; - *pnBytes = nByte; - *piStartOffset = pCsr->aOffset[iStart]; - *piEndOffset = pCsr->aOffset[iEnd]; - *piPosition = pCsr->iToken++; - - return SQLITE_OK; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module icuTokenizerModule = { - 0, /* iVersion */ - icuCreate, /* xCreate */ - icuDestroy, /* xCreate */ - icuOpen, /* xOpen */ - icuClose, /* xClose */ - icuNext, /* xNext */ -}; - -/* -** Set *ppModule to point at the implementation of the ICU tokenizer. -*/ -void sqlite3Fts3IcuTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &icuTokenizerModule; -} - -#endif /* defined(SQLITE_ENABLE_ICU) */ -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_icu.c ********************************************/ diff --git a/db/sqlite3/src/sqlite3.h b/db/sqlite3/src/sqlite3.h index f6c092180cde..5842b3c61700 100644 --- a/db/sqlite3/src/sqlite3.h +++ b/db/sqlite3/src/sqlite3.h @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite3.h,v 1.16 2008/01/11 09:12:25 dwitte%stanford.edu Exp $ +** @(#) $Id: sqlite3.h,v 1.17 2008/01/22 13:54:07 mozilla%weilbacher.org Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -88,7 +88,7 @@ extern "C" { ** ** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. */ -#define SQLITE_VERSION "3.5.4" +#define SQLITE_VERSION "3.5.4.1" #define SQLITE_VERSION_NUMBER 3005004 /* diff --git a/docshell/base/nsAboutRedirector.cpp b/docshell/base/nsAboutRedirector.cpp index edf23e7839b6..74e0fd41cd9e 100644 --- a/docshell/base/nsAboutRedirector.cpp +++ b/docshell/base/nsAboutRedirector.cpp @@ -70,6 +70,9 @@ static RedirEntry kRedirMap[] = { nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT }, { "plugins", "chrome://global/content/plugins.html", 0 }, { "config", "chrome://global/content/config.xul", 0 }, +#ifdef MOZ_CRASHREPORTER + { "crashes", "chrome://global/content/crashes.xhtml", 0 }, +#endif #ifdef MOZ_XUL_APP { "logo", "chrome://branding/content/about.png", #else diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index b1238def2321..d3d33f382f9a 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -678,7 +678,9 @@ nsDocShell::LoadURI(nsIURI * aURI, PRUint32 aLoadFlags, PRBool aFirstParty) { - if (!IsNavigationAllowed()) { + // Note: we allow loads to get through here even if mFiredUnloadEvent is + // true; that case will get handled in LoadInternal or LoadHistoryEntry. + if (IsPrintingOrPP()) { return NS_OK; // JS may not handle returning of an error code } nsresult rv; @@ -1903,37 +1905,35 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem, // XXXbz should we care if aAccessingItem or the document therein is // chrome? Should those get extra privileges? - // Now do a security check - // Bug 13871: Prevent frameset spoofing - // See BugSplat 336170, 338737 and XP_FindNamedContextInList in - // the classic codebase - // Nav's behaviour was: - // - pref controlled: "browser.frame.validate_origin" - // (gValidateOrigin) - // - allow load if host of target or target's parent is same - // as host of origin - // - allow load if target is a top level window - - // We are going to be a little more restrictive, with the - // following algorithm: - // - pref controlled in the same way - // - allow access if the two treeitems are in the same tree - // - allow access if the aTargetItem or one of its ancestors - // has the same origin as aAccessingItem - // - allow access if the target is a toplevel window and we can - // access its opener. Note that we only allow one level of - // recursion there. + // For historical context, see: + // + // Bug 13871: Prevent frameset spoofing + // Bug 103638: Targets with same name in different windows open in wrong + // window with javascript - nsCOMPtr targetRoot; - aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot)); + // Now do a security check + // + // Allow navigation if + // 1) aAccessingItem can script aTargetItem or one of its ancestors in + // the frame hierarchy or + // 2) aTargetItem is a top-level frame and aAccessingItem is its descendant + // 3) aTargetItem is a top-level frame and aAccessingItem can target + // its opener per rule (1) or (2). + + if (aTargetItem == aAccessingItem) { + // A frame is allowed to navigate itself. + return PR_TRUE; + } nsCOMPtr accessingRoot; aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot)); - if (targetRoot == accessingRoot) { + if (aTargetItem == accessingRoot) { + // A frame can navigate its root. return PR_TRUE; } + // Check if aAccessingItem can navigate one of aTargetItem's ancestors. nsCOMPtr target = aTargetItem; do { if (ValidateOrigin(aAccessingItem, target)) { @@ -1945,6 +1945,9 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem, parent.swap(target); } while (target); + nsCOMPtr targetRoot; + aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot)); + if (aTargetItem != targetRoot) { // target is a subframe, not in accessor's frame hierarchy, and all its // ancestors have origins different from that of the accessor. Don't @@ -3603,6 +3606,10 @@ nsDocShell::Destroy() } } + // Make sure to blow away our mLoadingURI just in case. No loads + // from inside this pagehide. + mLoadingURI = nsnull; + // Fire unload event before we blow anything away. (void) FirePageHideNotification(PR_TRUE); @@ -3782,15 +3789,6 @@ nsDocShell::SetParentWidget(nsIWidget * aParentWidget) { mParentWidget = aParentWidget; - if (!mParentWidget) { - // If the parent widget is set to null we don't want to hold - // on to the current device context any more since it is - // associated with the parent widget we no longer own. We'll - // need to create a new device context if one is needed again. - - mDeviceContext = nsnull; - } - return NS_OK; } @@ -5112,24 +5110,6 @@ nsDocShell::EnsureContentViewer() return rv; } -NS_IMETHODIMP -nsDocShell::EnsureDeviceContext() -{ - if (mDeviceContext) - return NS_OK; - - mDeviceContext = do_CreateInstance(kDeviceContextCID); - NS_ENSURE_TRUE(mDeviceContext, NS_ERROR_FAILURE); - - nsCOMPtr widget; - GetMainWidget(getter_AddRefs(widget)); - NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE); - - mDeviceContext->Init(widget->GetNativeData(NS_NATIVE_WIDGET)); - - return NS_OK; -} - nsresult nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal) { @@ -5165,6 +5145,10 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal) mSavingOldViewer = CanSavePresentation(LOAD_NORMAL, nsnull, nsnull); + // Make sure to blow away our mLoadingURI just in case. No loads + // from inside this pagehide. + mLoadingURI = nsnull; + // Notify the current document that it is about to be unloaded!! // // It is important to fire the unload() notification *before* any state @@ -5581,6 +5565,10 @@ nsDocShell::RestoreFromHistory() // pagehide or unload. nsCOMPtr origLSHE = mLSHE; + // Make sure to blow away our mLoadingURI just in case. No loads + // from inside this pagehide. + mLoadingURI = nsnull; + // Notify the old content viewer that it's being hidden. FirePageHideNotification(!mSavingOldViewer); @@ -5943,7 +5931,14 @@ nsDocShell::CreateContentViewer(const char *aContentType, mSavingOldViewer = CanSavePresentation(mLoadType, request, doc); } + NS_ASSERTION(!mLoadingURI, "Re-entering unload?"); + + nsCOMPtr aOpenedChannel = do_QueryInterface(request); + if (aOpenedChannel) { + aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI)); + } FirePageHideNotification(!mSavingOldViewer); + mLoadingURI = nsnull; // Set mFiredUnloadEvent = PR_FALSE so that the unload handler for the // *new* document will fire. @@ -5954,8 +5949,6 @@ nsDocShell::CreateContentViewer(const char *aContentType, // notifications before we've called Embed(). See bug 284993. mURIResultedInDocument = PR_TRUE; - nsCOMPtr aOpenedChannel = do_QueryInterface(request); - PRBool onLocationChangeNeeded = OnLoadingSite(aOpenedChannel, PR_FALSE); // let's try resetting the load group if we need to... @@ -6272,13 +6265,16 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer) nsCOMPtr widget; NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE); + nsCOMPtr deviceContext; if (widget) { - NS_ENSURE_SUCCESS(EnsureDeviceContext(), NS_ERROR_FAILURE); + deviceContext = do_CreateInstance(kDeviceContextCID); + NS_ENSURE_TRUE(deviceContext, NS_ERROR_FAILURE); + deviceContext->Init(widget->GetNativeData(NS_NATIVE_WIDGET)); } nsRect bounds(x, y, cx, cy); - if (NS_FAILED(mContentViewer->Init(widget, mDeviceContext, bounds))) { + if (NS_FAILED(mContentViewer->Init(widget, deviceContext, bounds))) { mContentViewer = nsnull; NS_ERROR("ContentViewer Initialization failed"); return NS_ERROR_FAILURE; @@ -6424,56 +6420,66 @@ nsDocShell::CheckLoadingPermissions() item.swap(tmp); } while (item); - // The caller is not from the same origin as this item, or any if - // this items ancestors. Only permit loading content if both are - // part of the same window, assuming we can find the window of the - // caller. - - nsCOMPtr stack = - do_GetService("@mozilla.org/js/xpc/ContextStack;1"); - if (!stack) { - // No context stack available. Should never happen, but in - // case it does, return the sameOrigin error from the security - // check above. - - return sameOrigin; - } - - JSContext *cx = nsnull; - stack->Peek(&cx); - - if (!cx) { - // No caller docshell reachable, return the sameOrigin error - // from the security check above. - - return sameOrigin; - } - - nsIScriptContext *currentCX = GetScriptContextFromJSContext(cx); - nsCOMPtr callerTreeItem; - nsCOMPtr win; - if (currentCX && - (win = do_QueryInterface(currentCX->GetGlobalObject())) && - (callerTreeItem = do_QueryInterface(win->GetDocShell()))) { - nsCOMPtr callerRoot; - callerTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(callerRoot)); - - nsCOMPtr ourRoot; - GetSameTypeRootTreeItem(getter_AddRefs(ourRoot)); - - if (ourRoot == callerRoot) { - // The running JS is in the same window as the target - // frame, permit load. - sameOrigin = NS_OK; - } - } - return sameOrigin; } //***************************************************************************** // nsDocShell: Site Loading //***************************************************************************** +class InternalLoadEvent : public nsRunnable +{ +public: + InternalLoadEvent(nsDocShell* aDocShell, nsIURI * aURI, nsIURI * aReferrer, + nsISupports * aOwner, PRUint32 aFlags, + const PRUnichar *aWindowTarget, const char* aTypeHint, + nsIInputStream * aPostData, + nsIInputStream * aHeadersData, PRUint32 aLoadType, + nsISHEntry * aSHEntry, PRBool aFirstParty) : + mDocShell(aDocShell), + mURI(aURI), + mReferrer(aReferrer), + mOwner(aOwner), + mFlags(aFlags), + mPostData(aPostData), + mHeadersData(aHeadersData), + mLoadType(aLoadType), + mSHEntry(aSHEntry), + mFirstParty(aFirstParty) + { + // Make sure to keep null things null as needed + if (aWindowTarget) { + mWindowTarget = aWindowTarget; + } + if (aTypeHint) { + mTypeHint = aTypeHint; + } + } + + NS_IMETHOD Run() { + return mDocShell->InternalLoad(mURI, mReferrer, mOwner, mFlags, + mWindowTarget.get(), mTypeHint.get(), + mPostData, mHeadersData, mLoadType, + mSHEntry, mFirstParty, nsnull, nsnull); + } + +private: + nsRefPtr mDocShell; + nsCOMPtr mURI; + nsCOMPtr mReferrer; + nsCOMPtr mOwner; + PRUint32 mFlags; + + // Use IDL strings so .get() returns null by default + nsXPIDLString mWindowTarget; + nsXPIDLCString mTypeHint; + + nsCOMPtr mPostData; + nsCOMPtr mHeadersData; + PRUint32 mLoadType; + nsCOMPtr mSHEntry; + PRBool mFirstParty; +}; + NS_IMETHODIMP nsDocShell::InternalLoad(nsIURI * aURI, nsIURI * aReferrer, @@ -6489,10 +6495,6 @@ nsDocShell::InternalLoad(nsIURI * aURI, nsIDocShell** aDocShell, nsIRequest** aRequest) { - if (mFiredUnloadEvent) { - return NS_OK; // JS may not handle returning of an error code - } - nsresult rv = NS_OK; #ifdef PR_LOGGING @@ -6520,6 +6522,21 @@ nsDocShell::InternalLoad(nsIURI * aURI, NS_ENSURE_TRUE(!mIsBeingDestroyed, NS_ERROR_NOT_AVAILABLE); + if (mFiredUnloadEvent) { + if (IsOKToLoadURI(aURI)) { + // Do this asynchronously + nsCOMPtr ev = + new InternalLoadEvent(this, aURI, aReferrer, aOwner, aFlags, + aWindowTarget, aTypeHint, + aPostData, aHeadersData, aLoadType, + aSHEntry, aFirstParty); + return NS_DispatchToCurrentThread(ev); + } + + // Just ignore this load attempt + return NS_OK; + } + // wyciwyg urls can only be loaded through history. Any normal load of // wyciwyg through docshell is illegal. Disallow such loads. if (aLoadType & LOAD_CMD_NORMAL) { @@ -8088,6 +8105,10 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, NS_IMETHODIMP nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType) { + if (!IsNavigationAllowed()) { + return NS_OK; + } + nsCOMPtr uri; nsCOMPtr postData; nsCOMPtr referrerURI; @@ -9235,6 +9256,26 @@ nsDocShell::IsAboutBlank(nsIURI* aURI) return str.EqualsLiteral("about:blank"); } +PRBool +nsDocShell::IsOKToLoadURI(nsIURI* aURI) +{ + NS_PRECONDITION(aURI, "Must have a URI!"); + + if (!mFiredUnloadEvent) { + return PR_TRUE; + } + + if (!mLoadingURI) { + return PR_FALSE; + } + + nsCOMPtr secMan = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); + return + secMan && + NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, PR_FALSE)); +} + //***************************************************************************** // nsClassifierCallback //***************************************************************************** diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 3f9bee4765d8..6b1a58941dab 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -240,7 +240,6 @@ protected: // Content Viewer Management NS_IMETHOD EnsureContentViewer(); - NS_IMETHOD EnsureDeviceContext(); // aPrincipal can be passed in if the caller wants. If null is // passed in, the about:blank principal will end up being used. nsresult CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal); @@ -513,6 +512,11 @@ protected: // Check whether aURI is about:blank static PRBool IsAboutBlank(nsIURI* aURI); + + // Call this when a URI load is handed to us (via OnLinkClick or + // InternalLoad). This makes sure that we're not inside unload, or that if + // we are it's still OK to load this URI. + PRBool IsOKToLoadURI(nsIURI* aURI); protected: // Override the parent setter from nsDocLoader @@ -600,7 +604,6 @@ protected: nsRect mBounds; // Dimensions of the docshell nsCOMPtr mContentViewer; nsCOMPtr mDocumentCharsetInfo; - nsCOMPtr mDeviceContext; nsCOMPtr mParentWidget; nsCOMPtr mPrefs; @@ -644,6 +647,13 @@ protected: // Suspends/resumes channels based on the URI classifier. nsRefPtr mClassifier; + // The URI we're currently loading. This is only relevant during the + // firing of a pagehide/unload. The caller of FirePageHideNotification() + // is responsible for setting it and unsetting it. It may be null if the + // pagehide/unload is happening for some reason other than just loading a + // new URI. + nsCOMPtr mLoadingURI; + // WEAK REFERENCES BELOW HERE. // Note these are intentionally not addrefd. Doing so will create a cycle. // For that reasons don't use nsCOMPtr. diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp index 937391e4b868..d8444426b51a 100644 --- a/docshell/base/nsWebShell.cpp +++ b/docshell/base/nsWebShell.cpp @@ -565,7 +565,6 @@ nsWebShell::~nsWebShell() // recursively if the refcount is allowed to remain 0 mContentViewer=nsnull; - mDeviceContext=nsnull; InitFrameData(); @@ -767,7 +766,7 @@ nsWebShell::OnLinkClick(nsIContent* aContent, { NS_ASSERTION(NS_IsMainThread(), "wrong thread"); - if (mFiredUnloadEvent) { + if (!IsOKToLoadURI(aURI)) { return NS_OK; } @@ -798,7 +797,7 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent, *aRequest = nsnull; } - if (mFiredUnloadEvent) { + if (!IsOKToLoadURI(aURI)) { return NS_OK; } diff --git a/docshell/build/nsDocShellModule.cpp b/docshell/build/nsDocShellModule.cpp index 6138db08eda8..dbb5f0484b26 100644 --- a/docshell/build/nsDocShellModule.cpp +++ b/docshell/build/nsDocShellModule.cpp @@ -156,6 +156,13 @@ static const nsModuleComponentInfo gDocShellModuleInfo[] = { NS_ABOUT_MODULE_CONTRACTID_PREFIX "config", nsAboutRedirector::Create }, +#ifdef MOZ_CRASHREPORTER + { "about:crashes", + NS_ABOUT_REDIRECTOR_MODULE_CID, + NS_ABOUT_MODULE_CONTRACTID_PREFIX "crashes", + nsAboutRedirector::Create + }, +#endif { "about:credits", NS_ABOUT_REDIRECTOR_MODULE_CID, NS_ABOUT_MODULE_CONTRACTID_PREFIX "credits", diff --git a/docshell/test/Makefile.in b/docshell/test/Makefile.in index 745bc73a90ff..c4fbb9b6f8bc 100644 --- a/docshell/test/Makefile.in +++ b/docshell/test/Makefile.in @@ -45,6 +45,7 @@ MODULE = test_docshell DIRS += chrome \ browser \ + navigation \ $(NULL) XPCSHELL_TESTS = unit diff --git a/docshell/test/navigation/Makefile.in b/docshell/test/navigation/Makefile.in new file mode 100644 index 000000000000..69817c8055ab --- /dev/null +++ b/docshell/test/navigation/Makefile.in @@ -0,0 +1,69 @@ +# +# ***** 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.org code. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2007 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = docshell/test/navigation + +MODULE = test_docshell + +include $(DEPTH)/config/autoconf.mk +include $(topsrcdir)/config/rules.mk + +_TEST_FILES = \ + test_bug13871.html \ + test_bug270414.html \ + test_bug278916.html \ + test_bug279495.html \ + test_child.html \ + test_grandchild.html \ + test_sibling-off-domain.html \ + test_sibling-matching-parent.html \ + test_opener.html \ + test_not-opener.html \ + test_popup-navigates-children.html \ + test_reserved.html \ + NavigationUtils.js \ + navigate.html \ + open.html \ + iframe.html \ + parent.html \ + blank.html \ + $(NULL) + +libs:: $(_TEST_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) diff --git a/docshell/test/navigation/NavigationUtils.js b/docshell/test/navigation/NavigationUtils.js new file mode 100644 index 000000000000..bb23547d6f4b --- /dev/null +++ b/docshell/test/navigation/NavigationUtils.js @@ -0,0 +1,231 @@ +/* ***** 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 NavigationUtils.js + * + * The Initial Developer of the Original Code is + * Stanford University + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Adam Barth + * Collin Jackson + * + * 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 ***** */ + +/////////////////////////////////////////////////////////////////////////// +// +// Utilities for navigation tests +// +/////////////////////////////////////////////////////////////////////////// + +var body = "This frame was navigated."; +var target_url = "data:text/html," + body + ""; + +/////////////////////////////////////////////////////////////////////////// +// Functions that navigate frames +/////////////////////////////////////////////////////////////////////////// + +function navigateByLocation(wnd) { + try { + wnd.location = target_url; + } catch(ex) { + // We need to keep our finished frames count consistent. + // Oddly, this ends up simulating the behavior of IE7. + window.open(target_url, "_blank", "width=10,height=10"); + } +} + +function navigateByOpen(name) { + window.open(target_url, name, "width=10,height=10"); +} + +function navigateByForm(name) { + var form = document.createElement("form"); + form.action = target_url; + form.method = "POST"; + form.target = name; document.body.appendChild(form); + form.submit(); +} + +var hyperlink_count = 0; + +function navigateByHyperlink(name) { + var link = document.createElement("a"); + link.href = target_url; + link.target = name; + link.id = "navigation_hyperlink_" + hyperlink_count++; + document.body.appendChild(link); + sendMouseEvent({type:"click"}, link.id); +} + +/////////////////////////////////////////////////////////////////////////// +// Functions that call into Mochitest framework +/////////////////////////////////////////////////////////////////////////// + +function isNavigated(wnd, message) { + var result = null; + try { + result = wnd.document.body.innerHTML; + } catch(ex) { + result = ex; + } + is(result, body, message); +} + +function isBlank(wnd, message) { + var result = null; + try { + result = wnd.document.body.innerHTML; + } catch(ex) { + result = ex; + } + is(result, "This is a blank document.", message); +} + +function isAccessible(wnd, message) { + try { + wnd.document.body.innerHTML; + ok(true, message); + } catch(ex) { + ok(false, message); + } +} + +function isInaccessible(wnd, message) { + try { + wnd.document.body.innerHTML; + ok(false, message); + } catch(ex) { + ok(true, message); + } +} + +/////////////////////////////////////////////////////////////////////////// +// Functions that require UniversalXPConnect privilege +/////////////////////////////////////////////////////////////////////////// + +// Note: This only searches for top-level frames with this name. +function xpcGetFramesByName(name) { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Components.interfaces.nsIWindowWatcher); + var enumerator = ww.getWindowEnumerator(); + + var results = []; + + while (enumerator.hasMoreElements()) { + var win = enumerator.getNext(); + var tabs = win.gBrowser.browsers; + + for (var i = 0; i < tabs.length; i++) { + var domwindow = tabs[i].docShell.document.defaultView; + + if (domwindow.name == name) + results.push(domwindow); + } + } + + return results; +} + +function xpcCleanupWindows() { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Components.interfaces.nsIWindowWatcher); + var enumerator = ww.getWindowEnumerator(); + + while (enumerator.hasMoreElements()) { + var win = enumerator.getNext(); + var tabs = win.gBrowser.browsers; + + for (var i = 0; i < tabs.length; i++) { + var domwindow = tabs[i].docShell.document.defaultView; + + if (domwindow.location.protocol == "data:") + domwindow.close(); + } + } +} + +function xpcWaitForFinishedFrames(callback, numFrames) { + var finishedFrameCount = 0; + function frameFinished() { + finishedFrameCount++; + + if (finishedFrameCount == numFrames) { + clearInterval(frameWaitInterval); + setTimeout(callback, 1); + return; + } + + if (finishedFrameCount > numFrames) + throw "Too many frames loaded."; + } + + var finishedWindows = []; + + function contains(obj, arr) { + for (var i = 0; i < arr.length; i++) { + if (obj === arr[i]) + return true; + } + return false; + } + + function searchForFinishedFrames(win) { + if (escape(unescape(win.location)) == escape(target_url)) { + if (!contains(win, finishedWindows)) { + finishedWindows.push(win); + frameFinished(); + } + } + for (var i = 0; i < win.frames.length; i++) + searchForFinishedFrames(win.frames[i]); + } + + function poll() { + // This only gives us UniversalXPConnect for the current stack frame + // We're using setInterval, so the main page's privileges are still normal + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Components.interfaces.nsIWindowWatcher); + var enumerator = ww.getWindowEnumerator(); + while (enumerator.hasMoreElements()) { + var win = enumerator.getNext(); + if (!win.gBrowser) + continue; // This window hasn't finished initializing + var tabs = win.gBrowser.browsers; + + for (var i = 0; i < tabs.length; i++) { + searchForFinishedFrames(tabs[i].docShell.document.defaultView); + } + } + } + + var frameWaitInterval = setInterval(poll, 500); +} + diff --git a/docshell/test/navigation/blank.html b/docshell/test/navigation/blank.html new file mode 100644 index 000000000000..245c62e8d1e2 --- /dev/null +++ b/docshell/test/navigation/blank.html @@ -0,0 +1 @@ +This is a blank document. diff --git a/docshell/test/navigation/iframe.html b/docshell/test/navigation/iframe.html new file mode 100644 index 000000000000..4685fea7b7a8 --- /dev/null +++ b/docshell/test/navigation/iframe.html @@ -0,0 +1,8 @@ + + + + + diff --git a/docshell/test/navigation/navigate.html b/docshell/test/navigation/navigate.html new file mode 100644 index 000000000000..dcb879b83a65 --- /dev/null +++ b/docshell/test/navigation/navigate.html @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/docshell/test/navigation/open.html b/docshell/test/navigation/open.html new file mode 100644 index 000000000000..1bb70f865b22 --- /dev/null +++ b/docshell/test/navigation/open.html @@ -0,0 +1,9 @@ + + + + + diff --git a/docshell/test/navigation/parent.html b/docshell/test/navigation/parent.html new file mode 100644 index 000000000000..46028aad9353 --- /dev/null +++ b/docshell/test/navigation/parent.html @@ -0,0 +1,11 @@ + + + +This document contains a frame. +
+ + + + diff --git a/docshell/test/navigation/test_bug13871.html b/docshell/test/navigation/test_bug13871.html new file mode 100644 index 000000000000..088a5b7ebc62 --- /dev/null +++ b/docshell/test/navigation/test_bug13871.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + +Mozilla Bug 13871 +
+
+
+ + diff --git a/docshell/test/navigation/test_bug270414.html b/docshell/test/navigation/test_bug270414.html new file mode 100644 index 000000000000..f0734daf16c0 --- /dev/null +++ b/docshell/test/navigation/test_bug270414.html @@ -0,0 +1,94 @@ + + + + + + + + + + + + +Mozilla Bug 270414 +
+ + + + +
+
+
+
+ + diff --git a/docshell/test/navigation/test_bug278916.html b/docshell/test/navigation/test_bug278916.html new file mode 100644 index 000000000000..697ba11de862 --- /dev/null +++ b/docshell/test/navigation/test_bug278916.html @@ -0,0 +1,40 @@ + + + + + + + + + + + +Mozilla Bug 278916 + +
+
+
+ + diff --git a/docshell/test/navigation/test_bug279495.html b/docshell/test/navigation/test_bug279495.html new file mode 100644 index 000000000000..86cc51eca5cd --- /dev/null +++ b/docshell/test/navigation/test_bug279495.html @@ -0,0 +1,49 @@ + + + + + + + + + + + +Mozilla Bug 279495 + +
+
+
+ + diff --git a/docshell/test/navigation/test_child.html b/docshell/test/navigation/test_child.html new file mode 100644 index 000000000000..f0a05f0e4a33 --- /dev/null +++ b/docshell/test/navigation/test_child.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+ + + + +
+
+
+
+ + diff --git a/docshell/test/navigation/test_grandchild.html b/docshell/test/navigation/test_grandchild.html new file mode 100644 index 000000000000..426fad065570 --- /dev/null +++ b/docshell/test/navigation/test_grandchild.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+ + + + +
+
+
+
+ + diff --git a/docshell/test/navigation/test_not-opener.html b/docshell/test/navigation/test_not-opener.html new file mode 100644 index 000000000000..072ee8ada14b --- /dev/null +++ b/docshell/test/navigation/test_not-opener.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+
+
+ + diff --git a/docshell/test/navigation/test_opener.html b/docshell/test/navigation/test_opener.html new file mode 100644 index 000000000000..c5a88a1bb204 --- /dev/null +++ b/docshell/test/navigation/test_opener.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+
+
+ + diff --git a/docshell/test/navigation/test_popup-navigates-children.html b/docshell/test/navigation/test_popup-navigates-children.html new file mode 100644 index 000000000000..8684c0400d02 --- /dev/null +++ b/docshell/test/navigation/test_popup-navigates-children.html @@ -0,0 +1,63 @@ + + + + + + + + + + + + +
+ + + + +
+
+
+
+ + diff --git a/docshell/test/navigation/test_reserved.html b/docshell/test/navigation/test_reserved.html new file mode 100644 index 000000000000..7fb3af69d440 --- /dev/null +++ b/docshell/test/navigation/test_reserved.html @@ -0,0 +1,97 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+
+
+
+
+ + diff --git a/docshell/test/navigation/test_sibling-matching-parent.html b/docshell/test/navigation/test_sibling-matching-parent.html new file mode 100644 index 000000000000..fe84335b2da1 --- /dev/null +++ b/docshell/test/navigation/test_sibling-matching-parent.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+ + + + +
+
+
+
+
+ + diff --git a/docshell/test/navigation/test_sibling-off-domain.html b/docshell/test/navigation/test_sibling-off-domain.html new file mode 100644 index 000000000000..3d34188b1c02 --- /dev/null +++ b/docshell/test/navigation/test_sibling-off-domain.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + +Mozilla Bug 408052 +
+ + + + +
+
+
+
+
+ + diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 893d3aac5e42..a69a0c7a54dc 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -20,6 +20,7 @@ # # Contributor(s): # Mitch (original author) +# Ehsan Akhgari # # 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"), @@ -42,7 +43,7 @@ KillScriptLocation=Script: %S StopScriptButton=Stop script DebugScriptButton=Debug script WaitForScriptButton=Continue -DontAskAgain=Don't ask me again +DontAskAgain=&Don't ask me again JSURLLoadBlockedWarning=Attempt to load a javascript: URL from one host\nin a window displaying content from another host\nwas blocked by the security manager. WindowCloseBlockedWarning=Scripts may not close windows that were not opened by script. OnBeforeUnloadPreMessage=Are you sure you want to navigate away from this page? diff --git a/dom/locales/en-US/chrome/layout/xul.properties b/dom/locales/en-US/chrome/layout/xul.properties index 45c8a8dfa85a..a2ce598dd3f7 100644 --- a/dom/locales/en-US/chrome/layout/xul.properties +++ b/dom/locales/en-US/chrome/layout/xul.properties @@ -18,6 +18,7 @@ # (C) 2004. All Rights Reserved. # # Contributor(s): +# L. David Baron , Mozilla Corporation # # 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,3 +37,4 @@ MissingOverlay=Failed to load overlay from %1$S. PINotInProlog= processing instruction does not have any effect outside the prolog anymore (see bug 360119). NeededToWrapXUL=XUL box for %1$S element contained an inline %2$S child, forcing all its children to be wrapped in a block. +NeededToWrapXULInlineBox=XUL box for %1$S element contained an inline %2$S child, forcing all its children to be wrapped in a block. This can often be fixed by replacing "display: -moz-inline-box" with "display: -moz-inline-box; display: inline-block". diff --git a/dom/public/idl/storage/nsIDOMStorageManager.idl b/dom/public/idl/storage/nsIDOMStorageManager.idl index c10692846813..8d69d6ab3181 100644 --- a/dom/public/idl/storage/nsIDOMStorageManager.idl +++ b/dom/public/idl/storage/nsIDOMStorageManager.idl @@ -37,7 +37,7 @@ #include "nsISupports.idl" -[scriptable, uuid(74dc93d1-8cdf-43b1-a52c-776dcb873475)] +[scriptable, uuid(6e4bc25e-f056-4c6c-b27e-89152ca91834)] interface nsIDOMStorageManager : nsISupports { /** @@ -49,4 +49,10 @@ interface nsIDOMStorageManager : nsISupports * @returns the space usage of the domain, in bytes. */ long getUsage(in AString aOwnerDomain); + + /** + * Clear keys owned by offline applications. All data owned by a domain + * with the "offline-app" permission will be removed from the database. + */ + void clearOfflineApps(); }; diff --git a/dom/src/base/nsJSEnvironment.cpp b/dom/src/base/nsJSEnvironment.cpp index 9cdf85c6158f..382e417a7b82 100644 --- a/dom/src/base/nsJSEnvironment.cpp +++ b/dom/src/base/nsJSEnvironment.cpp @@ -782,17 +782,9 @@ PrintWinCodebase(nsGlobalWindow *win) } #endif -// The number of operation callbacks between calls to JS_MaybeGC -#define MAYBE_GC_OPERATION_COUNT_MASK 0x00000fff // 4095 +// The accumulated operation weight before we call JS_MaybeGC +const PRUint32 MAYBE_GC_OPERATION_WEIGHT = 5000 * JS_OPERATION_WEIGHT_BASE; -// The number of operation callbacks before we even check if our start -// timestamp is initialized. This is a fairly low number as we want to -// initialize the timestamp early enough to not waste much time before -// we get there, but we don't want to bother doing this too early as -// it's not generally necessary. -#define INITIALIZE_TIME_OPERATION_COUNT_MASK 0x000000ff // 255 - -// This function is called after each JS branch execution JSBool JS_DLL_CALLBACK nsJSContext::DOMOperationCallback(JSContext *cx) { @@ -804,49 +796,34 @@ nsJSContext::DOMOperationCallback(JSContext *cx) return JS_TRUE; } - PRUint32 callbackCount = ++ctx->mOperationCallbackCount; - - if (callbackCount & INITIALIZE_TIME_OPERATION_COUNT_MASK) { - return JS_TRUE; - } - - if (callbackCount == INITIALIZE_TIME_OPERATION_COUNT_MASK + 1 && - LL_IS_ZERO(ctx->mOperationCallbackTime)) { - // Initialize mOperationCallbackTime to start timing how long the - // script has run - ctx->mOperationCallbackTime = PR_Now(); - - ctx->mIsTrackingChromeCodeTime = - ::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx)); - - return JS_TRUE; - } - - if (callbackCount & MAYBE_GC_OPERATION_COUNT_MASK) { - return JS_TRUE; - } - // XXX Save the operation callback time so we can restore it after the GC, // because GCing can cause JS to run on our context, causing our - // ScriptEvaluated to be called, and clearing our operation callback time - // and count. See bug 302333. + // ScriptEvaluated to be called, and clearing our operation callback time. + // See bug 302333. PRTime callbackTime = ctx->mOperationCallbackTime; - // Run the GC if we get this far. JS_MaybeGC(cx); // Now restore the callback time and count, in case they got reset. ctx->mOperationCallbackTime = callbackTime; - ctx->mOperationCallbackCount = callbackCount; PRTime now = PR_Now(); + if (LL_IS_ZERO(callbackTime)) { + // Initialize mOperationCallbackTime to start timing how long the + // script has run + ctx->mOperationCallbackTime = now; + return JS_TRUE; + } + PRTime duration; LL_SUB(duration, now, callbackTime); // Check the amount of time this script has been running, or if the // dialog is disabled. - if (duration < (ctx->mIsTrackingChromeCodeTime ? + PRBool isTrackingChromeCodeTime = + ::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx)); + if (duration < (isTrackingChromeCodeTime ? sMaxChromeScriptRunTime : sMaxScriptRunTime)) { return JS_TRUE; } @@ -991,7 +968,7 @@ nsJSContext::DOMOperationCallback(JSContext *cx) nsIPrefBranch *prefBranch = nsContentUtils::GetPrefBranch(); if (prefBranch) { - prefBranch->SetIntPref(ctx->mIsTrackingChromeCodeTime ? + prefBranch->SetIntPref(isTrackingChromeCodeTime ? "dom.max_chrome_script_run_time" : "dom.max_script_run_time", 0); } @@ -1116,7 +1093,7 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE) this); ::JS_SetOperationCallback(mContext, DOMOperationCallback, - JS_OPERATION_WEIGHT_BASE); + MAYBE_GC_OPERATION_WEIGHT); static JSLocaleCallbacks localeCallbacks = { @@ -1132,10 +1109,8 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE) mNumEvaluations = 0; mTerminations = nsnull; mScriptsEnabled = PR_TRUE; - mOperationCallbackCount = 0; mOperationCallbackTime = LL_ZERO; mProcessingScriptTag = PR_FALSE; - mIsTrackingChromeCodeTime = PR_FALSE; } nsJSContext::~nsJSContext() @@ -3099,10 +3074,10 @@ static JSFunctionSpec JProfFunctions[] = { #ifdef MOZ_SHARK static JSFunctionSpec SharkFunctions[] = { - {"startShark", StartShark, 0, 0, 0}, - {"stopShark", StopShark, 0, 0, 0}, - {"connectShark", ConnectShark, 0, 0, 0}, - {"disconnectShark", DisconnectShark, 0, 0, 0}, + {"startShark", js_StartShark, 0, 0, 0}, + {"stopShark", js_StopShark, 0, 0, 0}, + {"connectShark", js_ConnectShark, 0, 0, 0}, + {"disconnectShark", js_DisconnectShark, 0, 0, 0}, {nsnull, nsnull, 0, 0, 0} }; #endif @@ -3244,7 +3219,6 @@ nsJSContext::ScriptEvaluated(PRBool aTerminated) } #endif - mOperationCallbackCount = 0; mOperationCallbackTime = LL_ZERO; } diff --git a/dom/src/base/nsJSEnvironment.h b/dom/src/base/nsJSEnvironment.h index 7502708c3562..eec94a6a3ac9 100644 --- a/dom/src/base/nsJSEnvironment.h +++ b/dom/src/base/nsJSEnvironment.h @@ -277,11 +277,9 @@ private: PRPackedBool mScriptsEnabled; PRPackedBool mGCOnDestruction; PRPackedBool mProcessingScriptTag; - PRPackedBool mIsTrackingChromeCodeTime; - PRUint32 mOperationCallbackCount; - PRTime mOperationCallbackTime; PRUint32 mDefaultJSOptions; + PRTime mOperationCallbackTime; // mGlobalWrapperRef is used only to hold a strong reference to the // global object wrapper while the nsJSContext is alive. This cuts diff --git a/dom/src/offline/nsDOMOfflineResourceList.cpp b/dom/src/offline/nsDOMOfflineResourceList.cpp index 9b5b700e2c26..6c2cc4bf08be 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.cpp +++ b/dom/src/offline/nsDOMOfflineResourceList.cpp @@ -73,7 +73,7 @@ static const char kMaxEntriesPref[] = "offline.max_site_resources"; #define DEFAULT_MAX_ENTRIES 100 #define MAX_URI_LENGTH 2048 -static nsCAutoString gCachedHostPort; +static nsCAutoString gCachedAsciiHost; static char **gCachedKeys = nsnull; static PRUint32 gCachedKeysCount = 0; @@ -187,7 +187,7 @@ nsDOMOfflineResourceList::Init() // Dynamically-managed resources are stored as a separate ownership list // from the manifest. - rv = mManifestURI->GetSpec(mDynamicOwnerSpec); + rv = mManifestURI->GetAsciiSpec(mDynamicOwnerSpec); NS_ENSURE_SUCCESS(rv, rv); mDynamicOwnerSpec.Append("#dynamic"); @@ -196,7 +196,7 @@ nsDOMOfflineResourceList::Init() if (!innerURI) return NS_ERROR_FAILURE; - rv = innerURI->GetHostPort(mHostPort); + rv = innerURI->GetAsciiHost(mAsciiHost); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr serv = do_GetService(NS_CACHESERVICE_CONTRACTID, @@ -383,7 +383,7 @@ nsDOMOfflineResourceList::Remove(const nsAString& aURI) ClearCachedKeys(); - rv = mCacheSession->RemoveOwnedKey(mHostPort, mDynamicOwnerSpec, key); + rv = mCacheSession->RemoveOwnedKey(mAsciiHost, mDynamicOwnerSpec, key); NS_ENSURE_SUCCESS(rv, rv); rv = mCacheSession->EvictUnownedEntries(); @@ -969,7 +969,7 @@ nsDOMOfflineResourceList::UpdateCompleted(nsIOfflineCacheUpdate *aUpdate) nsresult nsDOMOfflineResourceList::GetCacheKey(nsIURI *aURI, nsCString &aKey) { - nsresult rv = aURI->GetSpec(aKey); + nsresult rv = aURI->GetAsciiSpec(aKey); NS_ENSURE_SUCCESS(rv, rv); // url fragments aren't used in cache keys @@ -987,16 +987,16 @@ nsDOMOfflineResourceList::GetCacheKey(nsIURI *aURI, nsCString &aKey) nsresult nsDOMOfflineResourceList::CacheKeys() { - if (gCachedKeys && mHostPort == gCachedHostPort) + if (gCachedKeys && mAsciiHost == gCachedAsciiHost) return NS_OK; ClearCachedKeys(); - nsresult rv = mCacheSession->GetOwnedKeys(mHostPort, mDynamicOwnerSpec, + nsresult rv = mCacheSession->GetOwnedKeys(mAsciiHost, mDynamicOwnerSpec, &gCachedKeysCount, &gCachedKeys); if (NS_SUCCEEDED(rv)) - gCachedHostPort = mHostPort; + gCachedAsciiHost = mAsciiHost; return rv; } @@ -1010,7 +1010,7 @@ nsDOMOfflineResourceList::ClearCachedKeys() gCachedKeysCount = 0; } - gCachedHostPort = ""; + gCachedAsciiHost = ""; } diff --git a/dom/src/offline/nsDOMOfflineResourceList.h b/dom/src/offline/nsDOMOfflineResourceList.h index f255d5a0c454..92db2dfa36aa 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.h +++ b/dom/src/offline/nsDOMOfflineResourceList.h @@ -110,7 +110,7 @@ private: nsCOMPtr mWindow; nsCOMPtr mCacheSession; nsCOMPtr mCacheUpdate; - nsCAutoString mHostPort; + nsCAutoString mAsciiHost; nsCAutoString mDynamicOwnerSpec; nsCOMArray mCheckingListeners; diff --git a/dom/src/storage/Makefile.in b/dom/src/storage/Makefile.in index 5f35765eaa17..afe1e59b66fa 100644 --- a/dom/src/storage/Makefile.in +++ b/dom/src/storage/Makefile.in @@ -60,6 +60,7 @@ REQUIRES = xpcom \ unicharutil \ widget \ xpconnect \ + prefetch \ $(NULL) ifdef MOZ_STORAGE diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index 9cb5964ada52..05a56b6ad30a 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -52,20 +52,29 @@ #include "nsNetUtil.h" #include "nsIPrefBranch.h" #include "nsICookiePermission.h" +#include "nsIPermission.h" #include "nsIPermissionManager.h" #include "nsCycleCollectionParticipant.h" +#include "nsIOfflineCacheUpdate.h" +#include "nsIJSContextStack.h" static const PRUint32 ASK_BEFORE_ACCEPT = 1; static const PRUint32 ACCEPT_SESSION = 2; static const PRUint32 BEHAVIOR_REJECT = 2; static const PRUint32 DEFAULT_QUOTA = 5 * 1024; +// Be generous with offline apps by default... +static const PRUint32 DEFAULT_OFFLINE_APP_QUOTA = 200 * 1024; +// ... but warn if it goes over this amount +static const PRUint32 DEFAULT_OFFLINE_WARN_QUOTA = 50 * 1024; static const char kPermissionType[] = "cookie"; static const char kStorageEnabled[] = "dom.storage.enabled"; static const char kDefaultQuota[] = "dom.storage.default_quota"; static const char kCookiesBehavior[] = "network.cookie.cookieBehavior"; static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy"; +static const char kOfflineAppWarnQuota[] = "offline-apps.quota.warn"; +static const char kOfflineAppQuota[] = "offline-apps.quota.max"; // // Helper that tells us whether the caller is secure or not. @@ -104,11 +113,44 @@ IsCallerSecure() return NS_SUCCEEDED(rv) && isHttps; } -static PRInt32 -GetQuota(const nsAString &domain) + +// Returns two quotas - A hard limit for which adding data will be an error, +// and a limit after which a warning event will be sent to the observer +// service. The warn limit may be -1, in which case there will be no warning. +static void +GetQuota(const nsAString &aDomain, PRInt32 *aQuota, PRInt32 *aWarnQuota) { + // Fake a URI for the permission manager + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("http://") + aDomain); + + if (uri) { + nsCOMPtr permissionManager = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + + PRUint32 perm; + if (permissionManager && + NS_SUCCEEDED(permissionManager->TestExactPermission(uri, "offline-app", &perm)) && + perm != nsIPermissionManager::UNKNOWN_ACTION && + perm != nsIPermissionManager::DENY_ACTION) { + // This is an offline app, give more space by default. + *aQuota = ((PRInt32)nsContentUtils::GetIntPref(kOfflineAppQuota, + DEFAULT_OFFLINE_WARN_QUOTA * 1024)); + + if (perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN) { + *aWarnQuota = -1; + } else { + *aWarnQuota = ((PRInt32)nsContentUtils::GetIntPref(kOfflineAppWarnQuota, + DEFAULT_OFFLINE_WARN_QUOTA) * 1024); + } + return; + } + } + // FIXME: per-domain quotas? - return ((PRInt32)nsContentUtils::GetIntPref(kDefaultQuota, DEFAULT_QUOTA) * 1024); + *aQuota = ((PRInt32)nsContentUtils::GetIntPref(kDefaultQuota, + DEFAULT_QUOTA) * 1024); + *aWarnQuota = -1; } nsSessionStorageEntry::nsSessionStorageEntry(KeyTypePointer aStr) @@ -153,8 +195,10 @@ nsDOMStorageManager::Initialize() NS_ADDREF(gStorageManager); nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1"); - if (os) + if (os) { os->AddObserver(gStorageManager, "cookie-changed", PR_FALSE); + os->AddObserver(gStorageManager, "offline-app-removed", PR_FALSE); + } return NS_OK; } @@ -189,18 +233,68 @@ ClearStorage(nsDOMStorageEntry* aEntry, void* userArg) return PL_DHASH_REMOVE; } +static nsresult +GetOfflineDomains(nsStringArray& aDomains) +{ + nsCOMPtr permissionManager = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + if (permissionManager) { + nsCOMPtr enumerator; + nsresult rv = permissionManager->GetEnumerator(getter_AddRefs(enumerator)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasMore; + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr perm; + rv = enumerator->GetNext(getter_AddRefs(perm)); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 capability; + rv = perm->GetCapability(&capability); + NS_ENSURE_SUCCESS(rv, rv); + if (capability != nsIPermissionManager::DENY_ACTION) { + nsCAutoString type; + rv = perm->GetType(type); + NS_ENSURE_SUCCESS(rv, rv); + + if (type.EqualsLiteral("offline-app")) { + nsCAutoString host; + rv = perm->GetHost(host); + NS_ENSURE_SUCCESS(rv, rv); + + aDomains.AppendString(NS_ConvertUTF8toUTF16(host)); + } + } + } + } + + return NS_OK; +} + nsresult nsDOMStorageManager::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { - if (!nsCRT::strcmp(aData, NS_LITERAL_STRING("cleared").get())) { + if (!strcmp(aTopic, "offline-app-removed")) { +#ifdef MOZ_STORAGE + nsresult rv = nsDOMStorage::InitDB(); + NS_ENSURE_SUCCESS(rv, rv); + return nsDOMStorage::gStorageDB->RemoveOwner(nsDependentString(aData)); +#endif + } else if (!strcmp(aTopic, "cookie-changed") && + !nsCRT::strcmp(aData, NS_LITERAL_STRING("cleared").get())) { mStorages.EnumerateEntries(ClearStorage, nsnull); #ifdef MOZ_STORAGE nsresult rv = nsDOMStorage::InitDB(); NS_ENSURE_SUCCESS(rv, rv); - return nsDOMStorage::gStorageDB->RemoveAll(); + + // Remove global storage for domains that aren't marked for offline use. + nsStringArray domains; + rv = GetOfflineDomains(domains); + NS_ENSURE_SUCCESS(rv, rv); + return nsDOMStorage::gStorageDB->RemoveOwners(domains, PR_FALSE); #endif } @@ -217,6 +311,18 @@ nsDOMStorageManager::GetUsage(const nsAString& aDomain, return nsDOMStorage::gStorageDB->GetUsage(aDomain, aUsage); } +NS_IMETHODIMP +nsDOMStorageManager::ClearOfflineApps() +{ + nsresult rv = nsDOMStorage::InitDB(); + NS_ENSURE_SUCCESS(rv, rv); + + nsStringArray domains; + rv = GetOfflineDomains(domains); + NS_ENSURE_SUCCESS(rv, rv); + return nsDOMStorage::gStorageDB->RemoveOwners(domains, PR_TRUE); +} + void nsDOMStorageManager::AddToStoragesHash(nsDOMStorage* aStorage) { @@ -762,12 +868,37 @@ nsDOMStorage::SetDBValue(const nsAString& aKey, currentDomain = mDomain; } + PRInt32 quota; + PRInt32 warnQuota; + GetQuota(currentDomain, "a, &warnQuota); + + PRInt32 usage; rv = gStorageDB->SetKey(mDomain, aKey, aValue, aSecure, - currentDomain, GetQuota(currentDomain)); + currentDomain, quota, &usage); NS_ENSURE_SUCCESS(rv, rv); mItemsCached = PR_FALSE; + if (warnQuota >= 0 && usage > warnQuota) { + // try to include the window that exceeded the warn quota + nsCOMPtr window; + JSContext *cx; + nsCOMPtr stack = + do_GetService("@mozilla.org/js/xpc/ContextStack;1"); + if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) { + nsCOMPtr scriptContext; + scriptContext = GetScriptContextFromJSContext(cx); + if (scriptContext) { + window = do_QueryInterface(scriptContext->GetGlobalObject()); + } + } + + nsCOMPtr os = + do_GetService("@mozilla.org/observer-service;1"); + os->NotifyObservers(window, "dom-storage-warn-quota-exceeded", + currentDomain.get()); + } + BroadcastChangeNotification(); #endif diff --git a/dom/src/storage/nsDOMStorageDB.cpp b/dom/src/storage/nsDOMStorageDB.cpp index 2558a117c945..1babb9bc3306 100644 --- a/dom/src/storage/nsDOMStorageDB.cpp +++ b/dom/src/storage/nsDOMStorageDB.cpp @@ -169,6 +169,13 @@ nsDOMStorageDB::Init() getter_AddRefs(mRemoveKeyStatement)); NS_ENSURE_SUCCESS(rv, rv); + // remove keys owned by a specific domain + rv = mConnection->CreateStatement( + NS_LITERAL_CSTRING("DELETE FROM webappsstore " + "WHERE owner = ?1"), + getter_AddRefs(mRemoveOwnerStatement)); + NS_ENSURE_SUCCESS(rv, rv); + // remove all keys rv = mConnection->CreateStatement( NS_LITERAL_CSTRING("DELETE FROM webappsstore"), @@ -264,7 +271,8 @@ nsDOMStorageDB::SetKey(const nsAString& aDomain, const nsAString& aValue, PRBool aSecure, const nsAString& aOwner, - PRInt32 aQuota) + PRInt32 aQuota, + PRInt32 *aNewUsage) { mozStorageStatementScoper scope(mGetKeyValueStatement); @@ -355,6 +363,8 @@ nsDOMStorageDB::SetKey(const nsAString& aDomain, mCachedUsage = usage; } + *aNewUsage = usage; + return NS_OK; } @@ -412,6 +422,63 @@ nsDOMStorageDB::RemoveKey(const nsAString& aDomain, return mRemoveKeyStatement->Execute(); } +nsresult +nsDOMStorageDB::RemoveOwner(const nsAString& aOwner) +{ + mozStorageStatementScoper scope(mRemoveOwnerStatement); + + if (aOwner == mCachedOwner) { + mCachedUsage = 0; + mCachedOwner.Truncate(); + } + + nsresult rv = mRemoveOwnerStatement->BindStringParameter(0, aOwner); + NS_ENSURE_SUCCESS(rv, rv); + + return mRemoveOwnerStatement->Execute(); +} + + +nsresult +nsDOMStorageDB::RemoveOwners(const nsStringArray &aOwners, PRBool aMatch) +{ + if (aOwners.Count() == 0) { + if (aMatch) { + return NS_OK; + } + + return RemoveAll(); + } + + nsCAutoString expression; + + if (aMatch) { + expression.Assign(NS_LITERAL_CSTRING("DELETE FROM webappsstore " + "WHERE owner IN (?")); + } else { + expression.Assign(NS_LITERAL_CSTRING("DELETE FROM webappsstore " + "WHERE owner NOT IN (?")); + } + + for (PRInt32 i = 1; i < aOwners.Count(); i++) { + expression.Append(", ?"); + } + expression.Append(")"); + + nsCOMPtr statement; + + nsresult rv = mConnection->CreateStatement(expression, + getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); + + for (PRInt32 i = 0; i < aOwners.Count(); i++) { + rv = statement->BindStringParameter(i, *aOwners[i]); + NS_ENSURE_SUCCESS(rv, rv); + } + + return statement->Execute(); +} + nsresult nsDOMStorageDB::RemoveAll() { diff --git a/dom/src/storage/nsDOMStorageDB.h b/dom/src/storage/nsDOMStorageDB.h index feeb8401e2cf..5ff1e475bceb 100644 --- a/dom/src/storage/nsDOMStorageDB.h +++ b/dom/src/storage/nsDOMStorageDB.h @@ -85,7 +85,8 @@ public: const nsAString& aValue, PRBool aSecure, const nsAString& aOwner, - PRInt32 aQuota); + PRInt32 aQuota, + PRInt32* aNewUsage); /** * Set the secure flag for a key in storage. Does nothing if the key was @@ -105,6 +106,19 @@ public: const nsAString& aOwner, PRInt32 aKeyUsage); + /** + * Removes all keys added by a given domain. + */ + nsresult + RemoveOwner(const nsAString& aOwner); + + /** + * Removes keys owned by domains that either match or don't match the + * list. + */ + nsresult + RemoveOwners(const nsStringArray& aOwners, PRBool aMatch); + /** * Removes all keys from storage. Used when clearing storage. */ @@ -123,6 +137,7 @@ protected: nsCOMPtr mUpdateKeyStatement; nsCOMPtr mSetSecureStatement; nsCOMPtr mRemoveKeyStatement; + nsCOMPtr mRemoveOwnerStatement; nsCOMPtr mRemoveAllStatement; nsCOMPtr mGetUsageStatement; diff --git a/dom/tests/mochitest/ajax/offline/offlineTests.js b/dom/tests/mochitest/ajax/offline/offlineTests.js index 557c00464591..a8a92cbd414f 100644 --- a/dom/tests/mochitest/ajax/offline/offlineTests.js +++ b/dom/tests/mochitest/ajax/offline/offlineTests.js @@ -113,12 +113,18 @@ clear: function() true) .QueryInterface(Ci.nsIOfflineCacheSession); + // Get the asciiHost from the page URL + var locationURI = Cc["@mozilla.org/network/standard-url;1"] + .createInstance(Ci.nsIURI); + locationURI.spec = window.location.href; + var asciiHost = locationURI.asciiHost; + // Clear manifest-owned urls - cacheSession.setOwnedKeys(window.location.host, + cacheSession.setOwnedKeys(asciiHost, this.getManifestUrl() + "#manifest", 0, []); // Clear dynamically-owned urls - cacheSession.setOwnedKeys(window.location.host, + cacheSession.setOwnedKeys(asciiHost, this.getManifestUrl() + "#dynamic", 0, []); cacheSession.evictUnownedEntries(); diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 7892cec0b6ad..328035ebc64b 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -4353,9 +4353,7 @@ nsresult nsEditor::BeginUpdateViewBatch() } // Turn off view updating. - - if (mViewManager) - mViewManager->BeginUpdateViewBatch(); + mBatch.BeginUpdateViewBatch(mViewManager); } mUpdateCount++; @@ -4411,7 +4409,7 @@ nsresult nsEditor::EndUpdateViewBatch() // have selection code that does sync caret scrolling in this case. presShell->FlushPendingNotifications(Flush_Layout); } - mViewManager->EndUpdateViewBatch(updateFlag); + mBatch.EndUpdateViewBatch(updateFlag); } // Turn selection updating and notifications back on. diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index b1929dd4b688..3f8d5e31e87c 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -65,11 +65,11 @@ #include "nsIInlineSpellChecker.h" #include "nsPIDOMEventTarget.h" #include "nsStubMutationObserver.h" +#include "nsIViewManager.h" class nsIDOMCharacterData; class nsIDOMRange; class nsIPresShell; -class nsIViewManager; class ChangeAttributeTxn; class CreateElementTxn; class InsertElementTxn; @@ -597,6 +597,7 @@ protected: nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController nsIViewManager *mViewManager; PRInt32 mUpdateCount; + nsIViewManager::UpdateViewBatch mBatch; // Spellchecking enum Tristate { diff --git a/editor/libeditor/html/nsHTMLAbsPosition.cpp b/editor/libeditor/html/nsHTMLAbsPosition.cpp index 3f9716d6a5db..aa06b289a831 100644 --- a/editor/libeditor/html/nsHTMLAbsPosition.cpp +++ b/editor/libeditor/html/nsHTMLAbsPosition.cpp @@ -106,7 +106,7 @@ nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval) nsCOMPtr node = do_QueryInterface(element); nsCOMPtr resultNode; - do { + while (!resultNode && !nsEditor::NodeIsType(node, nsEditProperty::html)) { res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition, positionStr); if (NS_FAILED(res)) return res; @@ -118,8 +118,7 @@ nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval) if (NS_FAILED(res)) return res; node.swap(parentNode); } - } while (!resultNode && - !nsEditor::NodeIsType(node, nsEditProperty::html)); + } element = do_QueryInterface(resultNode ); *_retval = element; @@ -315,16 +314,16 @@ nsHTMLEditor::HideGrabber() nsCOMPtr ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // get the root content node. + nsCOMPtr parentNode; + res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); - nsIDOMElement *rootElement = GetRoot(); + nsCOMPtr parentContent = do_QueryInterface(parentNode); + if (!parentContent) return NS_ERROR_NULL_POINTER; - nsCOMPtr rootContent = do_QueryInterface(rootElement); - if (!rootContent) return NS_ERROR_NULL_POINTER; - - DeleteRefToAnonymousNode(mGrabber, rootContent, ps); + DeleteRefToAnonymousNode(mGrabber, parentContent, ps); mGrabber = nsnull; - DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps); + DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); mPositioningShadow = nsnull; return NS_OK; @@ -346,11 +345,13 @@ nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement) // first, let's keep track of that element... mAbsolutelyPositionedObject = aElement; - nsIDOMElement *rootElement = GetRoot(); - if (!rootElement) return NS_ERROR_NULL_POINTER; + nsCOMPtr parentNode; + res = aElement->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); + + res = CreateGrabber(parentNode, getter_AddRefs(mGrabber)); + NS_ENSURE_SUCCESS(res, res); - res = CreateGrabber(rootElement, getter_AddRefs(mGrabber)); - if (NS_FAILED(res)) return res; // and set its position return RefreshGrabber(); } @@ -358,16 +359,17 @@ nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement) nsresult nsHTMLEditor::StartMoving(nsIDOMElement *aHandle) { - nsIDOMElement *rootElement = GetRoot(); - if (!rootElement) return NS_ERROR_NULL_POINTER; + nsCOMPtr parentNode; + nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); // now, let's create the resizing shadow - nsresult result = CreateShadow(getter_AddRefs(mPositioningShadow), - rootElement, mAbsolutelyPositionedObject); - if (NS_FAILED(result)) return result; - result = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject, + res = CreateShadow(getter_AddRefs(mPositioningShadow), + parentNode, mAbsolutelyPositionedObject); + NS_ENSURE_SUCCESS(res,res); + res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject, mPositionedObjectX, mPositionedObjectY); - if (NS_FAILED(result)) return result; + NS_ENSURE_SUCCESS(res,res); // make the shadow appear mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class")); @@ -381,7 +383,7 @@ nsHTMLEditor::StartMoving(nsIDOMElement *aHandle) mPositionedObjectHeight); mIsMoving = PR_TRUE; - return result; + return res; } void @@ -421,14 +423,15 @@ nsHTMLEditor::EndMoving() nsCOMPtr ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // get the root content node. + nsCOMPtr parentNode; + nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); - nsIDOMElement *rootElement = GetRoot(); + nsCOMPtr parentContent( do_QueryInterface(parentNode) ); + if (!parentContent) return NS_ERROR_FAILURE; - nsCOMPtr rootContent( do_QueryInterface(rootElement) ); - if (!rootContent) return NS_ERROR_FAILURE; + DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); - DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps); mPositioningShadow = nsnull; } nsCOMPtr piTarget = GetPIDOMEventTarget(); diff --git a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp index d8f710677840..2dbdc6868af7 100644 --- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp +++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp @@ -203,8 +203,18 @@ nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement, aShell->GetPresContext()->GetPresShell() == aShell) { nsCOMPtr docObserver = do_QueryInterface(aShell); if (docObserver) { + // Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell + // knows we're messing with the frame tree. + nsCOMPtr domDocument; + nsresult res = GetDocument(getter_AddRefs(domDocument)); + nsCOMPtr document = do_QueryInterface(domDocument); + if (document) + docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL); + docObserver->ContentRemoved(content->GetCurrentDoc(), aParentContent, content, -1); + if (document) + docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL); } } content->UnbindFromTree(); diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index ae43e0c89c7c..251ca22b1d59 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -6476,7 +6476,11 @@ nsHTMLEditRules::ReturnInParagraph(nsISelection *aSelection, PRBool newBRneeded = PR_FALSE; nsCOMPtr sibling; - if (mHTMLEditor->IsTextNode(aNode)) + if (aNode == aPara && doesCRCreateNewP) { + // we are at the edges of the block, newBRneeded not needed! + sibling = aNode; + } + else if (mHTMLEditor->IsTextNode(aNode)) { nsCOMPtr textNode = do_QueryInterface(aNode); PRUint32 strLength; diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 22f6931e4bb4..694c6502b635 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -5800,34 +5800,21 @@ nsHTMLEditor::CopyLastEditableChildStyles(nsIDOMNode * aPreviousBlock, nsIDOMNod nsresult nsHTMLEditor::GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY) { - // we are going to need the PresShell + aX = 0; + aY = 0; + if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr content = do_QueryInterface(aElement); - nsIFrame *frame = ps->GetPrimaryFrameFor(content); // not ref-counted + nsIFrame *frame = ps->GetPrimaryFrameFor(content); - if (nsHTMLEditUtils::IsHR(aElement) && frame) { - frame = frame->GetNextSibling(); - } - PRInt32 offsetX = 0, offsetY = 0; - while (frame) { - // Look for a widget so we can get screen coordinates - nsIView* view = frame->GetViewExternal(); - if (view && view->HasWidget()) - break; - - // No widget yet, so count up the coordinates of the frame - nsPoint origin = frame->GetPosition(); - offsetX += origin.x; - offsetY += origin.y; - - frame = frame->GetParent(); - } - - aX = nsPresContext::AppUnitsToIntCSSPixels(offsetX); - aY = nsPresContext::AppUnitsToIntCSSPixels(offsetY); + nsIFrame *container = ps->GetAbsoluteContainingBlock(frame); + if (!frame) return NS_OK; + nsPoint off = frame->GetOffsetTo(container); + aX = nsPresContext::AppUnitsToIntCSSPixels(off.x); + aY = nsPresContext::AppUnitsToIntCSSPixels(off.y); return NS_OK; } diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 1ab4d1a62f3b..2a1e91453b7d 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -815,6 +815,8 @@ protected: void DeleteRefToAnonymousNode(nsIDOMElement* aElement, nsIContent * aParentContent, nsIPresShell* aShell); + + // Returns the offset of an element's frame to its absolute containing block. nsresult GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY); nsresult GetPositionAndDimensions(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY, diff --git a/editor/libeditor/html/nsHTMLObjectResizer.cpp b/editor/libeditor/html/nsHTMLObjectResizer.cpp index f430752dfe6e..eb84689fd641 100644 --- a/editor/libeditor/html/nsHTMLObjectResizer.cpp +++ b/editor/libeditor/html/nsHTMLObjectResizer.cpp @@ -338,37 +338,37 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement) NS_ENSURE_ARG_POINTER(aResizedElement); mResizedObject = aResizedElement; - // the resizers and the shadow will be anonymous children of the body - nsIDOMElement *bodyElement = GetRoot(); - if (!bodyElement) return NS_ERROR_NULL_POINTER; - - // let's create the resizers + // The resizers and the shadow will be anonymous siblings of the element. nsresult res; + nsCOMPtr parentNode; + res = aResizedElement->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); + res = CreateResizer(getter_AddRefs(mTopLeftHandle), - nsIHTMLObjectResizer::eTopLeft, bodyElement); + nsIHTMLObjectResizer::eTopLeft, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mTopHandle), - nsIHTMLObjectResizer::eTop, bodyElement); + nsIHTMLObjectResizer::eTop, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mTopRightHandle), - nsIHTMLObjectResizer::eTopRight, bodyElement); + nsIHTMLObjectResizer::eTopRight, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mLeftHandle), - nsIHTMLObjectResizer::eLeft, bodyElement); + nsIHTMLObjectResizer::eLeft, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mRightHandle), - nsIHTMLObjectResizer::eRight, bodyElement); + nsIHTMLObjectResizer::eRight, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mBottomLeftHandle), - nsIHTMLObjectResizer::eBottomLeft, bodyElement); + nsIHTMLObjectResizer::eBottomLeft, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mBottomHandle), - nsIHTMLObjectResizer::eBottom, bodyElement); + nsIHTMLObjectResizer::eBottom, parentNode); if (NS_FAILED(res)) return res; res = CreateResizer(getter_AddRefs(mBottomRightHandle), - nsIHTMLObjectResizer::eBottomRight, bodyElement); + nsIHTMLObjectResizer::eBottomRight, parentNode); if (NS_FAILED(res)) return res; res = GetPositionAndDimensions(aResizedElement, @@ -387,7 +387,7 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement) if (NS_FAILED(res)) return res; // now, let's create the resizing shadow - res = CreateShadow(getter_AddRefs(mResizingShadow), bodyElement, + res = CreateShadow(getter_AddRefs(mResizingShadow), parentNode, aResizedElement); if (NS_FAILED(res)) return res; // and set its position @@ -396,7 +396,7 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement) if (NS_FAILED(res)) return res; // and then the resizing info tooltip - res = CreateResizingInfo(getter_AddRefs(mResizingInfo), bodyElement); + res = CreateResizingInfo(getter_AddRefs(mResizingInfo), parentNode); if (NS_FAILED(res)) return res; @@ -428,60 +428,58 @@ nsHTMLEditor::HideResizers(void) nsCOMPtr ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // get the root content node. - - nsIDOMElement *bodyElement = GetRoot(); - - nsCOMPtr bodyContent( do_QueryInterface(bodyElement) ); - if (!bodyContent) return NS_ERROR_FAILURE; + nsresult res; + nsCOMPtr parentNode; + res = mTopLeftHandle->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); + nsCOMPtr parentContent = do_QueryInterface(parentNode); NS_NAMED_LITERAL_STRING(mousedown, "mousedown"); - + RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mTopLeftHandle, bodyContent, ps); + mTopLeftHandle, parentContent, ps); mTopLeftHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mTopHandle, bodyContent, ps); + mTopHandle, parentContent, ps); mTopHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mTopRightHandle, bodyContent, ps); + mTopRightHandle, parentContent, ps); mTopRightHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mLeftHandle, bodyContent, ps); + mLeftHandle, parentContent, ps); mLeftHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mRightHandle, bodyContent, ps); + mRightHandle, parentContent, ps); mRightHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mBottomLeftHandle, bodyContent, ps); + mBottomLeftHandle, parentContent, ps); mBottomLeftHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mBottomHandle, bodyContent, ps); + mBottomHandle, parentContent, ps); mBottomHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mBottomRightHandle, bodyContent, ps); + mBottomRightHandle, parentContent, ps); mBottomRightHandle = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mResizingShadow, bodyContent, ps); + mResizingShadow, parentContent, ps); mResizingShadow = nsnull; RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE, - mResizingInfo, bodyContent, ps); + mResizingInfo, parentContent, ps); mResizingInfo = nsnull; // don't forget to remove the listeners ! nsCOMPtr piTarget = GetPIDOMEventTarget(); nsCOMPtr target = do_QueryInterface(piTarget); - nsresult res; if (target && mMouseMotionListenerP) { @@ -683,10 +681,45 @@ nsHTMLEditor::SetResizingInfoPosition(PRInt32 aX, PRInt32 aY, PRInt32 aW, PRInt3 NS_NAMED_LITERAL_STRING(leftStr, "left"); NS_NAMED_LITERAL_STRING(topStr, "top"); + + // Determine the position of the resizing info box based upon the new + // position and size of the element (aX, aY, aW, aH), and which + // resizer is the "activated handle". For example, place the resizing + // info box at the bottom-right corner of the new element, if the element + // is being resized by the bottom-right resizer. + PRInt32 infoXPosition; + PRInt32 infoYPosition; + + if (mActivatedHandle == mTopLeftHandle || + mActivatedHandle == mLeftHandle || + mActivatedHandle == mBottomLeftHandle) + infoXPosition = aX; + else if (mActivatedHandle == mTopHandle || + mActivatedHandle == mBottomHandle) + infoXPosition = aX + (aW / 2); + else + // should only occur when mActivatedHandle is one of the 3 right-side + // handles, but this is a reasonable default if it isn't any of them (?) + infoXPosition = aX + aW; + + if (mActivatedHandle == mTopLeftHandle || + mActivatedHandle == mTopHandle || + mActivatedHandle == mTopRightHandle) + infoYPosition = aY; + else if (mActivatedHandle == mLeftHandle || + mActivatedHandle == mRightHandle) + infoYPosition = aY + (aH / 2); + else + // should only occur when mActivatedHandle is one of the 3 bottom-side + // handles, but this is a reasonable default if it isn't any of them (?) + infoYPosition = aY + aH; + + // Offset info box by 20 so it's not directly under the mouse cursor. + const int mouseCursorOffset = 20; mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, leftStr, - aX + mInfoXIncrement); + infoXPosition + mouseCursorOffset); mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, topStr, - aY + mInfoYIncrement); + infoYPosition + mouseCursorOffset); nsCOMPtr textInfo; nsresult res = mResizingInfo->GetFirstChild(getter_AddRefs(textInfo)); @@ -840,15 +873,17 @@ nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent) mouseEvent->GetClientX(&clientX); mouseEvent->GetClientY(&clientY); + PRInt32 newX = GetNewResizingX(clientX, clientY); + PRInt32 newY = GetNewResizingY(clientX, clientY); PRInt32 newWidth = GetNewResizingWidth(clientX, clientY); PRInt32 newHeight = GetNewResizingHeight(clientX, clientY); mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow, leftStr, - GetNewResizingX(clientX, clientY)); + newX); mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow, topStr, - GetNewResizingY(clientX, clientY)); + newY); mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow, NS_LITERAL_STRING("width"), newWidth); @@ -856,7 +891,7 @@ nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent) NS_LITERAL_STRING("height"), newHeight); - return SetResizingInfoPosition(clientX, clientY, newWidth, newHeight); + return SetResizingInfoPosition(newX, newY, newWidth, newHeight); } if (mGrabberClicked) { diff --git a/editor/libeditor/text/Makefile.in b/editor/libeditor/text/Makefile.in index a15e89ecbc1a..cecd5d02fc37 100644 --- a/editor/libeditor/text/Makefile.in +++ b/editor/libeditor/text/Makefile.in @@ -58,6 +58,7 @@ REQUIRES = xpcom \ necko \ pref \ lwbrk \ + view \ gfx \ thebes \ widget \ diff --git a/editor/libeditor/text/nsEditorEventListeners.cpp b/editor/libeditor/text/nsEditorEventListeners.cpp index 522e6c5b191a..5c66a26efffd 100644 --- a/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/editor/libeditor/text/nsEditorEventListeners.cpp @@ -1065,11 +1065,8 @@ FindSelectionRoot(nsIEditor *aEditor, nsIContent *aContent) CallQueryInterface(rootElement, &root); - if (!root) { - nsIDocument *document = aContent->GetCurrentDoc(); - if (document) { - NS_IF_ADDREF(root = document->GetRootContent()); - } + if (!root && document) { + NS_IF_ADDREF(root = document->GetRootContent()); } return root; @@ -1119,26 +1116,33 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent) { // only enable caret and selection if the editor is not disabled nsCOMPtr content = do_QueryInterface(target); - nsCOMPtr editableRoot = - content ? FindSelectionRoot(mEditor, content) : nsnull; + PRBool targetIsEditableDoc = PR_FALSE; + nsCOMPtr editableRoot; + if (content) { + editableRoot = FindSelectionRoot(mEditor, content); + } + else { + nsCOMPtr document = do_QueryInterface(target); + targetIsEditableDoc = document && document->HasFlag(NODE_IS_EDITABLE); + } nsCOMPtr selCon; mEditor->GetSelectionController(getter_AddRefs(selCon)); - if (selCon) + if (selCon && (targetIsEditableDoc || editableRoot)) { nsCOMPtr selection; selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); nsCOMPtr presShell = do_QueryReferent(mPresShell); - if (presShell) { - nsCOMPtr caret; - presShell->GetCaret(getter_AddRefs(caret)); - if (caret) { - caret->SetIgnoreUserModify(PR_FALSE); - if (selection) { - caret->SetCaretDOMSelection(selection); - } + if (presShell) { + nsCOMPtr caret; + presShell->GetCaret(getter_AddRefs(caret)); + if (caret) { + caret->SetIgnoreUserModify(PR_FALSE); + if (selection) { + caret->SetCaretDOMSelection(selection); + } } } @@ -1203,6 +1207,18 @@ nsTextEditorFocusListener::Blur(nsIDOMEvent* aEvent) } nsCOMPtr presShell = do_QueryReferent(mPresShell); + nsCOMPtr presSelCon = + do_QueryInterface(presShell); + if (presSelCon == selCon && selection) { + nsCOMPtr target; + aEvent->GetTarget(getter_AddRefs(target)); + nsCOMPtr node = do_QueryInterface(target); + nsIDocument* doc = node ? node->GetOwnerDoc() : nsnull; + if (doc && !doc->HasFlag(NODE_IS_EDITABLE)) { + selection->RemoveAllRanges(); + } + } + if (presShell) { nsCOMPtr caret; presShell->GetCaret(getter_AddRefs(caret)); diff --git a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp index a897df008ca7..6df7bc59fc10 100644 --- a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp +++ b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp @@ -44,6 +44,7 @@ #include "nsISupportsUtils.h" #include "nsISupportsArray.h" #include "nsString.h" +#include "nsIPrintDialogService.h" // Printing Progress Includes #include "nsPrintProgress.h" @@ -109,6 +110,13 @@ nsPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrin NS_ENSURE_ARG(webBrowserPrint); NS_ENSURE_ARG(printSettings); + // Try to access a component dialog + nsCOMPtr dlgPrint(do_GetService( + NS_PRINTDIALOGSERVICE_CONTRACTID)); + if (dlgPrint) + return dlgPrint->Show(printSettings); + + // Show the built-in dialog instead ParamBlock block; nsresult rv = block.Init(); if (NS_FAILED(rv)) @@ -177,6 +185,12 @@ nsPrintingPromptService::ShowPageSetup(nsIDOMWindow *parent, nsIPrintSettings *p { NS_ENSURE_ARG(printSettings); + // Try to access a component dialog + nsCOMPtr dlgPrint(do_GetService( + NS_PRINTDIALOGSERVICE_CONTRACTID)); + if (dlgPrint) + return dlgPrint->ShowPageSetup(printSettings); + ParamBlock block; nsresult rv = block.Init(); if (NS_FAILED(rv)) diff --git a/embedding/config/basebrowser-installer-win.pkg b/embedding/config/basebrowser-installer-win.pkg index b842f9f0837b..2cd5a30fbe83 100644 --- a/embedding/config/basebrowser-installer-win.pkg +++ b/embedding/config/basebrowser-installer-win.pkg @@ -222,6 +222,7 @@ components\pipboot.dll components\pipboot.xpt components\pipnss.dll components\pipnss.xpt +nssutil3.dll nss3.dll smime3.dll softokn3.chk diff --git a/embedding/config/basebrowser-mac-macho b/embedding/config/basebrowser-mac-macho index ca6990153cda..5cb4d97204c5 100644 --- a/embedding/config/basebrowser-mac-macho +++ b/embedding/config/basebrowser-mac-macho @@ -162,6 +162,7 @@ components/pipnss.xpt chrome/pipnss.jar defaults/pref/security-prefs.js libnss3.dylib +libnssutil3.dylib libsmime3.dylib libsoftokn3.chk libsoftokn3.dylib diff --git a/embedding/config/basebrowser-qnx b/embedding/config/basebrowser-qnx index 6b2b697d63fb..b912ebbb3cb7 100644 --- a/embedding/config/basebrowser-qnx +++ b/embedding/config/basebrowser-qnx @@ -201,6 +201,7 @@ components/libpipnss.so components/pipnss.xpt chrome/pipnss.jar defaults/pref/security-prefs.js +libnssutil3.so libnss3.so libsmime3.so libsoftokn3.chk diff --git a/embedding/config/basebrowser-unix b/embedding/config/basebrowser-unix index e27b8a8e2514..39775eefb362 100644 --- a/embedding/config/basebrowser-unix +++ b/embedding/config/basebrowser-unix @@ -202,6 +202,7 @@ components/libpipnss.so components/pipnss.xpt chrome/pipnss.jar defaults/pref/security-prefs.js +libnssutil3.so libnss3.so libsmime3.so libsoftokn3.chk diff --git a/embedding/config/basebrowser-win b/embedding/config/basebrowser-win index 1e48623f2341..2cadb6a2016a 100644 --- a/embedding/config/basebrowser-win +++ b/embedding/config/basebrowser-win @@ -238,6 +238,7 @@ components\pipboot.dll components\pipboot.xpt components\pipnss.dll components\pipnss.xpt +nssutil3.dll nss3.dll smime3.dll softokn3.chk diff --git a/embedding/config/minimo-qnx b/embedding/config/minimo-qnx index acfd273cebce..3fd40dd808af 100644 --- a/embedding/config/minimo-qnx +++ b/embedding/config/minimo-qnx @@ -155,6 +155,7 @@ components/libpipnss.so components/pipnss.xpt chrome/pipnss.jar defaults/pref/security-prefs.js +libnssutil3.so libnss3.so libsmime3.so libsoftokn3.chk diff --git a/embedding/config/minimo-unix b/embedding/config/minimo-unix index 567031a429f9..db699dea9a1e 100644 --- a/embedding/config/minimo-unix +++ b/embedding/config/minimo-unix @@ -154,6 +154,7 @@ components/libpipnss.so components/pipnss.xpt chrome/pipnss.jar defaults/pref/security-prefs.js +libnssutil3.so libnss3.so libsmime3.so libsoftokn3.chk diff --git a/extensions/canvas3d/src/nsCanvasRenderingContextGL.h b/extensions/canvas3d/src/nsCanvasRenderingContextGL.h index efcd47e46773..ff026d5684d1 100644 --- a/extensions/canvas3d/src/nsCanvasRenderingContextGL.h +++ b/extensions/canvas3d/src/nsCanvasRenderingContextGL.h @@ -361,7 +361,7 @@ public: ncc->SetReturnValueWasSet(PR_TRUE); } - nsAXPCNativeCallContext ncc; + nsAXPCNativeCallContext *ncc; nsresult error; JSContext *ctx; PRUint32 argc; diff --git a/extensions/inspector/resources/Makefile.in b/extensions/inspector/resources/Makefile.in index f68e3a7a5bcc..ebfcb1156c55 100644 --- a/extensions/inspector/resources/Makefile.in +++ b/extensions/inspector/resources/Makefile.in @@ -51,6 +51,7 @@ ALL_LOCALES = \ pl \ ru \ sk \ + sv-SE \ $(NULL) include $(topsrcdir)/config/config.mk diff --git a/extensions/inspector/resources/locale/sv-SE/inspector.dtd b/extensions/inspector/resources/locale/sv-SE/inspector.dtd index 817c171758fa..fdcc0114692e 100644 --- a/extensions/inspector/resources/locale/sv-SE/inspector.dtd +++ b/extensions/inspector/resources/locale/sv-SE/inspector.dtd @@ -3,6 +3,7 @@ + @@ -46,6 +47,7 @@ + diff --git a/extensions/inspector/resources/locale/sv-SE/search/findFiles.dtd b/extensions/inspector/resources/locale/sv-SE/search/findFiles.dtd deleted file mode 100644 index 6c0cc3216989..000000000000 --- a/extensions/inspector/resources/locale/sv-SE/search/findFiles.dtd +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/extensions/inspector/resources/locale/sv-SE/search/junkImgs.dtd b/extensions/inspector/resources/locale/sv-SE/search/junkImgs.dtd deleted file mode 100644 index 93db36efe1e9..000000000000 --- a/extensions/inspector/resources/locale/sv-SE/search/junkImgs.dtd +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/extensions/inspector/resources/locale/sv-SE/viewers/accessibleEvent.dtd b/extensions/inspector/resources/locale/sv-SE/viewers/accessibleEvent.dtd new file mode 100644 index 000000000000..5d190ae72484 --- /dev/null +++ b/extensions/inspector/resources/locale/sv-SE/viewers/accessibleEvent.dtd @@ -0,0 +1,47 @@ + + + + + + + + + + + diff --git a/extensions/inspector/resources/locale/sv-SE/viewers/accessibleRelations.dtd b/extensions/inspector/resources/locale/sv-SE/viewers/accessibleRelations.dtd new file mode 100644 index 000000000000..3d1254d6d596 --- /dev/null +++ b/extensions/inspector/resources/locale/sv-SE/viewers/accessibleRelations.dtd @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/extensions/inspector/resources/locale/sv-SE/viewers/dom.dtd b/extensions/inspector/resources/locale/sv-SE/viewers/dom.dtd index 2f5776fda1c2..304875231d52 100644 --- a/extensions/inspector/resources/locale/sv-SE/viewers/dom.dtd +++ b/extensions/inspector/resources/locale/sv-SE/viewers/dom.dtd @@ -21,7 +21,9 @@ - - Contributor(s): - Shawn Wilsher + - Ehsan Akhgari - Hasse Wallanger + - Lars P M - - 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 @@ -38,7 +40,7 @@ #endif - ***** END LICENSE BLOCK ***** --> - + @@ -57,7 +59,8 @@ - + + @@ -67,56 +70,85 @@ - + - + + + + - - + + + + + + + + + + - - + + + + - + + + - + + + + + + + + - - + + + + + + - + + + + - + @@ -136,3 +168,8 @@ + + + + + diff --git a/extensions/inspector/resources/locale/sv-SE/viewers/domNode.dtd b/extensions/inspector/resources/locale/sv-SE/viewers/domNode.dtd index 0af53e58647f..18b235525ee9 100644 --- a/extensions/inspector/resources/locale/sv-SE/viewers/domNode.dtd +++ b/extensions/inspector/resources/locale/sv-SE/viewers/domNode.dtd @@ -42,9 +42,9 @@ - + - + diff --git a/extensions/inspector/resources/locale/sv-SE/viewers/jsObject.dtd b/extensions/inspector/resources/locale/sv-SE/viewers/jsObject.dtd index 7eaa92452e1c..713f924d1266 100644 --- a/extensions/inspector/resources/locale/sv-SE/viewers/jsObject.dtd +++ b/extensions/inspector/resources/locale/sv-SE/viewers/jsObject.dtd @@ -38,13 +38,13 @@ - ***** END LICENSE BLOCK ***** --> - + - + diff --git a/extensions/inspector/resources/locale/sv-SE/viewers/styleRules.dtd b/extensions/inspector/resources/locale/sv-SE/viewers/styleRules.dtd index ed6d67db2869..fc28310de150 100644 --- a/extensions/inspector/resources/locale/sv-SE/viewers/styleRules.dtd +++ b/extensions/inspector/resources/locale/sv-SE/viewers/styleRules.dtd @@ -37,7 +37,7 @@ #endif - ***** END LICENSE BLOCK ***** --> - + diff --git a/extensions/metrics/src/Makefile.in b/extensions/metrics/src/Makefile.in index 0059a792e622..6648c55c22b2 100644 --- a/extensions/metrics/src/Makefile.in +++ b/extensions/metrics/src/Makefile.in @@ -66,6 +66,7 @@ REQUIRES = xpcom \ autocomplete \ places \ toolkitcomps \ + locale \ $(NULL) CSRCS = \ diff --git a/extensions/metrics/src/nsProfileCollector.cpp b/extensions/metrics/src/nsProfileCollector.cpp index f2d191ee245f..244f1c325777 100644 --- a/extensions/metrics/src/nsProfileCollector.cpp +++ b/extensions/metrics/src/nsProfileCollector.cpp @@ -57,6 +57,7 @@ #include "nsINavBookmarksService.h" #include "nsINavHistoryService.h" #include "nsILivemarkService.h" +#include "nsILocaleService.h" #include "nsToolkitCompsCID.h" // We need to suppress inclusion of nsString.h @@ -284,6 +285,43 @@ nsProfileCollector::LogInstall(nsIMetricsEventItem *profile) properties->SetPropertyAsACString(NS_LITERAL_STRING("buildid"), buildID); MS_LOG(("Logged install buildid=%s", buildID.get())); + nsCOMPtr em = do_GetService("@mozilla.org/extensions/manager;1"); + NS_ENSURE_STATE(em); + + nsCOMPtr item; + nsresult rv = em->GetItemForID(NS_LITERAL_STRING("metrics@mozilla.org"), getter_AddRefs(item)); + NS_ENSURE_SUCCESS(rv, rv); + + // get the metrics extension version + nsAutoString extversion; + rv = item->GetVersion(extversion); + NS_ENSURE_SUCCESS(rv, rv); + properties->SetPropertyAsAString(NS_LITERAL_STRING("extversion"), extversion); + + MS_LOG(("Logged install extversion=%s", NS_ConvertUTF16toUTF8(extversion).get())); + + // get the application version + nsCString appversion; + appInfo->GetVersion(appversion); + properties->SetPropertyAsACString(NS_LITERAL_STRING("appversion"), appversion); + + MS_LOG(("Logged install appversion=%s", appversion.get())); + + // get the application locale + nsCOMPtr ls = do_GetService(NS_LOCALESERVICE_CONTRACTID); + NS_ENSURE_STATE(ls); + + nsCOMPtr locale(nsnull); + rv = ls->GetApplicationLocale(getter_AddRefs(locale)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString l; + rv = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_CTYPE"), l); + NS_ENSURE_SUCCESS(rv, rv); + properties->SetPropertyAsAString(NS_LITERAL_STRING("locale"), l); + + MS_LOG(("Logged install locale=%s", NS_ConvertUTF16toUTF8(l).get())); + // The file defaults/pref/channel-prefs.js is exlucded from any // security update, so we can use its creation time as an indicator // of when this installation was performed. @@ -295,7 +333,7 @@ nsProfileCollector::LogInstall(nsIMetricsEventItem *profile) nsCOMPtr channelPrefs = do_QueryInterface(prefsDirectory); NS_ENSURE_STATE(channelPrefs); - nsresult rv = channelPrefs->Append(NS_LITERAL_STRING("channel-prefs.js")); + rv = channelPrefs->Append(NS_LITERAL_STRING("channel-prefs.js")); NS_ENSURE_SUCCESS(rv, rv); nsCString nativePath; diff --git a/extensions/spellcheck/locales/en-US/hunspell/en-US.aff b/extensions/spellcheck/locales/en-US/hunspell/en-US.aff index 2ddd98543718..33deb299d496 100644 --- a/extensions/spellcheck/locales/en-US/hunspell/en-US.aff +++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.aff @@ -110,13 +110,14 @@ SFX B e able [^aeiou]e SFX L Y 1 SFX L 0 ment . -REP 88 +REP 89 REP a ei REP ei a REP a ey REP ey a REP ai ie REP ie ai +REP alot a_lot REP are air REP are ear REP are eir diff --git a/extensions/spellcheck/locales/en-US/hunspell/mozilla_words.diff b/extensions/spellcheck/locales/en-US/hunspell/mozilla_words.diff index 6b3878ce336c..8b7d51a85b1d 100644 --- a/extensions/spellcheck/locales/en-US/hunspell/mozilla_words.diff +++ b/extensions/spellcheck/locales/en-US/hunspell/mozilla_words.diff @@ -146,3 +146,24 @@ diff -up4 en-US.dic en-US.dic wed/AS wedded/A wedder +diff -up4 en-US.aff en-US.aff +--- en-US.aff Fri Jan 11 00:27:09 2008 ++++ en-US.aff Sat Jan 12 09:00:41 2008 +@@ -109,15 +109,16 @@ SFX B e able [^aeiou]e + + SFX L Y 1 + SFX L 0 ment . + +-REP 88 ++REP 89 + REP a ei + REP ei a + REP a ey + REP ey a + REP ai ie + REP ie ai ++REP alot a_lot + REP are air + REP are ear + REP are eir + REP air are diff --git a/gfx/cairo/README b/gfx/cairo/README index f01f0873e8d1..2459d8d7297f 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -7,8 +7,8 @@ http://www.cairographics.org/. VERSIONS: - cairo (1.5.x - 1.5.2-55-g39b8ddf) - pixman (0.9.x - pixman-0.9.6-13-g4193b3c) + cairo (1.5.x - 1.5.6-75-gc621d8d) + pixman (0.9.x - pixman-0.9.6-34-g787cc57) glitz 0.5.2 (cvs - 2006-01-10) ***** NOTE FOR VISUAL C++ 6.0 ***** @@ -26,3 +26,5 @@ win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1 nonfatal-assertions.patch: Make assertions non-fatal endian.patch: include cairo-platform.h for endian macros + +fixed-24-8.patch: Switch fixed point mode from 16.16 to 24.8 diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index 374f28a1cb9d..412ea7945de4 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -60,6 +60,8 @@ ifeq ($(OS_ARCH),SunOS) MODULE_OPTIMIZE_FLAGS = -xO5 endif ifeq ($(OS_ARCH),WINNT) +# FIXME: bug 413019 +OS_COMPILE_CFLAGS += -GL- MODULE_OPTIMIZE_FLAGS = -O2 endif endif @@ -93,7 +95,6 @@ CSRCS = \ cairo-matrix.c \ cairo-meta-surface.c \ cairo-mutex.c \ - cairo-operator.c \ cairo-output-stream.c \ cairo-paginated-surface.c \ cairo-path.c \ @@ -121,30 +122,44 @@ CSRCS = \ EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h +# cairo-type1-subset.c should be here, but it's only supported on freetype platforms + +PSPDF_BASE_CSRCS = \ + cairo-base85-stream.c \ + cairo-type1-fallback.c \ + cairo-truetype-subset.c \ + cairo-cff-subset.c \ + $(NULL) + +PDF_CSRCS = \ + cairo-pdf-surface.c \ + cairo-pdf-operators.c \ + $(NULL) + +PS_CSRCS = cairo-ps-surface.c + +PDF_EXPORTS = cairo-pdf.h +PS_EXPORTS = cairo-ps.h ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -CSRCS += cairo-win32-font.c \ - cairo-win32-surface.c \ +CSRCS += cairo-win32.c \ + cairo-win32-font.c \ + cairo-win32-surface.c \ cairo-win32-printing-surface.c EXPORTS += cairo-win32.h -CSRCS += cairo-base85-stream.c \ - cairo-pdf-surface.c \ - cairo-type1-fallback.c \ - cairo-truetype-subset.c \ - cairo-cff-subset.c -EXPORTS += cairo-pdf.h +CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) +EXPORTS += $(PDF_EXPORTS) endif ifeq ($(MOZ_WIDGET_TOOLKIT),os2) +DEFINES += -DOS2_USE_PLATFORM_ALLOC +ifdef MOZ_OS2_HIGH_MEMORY +DEFINES += -DOS2_HIGH_MEMORY +endif CSRCS += cairo-os2-surface.c EXPORTS += cairo-os2.h cairo-os2-private.h -CSRCS += cairo-base85-stream.c \ - cairo-pdf-surface.c \ - cairo-type1-subset.c \ - cairo-type1-fallback.c \ - cairo-truetype-subset.c \ - cairo-cff-subset.c -EXPORTS += cairo-pdf.h +CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) +EXPORTS += $(PDF_EXPORTS) endif ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) @@ -158,14 +173,8 @@ EXPORTS += cairo-beos.h endif ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) -CSRCS += cairo-base85-stream.c \ - cairo-pdf-surface.c \ - cairo-ps-surface.c \ - cairo-type1-subset.c \ - cairo-type1-fallback.c \ - cairo-truetype-subset.c \ - cairo-cff-subset.c -EXPORTS += cairo-ps.h cairo-pdf.h +CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) $(PS_CSRCS) +EXPORTS += $(PDF_EXPORTS) $(PS_EXPORTS) endif ifdef BUILD_CAIRO_SVG @@ -181,7 +190,7 @@ EXPORTS += cairo-xlib.h cairo-xlib-xrender.h endif ifdef MOZ_ENABLE_CAIRO_FT -CSRCS += cairo-ft-font.c +CSRCS += cairo-ft-font.c cairo-type1-subset.c EXPORTS += cairo-ft.h OS_INCLUDES += $(CAIRO_FT_CFLAGS) endif diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface.c b/gfx/cairo/cairo/src/cairo-analysis-surface.c index 97b245e421fb..edface260878 100644 --- a/gfx/cairo/cairo/src/cairo-analysis-surface.c +++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c @@ -57,31 +57,42 @@ typedef struct { cairo_rectangle_int_t current_clip; cairo_box_t page_bbox; + cairo_bool_t has_ctm; + cairo_matrix_t ctm; + } cairo_analysis_surface_t; static cairo_int_status_t _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface, cairo_pattern_t *pattern) { + cairo_surface_t *analysis = &surface->base; cairo_surface_pattern_t *surface_pattern; - cairo_surface_t *meta_surface; - cairo_surface_t *analysis; cairo_status_t status; + cairo_bool_t old_has_ctm; + cairo_matrix_t old_ctm, p2d; assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); surface_pattern = (cairo_surface_pattern_t *) pattern; assert (_cairo_surface_is_meta (surface_pattern->surface)); - meta_surface = surface_pattern->surface; - analysis = _cairo_analysis_surface_create (surface->target, - surface->width, surface->height); - if (analysis == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + old_ctm = surface->ctm; + old_has_ctm = surface->has_ctm; + p2d = pattern->matrix; + status = cairo_matrix_invert (&p2d); + /* _cairo_pattern_set_matrix guarantees invertibility */ + assert (status == CAIRO_STATUS_SUCCESS); - status = _cairo_meta_surface_replay_analyze_meta_pattern (meta_surface, analysis); + cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm); + surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); + + status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface, + analysis); if (status == CAIRO_STATUS_SUCCESS) - status = analysis->status; - cairo_surface_destroy (analysis); + status = analysis->status; + + surface->ctm = old_ctm; + surface->has_ctm = old_has_ctm; return status; } @@ -97,6 +108,28 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface, if (rect->width == 0 || rect->height == 0) return CAIRO_STATUS_SUCCESS; + if (surface->has_ctm) { + double x1, y1, x2, y2; + + x1 = rect->x; + y1 = rect->y; + x2 = rect->x + rect->width; + y2 = rect->y + rect->height; + _cairo_matrix_transform_bounding_box (&surface->ctm, + &x1, &y1, &x2, &y2, + NULL); + rect->x = floor (x1); + rect->y = floor (y1); + + x2 = ceil (x2) - rect->x; + y2 = ceil (y2) - rect->y; + if (x2 <= 0 || y2 <= 0) + return CAIRO_STATUS_SUCCESS; + + rect->width = x2; + rect->height = y2; + } + bbox.p1.x = _cairo_fixed_from_int (rect->x); bbox.p1.y = _cairo_fixed_from_int (rect->y); bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width); @@ -188,28 +221,24 @@ _cairo_analysis_surface_intersect_clip_path (void *abstract_surface, cairo_analysis_surface_t *surface = abstract_surface; double x1, y1, x2, y2; cairo_rectangle_int_t extent; - cairo_status_t status; if (path == NULL) { surface->current_clip.x = 0; surface->current_clip.y = 0; - surface->current_clip.width = surface->width; + surface->current_clip.width = surface->width; surface->current_clip.height = surface->height; - status = CAIRO_STATUS_SUCCESS; } else { - status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2); - if (status) - return status; + _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance); extent.x = floor (x1); extent.y = floor (y1); - extent.width = ceil (x2) - extent.x; + extent.width = ceil (x2) - extent.x; extent.height = ceil (y2) - extent.y; _cairo_rectangle_intersect (&surface->current_clip, &extent); } - return status; + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -382,7 +411,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface, tolerance, &traps); - if (status) { + if (status || traps.num_traps == 0) { _cairo_traps_fini (&traps); return status; } @@ -405,9 +434,9 @@ _cairo_analysis_surface_fill (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, + cairo_fill_rule_t fill_rule, double tolerance, - cairo_antialias_t antialias) + cairo_antialias_t antialias) { cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; @@ -454,7 +483,7 @@ _cairo_analysis_surface_fill (void *abstract_surface, tolerance, &traps); - if (status) { + if (status || traps.num_traps == 0) { _cairo_traps_fini (&traps); return status; } @@ -557,6 +586,9 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = { _cairo_analysis_surface_fill, _cairo_analysis_surface_show_glyphs, NULL, /* snapshot */ + NULL, /* is_similar */ + NULL, /* reset */ + NULL, /* fill_stroke */ }; cairo_surface_t * @@ -568,7 +600,7 @@ _cairo_analysis_surface_create (cairo_surface_t *target, surface = malloc (sizeof (cairo_analysis_surface_t)); if (surface == NULL) - goto FAIL; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); /* I believe the content type here is truly arbitrary. I'm quite * sure nothing will ever use this value. */ @@ -577,6 +609,8 @@ _cairo_analysis_surface_create (cairo_surface_t *target, surface->width = width; surface->height = height; + cairo_matrix_init_identity (&surface->ctm); + surface->has_ctm = FALSE; surface->target = target; surface->first_op = TRUE; @@ -591,9 +625,6 @@ _cairo_analysis_surface_create (cairo_surface_t *target, surface->current_clip.height = height; return &surface->base; -FAIL: - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; } cairo_region_t * diff --git a/gfx/cairo/cairo/src/cairo-array.c b/gfx/cairo/cairo/src/cairo-array.c index 0313caa907dd..470b327cf38f 100644 --- a/gfx/cairo/cairo/src/cairo-array.c +++ b/gfx/cairo/cairo/src/cairo-array.c @@ -396,8 +396,7 @@ _cairo_user_data_array_get_data (cairo_user_data_array_t *array, int i, num_slots; cairo_user_data_slot_t *slots; - /* We allow this to support degenerate objects such as - * cairo_image_surface_nil. */ + /* We allow this to support degenerate objects such as cairo_surface_nil. */ if (array == NULL) return NULL; diff --git a/gfx/cairo/cairo/src/cairo-atsui-font.c b/gfx/cairo/cairo/src/cairo-atsui-font.c index 6a44730a53ed..d4c1f643b6d1 100644 --- a/gfx/cairo/cairo/src/cairo-atsui-font.c +++ b/gfx/cairo/cairo/src/cairo-atsui-font.c @@ -273,8 +273,7 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, err = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix, &font->style); if (err != noErr) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - status = CAIRO_STATUS_NO_MEMORY; + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FAIL; } @@ -301,8 +300,7 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, status = _cairo_atsui_font_set_metrics (font); - font->cgfref = NULL; - + font->cgfref = 0; FAIL: if (status) { if (font) { @@ -453,6 +451,7 @@ _cairo_atsui_font_fini(void *abstract_font) ATSUDisposeStyle(font->unscaled_style); if (font->cgfref) CGFontRelease(font->cgfref); + } static GlyphID diff --git a/gfx/cairo/cairo/src/cairo-base85-stream.c b/gfx/cairo/cairo/src/cairo-base85-stream.c index 97ef2635f385..b7dc9b14b600 100644 --- a/gfx/cairo/cairo/src/cairo-base85-stream.c +++ b/gfx/cairo/cairo/src/cairo-base85-stream.c @@ -113,6 +113,9 @@ _cairo_base85_stream_create (cairo_output_stream_t *output) { cairo_base85_stream_t *stream; + if (output->status) + return _cairo_output_stream_create_in_error (output->status); + stream = malloc (sizeof (cairo_base85_stream_t)); if (stream == NULL) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); diff --git a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c index b8a5f813aa85..3ef78589518e 100644 --- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c +++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c @@ -1421,7 +1421,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, { int intersections; cairo_status_t status; - cairo_bo_edge_t stack_edges[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_bo_edge_t)]; + cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)]; cairo_bo_edge_t *edges; cairo_fixed_t xmin = 0x7FFFFFFF; cairo_fixed_t ymin = 0x7FFFFFFF; diff --git a/gfx/cairo/cairo/src/cairo-clip.c b/gfx/cairo/cairo/src/cairo-clip.c index 0fed3f694e1a..ae3051515cad 100644 --- a/gfx/cairo/cairo/src/cairo-clip.c +++ b/gfx/cairo/cairo/src/cairo-clip.c @@ -704,7 +704,7 @@ _cairo_clip_int_rect_to_user (cairo_gstate_t *gstate, return is_tight; } -cairo_private cairo_rectangle_list_t* +cairo_rectangle_list_t * _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) { cairo_rectangle_list_t *list; @@ -721,7 +721,7 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) cairo_box_int_t *boxes; int i; - if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes) != CAIRO_STATUS_SUCCESS) + if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes)) return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; if (n_boxes) { diff --git a/gfx/cairo/cairo/src/cairo-compiler-private.h b/gfx/cairo/cairo/src/cairo-compiler-private.h index da80b89e43f0..1c6645e4afc4 100644 --- a/gfx/cairo/cairo/src/cairo-compiler-private.h +++ b/gfx/cairo/cairo/src/cairo-compiler-private.h @@ -70,12 +70,14 @@ CAIRO_BEGIN_DECLS #endif /* slim_internal.h */ +#define CAIRO_HAS_HIDDEN_SYMBOLS 1 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun) #define cairo_private_no_warn __attribute__((__visibility__("hidden"))) #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) #define cairo_private_no_warn __hidden #else /* not gcc >= 3.3 and not Sun Studio >= 8 */ #define cairo_private_no_warn +#undef CAIRO_HAS_HIDDEN_SYMBOLS #endif #ifndef WARN_UNUSED_RESULT @@ -109,6 +111,16 @@ CAIRO_BEGIN_DECLS #define __attribute__(x) #endif +#ifdef _MSC_VER +#define snprintf _snprintf +#undef inline +#define inline __inline +#endif + +#ifdef __STRICT_ANSI__ +#undef inline +#define inline __inline__ +#endif CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-deflate-stream.c b/gfx/cairo/cairo/src/cairo-deflate-stream.c index 707832db4caa..8734b1782dcd 100644 --- a/gfx/cairo/cairo/src/cairo-deflate-stream.c +++ b/gfx/cairo/cairo/src/cairo-deflate-stream.c @@ -117,11 +117,8 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output) { cairo_deflate_stream_t *stream; - if (output->status) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_output_stream_t *) &_cairo_output_stream_nil; - } - + if (output->status) + return _cairo_output_stream_create_in_error (output->status); stream = malloc (sizeof (cairo_deflate_stream_t)); if (stream == NULL) { diff --git a/gfx/cairo/cairo/src/cairo-directfb-surface.c b/gfx/cairo/cairo/src/cairo-directfb-surface.c index e6f354f63a85..2c57a9704e9f 100644 --- a/gfx/cairo/cairo/src/cairo-directfb-surface.c +++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c @@ -34,13 +34,14 @@ * Michael Emmel * Claudio Ciccani */ + #include "cairoint.h" - #include "cairo-directfb.h" -#include +#include +#include #include #include #include @@ -48,9 +49,11 @@ /* - * Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS). + * Rectangle works fine. + * Bugs 361377, 359553, 359243 in Gnome BTS are caused + * by GDK/DirectFB, not by Cairo/DirectFB. */ -#define DFB_RECTANGLES 0 +#define DFB_RECTANGLES 1 /* * Composite works fine. @@ -68,7 +71,7 @@ #define DFB_SHOW_GLYPHS 1 -D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend") +D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend"); /*****************************************************************************/ @@ -76,17 +79,22 @@ D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend") typedef struct _cairo_directfb_surface { cairo_surface_t base; cairo_format_t format; + cairo_content_t content; + IDirectFB *dfb; - int owner; IDirectFBSurface *dfbsurface; + IDirectFBSurface *tmpsurface; + /* color buffer */ cairo_surface_t *color; DFBRegion *clips; int n_clips; - DFBRegion *dirty_region; + int width; int height; + + cairo_bool_t local; } cairo_directfb_surface_t; @@ -108,6 +116,10 @@ static cairo_surface_backend_t cairo_directfb_surface_backend; /*****************************************************************************/ +static int _directfb_argb_font = 0; + +/*****************************************************************************/ + #define RUN_CLIPPED( surface, clip, func ) {\ if ((surface)->clips) {\ @@ -142,11 +154,18 @@ static cairo_surface_backend_t cairo_directfb_surface_backend; }\ } -#define TRANSFORM_POINT( m, x, y, ret_x, ret_y ) {\ +#define TRANSFORM_POINT2X( m, x, y, ret_x, ret_y ) {\ double _x = (x);\ double _y = (y);\ - (ret_x) = (_x * (m)->xx + _y * (m)->xy + (m)->x0);\ - (ret_y) = (_x * (m)->yx + _y * (m)->yy + (m)->y0);\ + (ret_x) = (_x * (m).xx + (m).x0);\ + (ret_y) = (_y * (m).yy + (m).y0);\ +} + +#define TRANSFORM_POINT3X( m, x, y, ret_x, ret_y ) {\ + double _x = (x);\ + double _y = (y);\ + (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\ + (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\ } /* XXX: A1 has a different bits ordering in cairo. @@ -154,24 +173,21 @@ static cairo_surface_backend_t cairo_directfb_surface_backend; */ static cairo_content_t -_directfb_format_to_content ( DFBSurfacePixelFormat format ) +_directfb_format_to_content (DFBSurfacePixelFormat format) { - switch (format) { - case DSPF_ARGB: + if (DFB_PIXELFORMAT_HAS_ALPHA(format)) { + if (DFB_COLOR_BITS_PER_PIXEL(format)) return CAIRO_CONTENT_COLOR_ALPHA; - case DSPF_A8: - return CAIRO_CONTENT_ALPHA; - case DSPF_RGB32: - case DSPF_A1: - default: - return CAIRO_CONTENT_COLOR; - break; + + return CAIRO_CONTENT_ALPHA; } + + return CAIRO_CONTENT_COLOR; } static inline DFBSurfacePixelFormat -cairo_to_directfb_format (cairo_format_t format) +_cairo_to_directfb_format (cairo_format_t format) { switch (format) { case CAIRO_FORMAT_RGB24: @@ -190,16 +206,16 @@ cairo_to_directfb_format (cairo_format_t format) } static inline cairo_format_t -directfb_to_cairo_format (DFBSurfacePixelFormat format) +_directfb_to_cairo_format (DFBSurfacePixelFormat format) { switch (format) { case DSPF_RGB32: return CAIRO_FORMAT_RGB24; case DSPF_ARGB: return CAIRO_FORMAT_ARGB32; - case DSPF_A8 : + case DSPF_A8: return CAIRO_FORMAT_A8; - case DSPF_A1 : + case DSPF_A1: return CAIRO_FORMAT_A1; default: break; @@ -211,13 +227,9 @@ directfb_to_cairo_format (DFBSurfacePixelFormat format) static cairo_status_t _directfb_get_operator (cairo_operator_t operator, - DFBSurfaceDrawingFlags *ret_drawing, - DFBSurfaceBlittingFlags *ret_blitting, DFBSurfaceBlendFunction *ret_srcblend, DFBSurfaceBlendFunction *ret_dstblend ) -{ - DFBSurfaceDrawingFlags drawing = DSDRAW_BLEND; - DFBSurfaceBlittingFlags blitting = DSBLIT_BLEND_ALPHACHANNEL; +{ DFBSurfaceBlendFunction srcblend = DSBF_ONE; DFBSurfaceBlendFunction dstblend = DSBF_ZERO; @@ -227,8 +239,8 @@ _directfb_get_operator (cairo_operator_t operator, dstblend = DSBF_ZERO; break; case CAIRO_OPERATOR_SOURCE: - drawing = DSDRAW_NOFX; - blitting = DSBLIT_NOFX; + srcblend = DSBF_ONE; + dstblend = DSBF_ZERO; break; case CAIRO_OPERATOR_OVER: srcblend = DSBF_ONE; @@ -281,11 +293,7 @@ _directfb_get_operator (cairo_operator_t operator, default: return CAIRO_INT_STATUS_UNSUPPORTED; } - - if (ret_drawing) - *ret_drawing = drawing; - if (ret_blitting) - *ret_blitting = blitting; + if (ret_srcblend) *ret_srcblend = srcblend; if (ret_dstblend) @@ -319,76 +327,106 @@ _directfb_buffer_surface_create (IDirectFB *dfb, } static cairo_status_t -_directfb_acquire_surface (cairo_directfb_surface_t *surface, - cairo_rectangle_int_t *intrest_rec, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra, - DFBSurfaceLockFlags lock_flags) +_directfb_acquire_surface (cairo_directfb_surface_t *surface, + cairo_rectangle_int_t *intrest_rec, + cairo_image_surface_t **image_out, + cairo_rectangle_int_t *image_rect_out, + void **image_extra, + DFBSurfaceLockFlags lock_flags) { - void *data; - int pitch; - IDirectFBSurface *buffer; + IDirectFBSurface *buffer = NULL; DFBRectangle source_rect; - cairo_format_t cairo_format; - cairo_format = surface->format; + cairo_format_t cairo_format; + void *data; + int pitch; if (surface->format == (cairo_format_t) -1) { - if( intrest_rec ) { + DFBSurfaceCapabilities caps; + + if (intrest_rec) { source_rect.x = intrest_rec->x; source_rect.y = intrest_rec->y; source_rect.w = intrest_rec->width; source_rect.h = intrest_rec->height; - }else { - source_rect.x=0; - source_rect.y=0; - surface->dfbsurface->GetSize (surface->dfbsurface,&source_rect.w, &source_rect.h); + } else { + source_rect.x = 0; + source_rect.y = 0; + surface->dfbsurface->GetSize (surface->dfbsurface, + &source_rect.w, &source_rect.h); + } + + if (surface->tmpsurface) { + int w, h; + surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h); + if (w < source_rect.w || h < source_rect.h) { + surface->tmpsurface->Release (surface->tmpsurface); + surface->tmpsurface = NULL; + } } - D_DEBUG_AT (Cairo_DirectFB, "%s buffer for surface.\n", - surface->dfbsurface ? "Reallocating" : "Allocating"); - cairo_format = directfb_to_cairo_format(DSPF_ARGB); - buffer = _directfb_buffer_surface_create (surface->dfb,DSPF_ARGB,source_rect.w,source_rect.h); - if (!buffer) - goto ERROR; - *image_extra = buffer; - buffer->SetBlittingFlags (buffer,DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE); - buffer->Blit (buffer,surface->dfbsurface,&source_rect,0,0); - } else { - /*might be a subsurface get the offset*/ - surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface,&source_rect); - buffer = surface->dfbsurface; - *image_extra = buffer; - } - - if( buffer->Lock (buffer,lock_flags, &data, &pitch) ) + cairo_format = _cairo_format_from_content (surface->content); + if (!surface->tmpsurface) { + D_DEBUG_AT (Cairo_DirectFB, "Allocating buffer for surface %p.\n", surface); + + surface->tmpsurface = + _directfb_buffer_surface_create (surface->dfb, + _cairo_to_directfb_format (cairo_format), + source_rect.w, source_rect.h); + if (!surface->tmpsurface) + goto ERROR; + } + buffer = surface->tmpsurface; + + surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps); + if (caps & DSCAPS_FLIPPING) { + DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y, + .x2 = source_rect.x + source_rect.w - 1, + .y2 = source_rect.y + source_rect.h - 1 }; + surface->dfbsurface->Flip (surface->dfbsurface, ®ion, DSFLIP_BLIT); + } + buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0); + } + else { + /*might be a subsurface get the offset*/ + surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect); + cairo_format = surface->format; + buffer = surface->dfbsurface; + } + + *image_extra = buffer; + + if (buffer->Lock (buffer, lock_flags, &data, &pitch)) { + D_DEBUG_AT (Cairo_DirectFB, "Couldn't lock surface!\n"); goto ERROR; + } - *image_out = (cairo_image_surface_t *)cairo_image_surface_create_for_data (data, - cairo_format,source_rect.w,source_rect.h, pitch); - if (*image_out == NULL ) - goto ERROR; + *image_out = (cairo_image_surface_t *) + cairo_image_surface_create_for_data (data, cairo_format, + source_rect.w, source_rect.h, pitch); + if (*image_out == NULL) + goto ERROR; if (image_rect_out) { image_rect_out->x = source_rect.x; image_rect_out->y = source_rect.y; image_rect_out->width = source_rect.w; image_rect_out->height = source_rect.h; - }else { - /*lock for read*/ + } else { + /* lock for read */ cairo_surface_t *sur = &((*image_out)->base); - /*might be a subsurface*/ - if( buffer == surface->dfbsurface ) - cairo_surface_set_device_offset (sur,source_rect.x,source_rect.y); + /* might be a subsurface */ + if (buffer == surface->dfbsurface) + cairo_surface_set_device_offset (sur, source_rect.x, source_rect.y); } - return CAIRO_STATUS_SUCCESS; + + return CAIRO_STATUS_SUCCESS; - ERROR: +ERROR: *image_extra = NULL; - if( buffer ) { - buffer->Unlock (buffer); - if( buffer != surface->dfbsurface) - buffer->Release(buffer); + if (buffer) { + buffer->Unlock (buffer); + if (buffer != surface->dfbsurface) + buffer->Release (buffer); } return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -415,26 +453,42 @@ _cairo_directfb_surface_create_similar (void *abstract_src, format = _cairo_format_from_content (content); surface = calloc (1, sizeof(cairo_directfb_surface_t)); if (!surface) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; } - surface->dfbsurface = _directfb_buffer_surface_create (source->dfb, - cairo_to_directfb_format (format), - width, height); - assert(surface->dfbsurface); - - surface->owner = TRUE; + surface->dfb = source->dfb; + + if (width < 8 || height < 8) { + IDirectFBSurface *tmp; + /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */ + tmp = _directfb_buffer_surface_create (surface->dfb, + _cairo_to_directfb_format (format), + MAX (width, 8), MAX (height, 8)); + if (tmp) { + DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height }; + tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface); + tmp->Release (tmp); + } + } + else { + surface->dfbsurface = _directfb_buffer_surface_create (surface->dfb, + _cairo_to_directfb_format (format), width, height); + } + if (!surface->dfbsurface) { - assert(0); + D_ASSERT (surface->dfbsurface != NULL); free (surface); return NULL; } - _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,content); - surface->dfb = source->dfb; - surface->format = format; - surface->width = width; - surface->height = height; + + _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend, content); + surface->format = format; + surface->content = content; + surface->width = width; + surface->height = height; + surface->local = true; + return &surface->base; } @@ -456,16 +510,19 @@ _cairo_directfb_surface_finish (void *data) cairo_surface_destroy (surface->color); surface->color = NULL; } + + if (surface->tmpsurface) { + surface->tmpsurface->Release (surface->tmpsurface); + surface->tmpsurface = NULL; + } if (surface->dfbsurface) { - if( surface->owner ) surface->dfbsurface->Release (surface->dfbsurface); - surface->dfbsurface = NULL; + surface->dfbsurface = NULL; } - if (surface->dfb) { - surface->dfb = NULL; - } + if (surface->dfb) + surface->dfb = NULL; return CAIRO_STATUS_SUCCESS; } @@ -476,9 +533,12 @@ _cairo_directfb_surface_acquire_source_image (void *abstract_s void **image_extra) { cairo_directfb_surface_t *surface = abstract_surface; + D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); - return _directfb_acquire_surface (surface,NULL,image_out,NULL,image_extra,DSLF_READ); + + return _directfb_acquire_surface (surface, NULL, image_out, + NULL, image_extra, DSLF_READ); } static void @@ -493,33 +553,36 @@ _cairo_directfb_surface_release_source_image (void *abstract_su "%s( surface=%p ).\n", __FUNCTION__, surface); buffer->Unlock (buffer); - if (surface->dfbsurface != buffer) { - buffer->Release (buffer); - } + cairo_surface_destroy (&image->base); } static cairo_status_t -_cairo_directfb_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) +_cairo_directfb_surface_acquire_dest_image (void *abstract_surface, + cairo_rectangle_int_t *interest_rect, + cairo_image_surface_t **image_out, + cairo_rectangle_int_t *image_rect_out, + void **image_extra) { cairo_directfb_surface_t *surface = abstract_surface; D_DEBUG_AT (Cairo_DirectFB, - "%s( surface=%p ).\n", __FUNCTION__, surface); + "%s( surface=%p, interest_rect={ %d %d %d %d } ).\n", + __FUNCTION__, surface, + interest_rect ? interest_rect->x : 0, + interest_rect ? interest_rect->y : 0, + interest_rect ? interest_rect->width : surface->width, + interest_rect ? interest_rect->height : surface->height); - return _directfb_acquire_surface (surface,interest_rect,image_out,image_rect_out,image_extra, - DSLF_READ | DSLF_WRITE); + return _directfb_acquire_surface (surface, interest_rect, image_out, + image_rect_out, image_extra, DSLF_READ | DSLF_WRITE); } static void _cairo_directfb_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, + cairo_rectangle_int_t *interest_rect, cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, + cairo_rectangle_int_t *image_rect, void *image_extra) { cairo_directfb_surface_t *surface = abstract_surface; @@ -527,29 +590,29 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf D_DEBUG_AT (Cairo_DirectFB, "%s( surface=%p ).\n", __FUNCTION__, surface); + buffer->Unlock (buffer); if (surface->dfbsurface != buffer) { DFBRegion region = { .x1 = interest_rect->x, .y1 = interest_rect->y, - .x2 = interest_rect->x+interest_rect->width-1, - .y2 = interest_rect->y+interest_rect->height-1 }; + .x2 = interest_rect->x+interest_rect->width-1, + .y2 = interest_rect->y+interest_rect->height-1 }; surface->dfbsurface->SetClip (surface->dfbsurface, ®ion); - /* surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, - DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE); */ - surface->dfbsurface->Blit (surface->dfbsurface,buffer,NULL, - image_rect->x,image_rect->y); - buffer->Release (buffer); + surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX); + surface->dfbsurface->Blit (surface->dfbsurface, buffer, + NULL, image_rect->x, image_rect->y); } + cairo_surface_destroy (&image->base); } static cairo_status_t _cairo_directfb_surface_clone_similar (void *abstract_surface, cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, + int src_x, + int src_y, + int width, + int height, cairo_surface_t **clone_out) { cairo_directfb_surface_t *surface = abstract_surface; @@ -586,8 +649,8 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - dst += pitch * src_y; - src += image_src->stride * src_y; + dst += pitch * src_y; + src += image_src->stride * src_y; if (image_src->format == CAIRO_FORMAT_A1) { /* A1 -> A8 */ @@ -599,9 +662,20 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface, } } else { - /* A8 -> A8 */ + int len; + + if (image_src->format == CAIRO_FORMAT_A8) { + dst += src_x; + src += src_x; + len = width; + } else { + dst += src_x * 4; + src += src_x * 4; + len = width * 4; + } + for (i = 0; i < height; i++) { - direct_memcpy( dst+src_x, src+src_x, sizeof(*dst)*width ); + direct_memcpy (dst+src_x, src+src_x, len); dst += pitch; src += image_src->stride; } @@ -619,7 +693,7 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface, #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS static cairo_int_status_t -_directfb_prepare_composite (cairo_directfb_surface_t *dst, +_directfb_prepare_composite (cairo_directfb_surface_t *dst, cairo_pattern_t *src_pattern, cairo_pattern_t *mask_pattern, cairo_operator_t op, @@ -631,14 +705,14 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, cairo_surface_attributes_t *ret_src_attr) { cairo_directfb_surface_t *src; - cairo_surface_attributes_t src_attr; + cairo_surface_attributes_t src_attr; cairo_status_t ret; DFBSurfaceBlittingFlags flags; DFBSurfaceBlendFunction sblend; DFBSurfaceBlendFunction dblend; DFBColor color; - if (_directfb_get_operator (op, NULL, &flags, &sblend, &dblend)) + if (_directfb_get_operator (op, &sblend, &dblend)) return CAIRO_INT_STATUS_UNSUPPORTED; if (mask_pattern) { @@ -663,10 +737,9 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, mask_pattern = tmp; *mask_x = tmp_x; *mask_y = tmp_y; - if (sblend == DSBF_ONE) { - flags |= DSBLIT_BLEND_ALPHACHANNEL; + if (sblend == DSBF_ONE) { sblend = DSBF_SRCALPHA; - /* dblend = DSBF_INVSRCALPHA; */ + /*dblend = DSBF_INVSRCALPHA;*/ } } @@ -691,14 +764,12 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, } src = (cairo_directfb_surface_t *)dst->color; - src->dfbsurface->SetColor (src->dfbsurface, - pattern->color.red_short >> 8, - pattern->color.green_short >> 8, - pattern->color.blue_short >> 8, - pattern->color.alpha_short >> 8); - src->dfbsurface->FillRectangle (src->dfbsurface, 0, 0, 1, 1); - - cairo_matrix_init_identity (&src_attr.matrix); + src->dfbsurface->Clear (src->dfbsurface, + pattern->color.red_short >> 8, + pattern->color.green_short >> 8, + pattern->color.blue_short >> 8, + pattern->color.alpha_short >> 8); + src_attr.matrix = src_pattern->matrix; src_attr.extend = CAIRO_EXTEND_NONE; src_attr.filter = CAIRO_FILTER_NEAREST; @@ -712,7 +783,32 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, if (ret) return ret; } - + + if (src->content == CAIRO_CONTENT_COLOR) { + if (sblend == DSBF_SRCALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVSRCALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_SRCALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVSRCALPHA) + dblend = DSBF_ZERO; + } + if (dst->content == CAIRO_CONTENT_COLOR) { + if (sblend == DSBF_DESTALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVDESTALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_DESTALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVDESTALPHA) + dblend = DSBF_ZERO; + } + + flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) + ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL; if (color.a != 0xff) flags |= DSBLIT_BLEND_COLORALPHA; if (color.r != 0xff || color.g != 0xff || color.b != 0xff) @@ -720,7 +816,7 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst, dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); - if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL)) { + if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); } @@ -746,6 +842,30 @@ _directfb_finish_composite (cairo_directfb_surface_t *dst, #endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */ #if DFB_COMPOSITE +static DFBAccelerationMask +_directfb_categorize_operation (cairo_surface_attributes_t *src_attr) +{ + cairo_matrix_t *m = &src_attr->matrix; + + if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) { + if (src_attr->extend != CAIRO_EXTEND_NONE) + return DFXL_NONE; + return DFXL_TEXTRIANGLES; + } + + if (m->xx != 1 || m->yy != 1) { + if (src_attr->extend != CAIRO_EXTEND_NONE) + return DFXL_NONE; + return DFXL_STRETCHBLIT; + } + + if (src_attr->extend != CAIRO_EXTEND_NONE && + src_attr->extend != CAIRO_EXTEND_REPEAT) + return DFXL_NONE; + + return DFXL_BLIT; +} + static cairo_int_status_t _cairo_directfb_surface_composite (cairo_operator_t op, cairo_pattern_t *src_pattern, @@ -758,10 +878,10 @@ _cairo_directfb_surface_composite (cairo_operator_t op, unsigned int height) { cairo_directfb_surface_t *dst = abstract_dst; - cairo_directfb_surface_t *src = NULL; /* hide compiler warning */ + cairo_directfb_surface_t *src; cairo_surface_attributes_t src_attr; - cairo_matrix_t *m; - cairo_status_t ret; + DFBAccelerationMask accel, mask; + cairo_int_status_t ret; D_DEBUG_AT (Cairo_DirectFB, "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p," @@ -775,133 +895,142 @@ _cairo_directfb_surface_composite (cairo_operator_t op, width, height, &src, &src_attr); if (ret) return ret; + + accel = _directfb_categorize_operation (&src_attr); - ret = CAIRO_INT_STATUS_UNSUPPORTED; - - m = &src_attr.matrix; - if (_cairo_matrix_is_integer_translation (m, NULL, NULL)) { - DFBRectangle sr; - - sr.x = src_x + src_attr.x_offset; - sr.y = src_y + src_attr.y_offset; - sr.w = src->width - sr.x; - sr.h = src->height - sr.y; - - if (src_attr.extend == CAIRO_EXTEND_NONE) { - D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n"); - - RUN_CLIPPED( dst, NULL, - dst->dfbsurface->Blit (dst->dfbsurface, - src->dfbsurface, &sr, dst_x, dst_y)); - ret = CAIRO_STATUS_SUCCESS; + dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &mask); + if (!(mask & accel)) { + D_DEBUG_AT (Cairo_DirectFB, "No acceleration (%08x)!\n", accel); + if (accel != DFXL_BLIT) { + _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); + return CAIRO_INT_STATUS_UNSUPPORTED; } - else if (src_attr.extend == CAIRO_EXTEND_REPEAT) { + } + + src_x += src_attr.x_offset; + src_y += src_attr.y_offset; + + switch (accel) { + case DFXL_BLIT: { + DFBRectangle sr; + + sr.x = src_x + _cairo_lround (src_attr.matrix.x0); + sr.y = src_y + _cairo_lround (src_attr.matrix.y0); + sr.w = width; + sr.h = height; + + if (src_attr.extend == CAIRO_EXTEND_NONE) { + D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n"); + + RUN_CLIPPED( dst, NULL, + dst->dfbsurface->Blit (dst->dfbsurface, + src->dfbsurface, &sr, dst_x, dst_y)); + } + else if (src_attr.extend == CAIRO_EXTEND_REPEAT) { + DFBRegion clip; + + clip.x1 = dst_x; + clip.y1 = dst_y; + clip.x2 = dst_x + width - 1; + clip.y2 = dst_y + height - 1; + + D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n"); + + RUN_CLIPPED( dst, &clip, + dst->dfbsurface->TileBlit (dst->dfbsurface, + src->dfbsurface, &sr, dst_x, dst_y)); + } + } break; + + case DFXL_STRETCHBLIT: { + DFBRectangle sr, dr; + double x1, y1, x2, y2; + + TRANSFORM_POINT2X (src_attr.matrix, + src_x, src_y, x1, y1); + TRANSFORM_POINT2X (src_attr.matrix, + src_x+width, src_y+height, x2, y2); + + sr.x = _cairo_lround (x1); + sr.y = _cairo_lround (y1); + sr.w = _cairo_lround (x2-x1); + sr.h = _cairo_lround (y2-y1); + + dr.x = dst_x; + dr.y = dst_y; + dr.w = width; + dr.h = height; + + D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n"); + + RUN_CLIPPED (dst, NULL, + dst->dfbsurface->StretchBlit (dst->dfbsurface, + src->dfbsurface, &sr, &dr)); + } break; + + case DFXL_TEXTRIANGLES: { DFBRegion clip; + DFBVertex v[4]; + float x1, y1, x2, y2; + int w, h; + + if (cairo_matrix_invert (&src_attr.matrix) != CAIRO_STATUS_SUCCESS) { + ret = CAIRO_INT_STATUS_UNSUPPORTED; + break; + } + + x1 = src_attr.x_offset; + y1 = src_attr.y_offset; + x2 = src->width - x1; + y2 = src->height - y1; + + src->dfbsurface->GetSize (src->dfbsurface, &w, &h); + + TRANSFORM_POINT3X (src_attr.matrix, + x1, y1, v[0].x, v[0].y); + v[0].z = 0; + v[0].w = 1; + v[0].s = x1 / w; + v[0].t = y1 / h; + + TRANSFORM_POINT3X (src_attr.matrix, + x2, y1, v[1].x, v[1].y); + v[1].z = 0; + v[1].w = 1; + v[1].s = x2 / w; + v[1].t = y1 / h; + + TRANSFORM_POINT3X (src_attr.matrix, + x2, y2, v[2].x, v[2].y); + v[2].z = 0; + v[2].w = 1; + v[2].s = x2 / w; + v[2].t = y2 / h; + + TRANSFORM_POINT3X (src_attr.matrix, + x1, y2, v[3].x, v[3].y); + v[3].z = 0; + v[3].w = 1; + v[3].s = x1 / w; + v[3].t = y2 / h; clip.x1 = dst_x; clip.y1 = dst_y; clip.x2 = dst_x + width - 1; clip.y2 = dst_y + height - 1; + + D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n"); - D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n"); - - RUN_CLIPPED( dst, &clip, - dst->dfbsurface->TileBlit (dst->dfbsurface, - src->dfbsurface, &sr, dst_x, dst_y)); - ret = CAIRO_STATUS_SUCCESS; - } - } - else if (src_attr.extend == CAIRO_EXTEND_NONE && - cairo_matrix_invert (m) == CAIRO_STATUS_SUCCESS) - { - DFBAccelerationMask accel; - - /* Yet I don't fully understand what these src_x/src_y mean. - * It seems they are X11 specific, so I ignore them for now. - */ - src_x = src_y = 0; - - dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel); - - if (m->xy != 0.0 || m->yx != 0.0) { - if (accel & DFXL_TEXTRIANGLES) { - DFBVertex v[4]; - float w, h; - float x1, y1, x2, y2; - int i; - - w = MAX (src->width, 8); - h = MAX (src->height, 8); - - x1 = src_x + src_attr.x_offset; - y1 = src_y + src_attr.y_offset; - x2 = src->width - x1; - y2 = src->height - y1; - - v[0].x = x1; - v[0].y = y1; - v[0].s = x1/w; - v[0].t = y1/h; - - v[1].x = x2; - v[1].y = y1; - v[1].s = x2/w; - v[1].t = y1/h; - - v[2].x = x2; - v[2].y = y2; - v[2].s = x2/w; - v[2].t = y2/h; - - v[3].x = x1; - v[3].y = y2; - v[3].s = x1/w; - v[3].t = y2/h; - - for (i = 0; i < 4; i++) { - TRANSFORM_POINT (m, v[i].x, v[i].y, v[i].x, v[i].y); - v[i].z = 0; - v[i].w = 1; - } - - D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n"); - - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->TextureTriangles (dst->dfbsurface, + RUN_CLIPPED (dst, &clip, + dst->dfbsurface->TextureTriangles (dst->dfbsurface, src->dfbsurface, v, NULL, 4, DTTF_FAN)); - ret = CAIRO_STATUS_SUCCESS; - } - } - else { - if (accel & DFXL_STRETCHBLIT || - src_attr.filter == CAIRO_FILTER_NEAREST) - { - DFBRectangle sr, dr; - double x1, y1, x2, y2; - - sr.x = src_x + src_attr.x_offset; - sr.y = src_y + src_attr.y_offset; - sr.w = src->width - sr.x; - sr.h = src->height - sr.y; - - TRANSFORM_POINT (m, sr.x, sr.y, x1, y1); - TRANSFORM_POINT (m, sr.x+sr.w, sr.y+sr.h, x2, y2); - - dr.x = _cairo_lround (x1); - dr.y = _cairo_lround (y1); - dr.w = _cairo_lround (x2-x1); - dr.h = _cairo_lround (y2-y1); + } break; - D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n"); + default: + D_BUG ("Unexpected operation"); + break; + } - RUN_CLIPPED (dst, NULL, - dst->dfbsurface->StretchBlit (dst->dfbsurface, - src->dfbsurface, &sr, &dr)); - ret = CAIRO_STATUS_SUCCESS; - } - } - } - _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr); return ret; @@ -910,13 +1039,13 @@ _cairo_directfb_surface_composite (cairo_operator_t op, #if DFB_RECTANGLES static cairo_int_status_t -_cairo_directfb_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int n_rects) +_cairo_directfb_surface_fill_rectangles (void *abstract_surface, + cairo_operator_t op, + const cairo_color_t *color, + cairo_rectangle_int_t *rects, + int n_rects) { - cairo_directfb_surface_t *dst = abstract_surface; + cairo_directfb_surface_t *dst = abstract_surface; DFBSurfaceDrawingFlags flags; DFBSurfaceBlendFunction sblend; DFBSurfaceBlendFunction dblend; @@ -927,19 +1056,44 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface, "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n", __FUNCTION__, dst, op, color, rects, n_rects); - if (_directfb_get_operator (op, &flags, NULL, &sblend, &dblend)) + if (_directfb_get_operator (op, &sblend, &dblend)) return CAIRO_INT_STATUS_UNSUPPORTED; + + if (color->alpha_short >= 0xff00) { + if (sblend == DSBF_SRCALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVSRCALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_SRCALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVSRCALPHA) + dblend = DSBF_ZERO; + } + if (dst->content == CAIRO_CONTENT_COLOR) { + if (sblend == DSBF_DESTALPHA) + sblend = DSBF_ONE; + else if (sblend == DSBF_INVDESTALPHA) + sblend = DSBF_ZERO; + + if (dblend == DSBF_DESTALPHA) + dblend = DSBF_ONE; + else if (dblend == DSBF_INVDESTALPHA) + dblend = DSBF_ZERO; + } + flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND; dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags); if (flags & DSDRAW_BLEND) { dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); } - dst->dfbsurface->SetColor (dst->dfbsurface, color->red_short >> 8, - color->green_short >> 8, - color->blue_short >> 8, - color->alpha_short >> 8 ); + dst->dfbsurface->SetColor (dst->dfbsurface, + color->red_short >> 8, + color->green_short >> 8, + color->blue_short >> 8, + color->alpha_short >> 8 ); for (i = 0; i < n_rects; i++) { r[i].x = rects[i].x; @@ -1108,22 +1262,23 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface, if (region) { cairo_box_int_t *boxes; - int n_boxes, i; - cairo_status_t status; + int n_boxes; + cairo_status_t status; + int i; status = _cairo_region_get_boxes (region, &n_boxes, &boxes); - if (status) - return status; - + if (status) + return status; + if (surface->n_clips != n_boxes) { - if( surface->clips ) + if (surface->clips) free (surface->clips); surface->clips = _cairo_malloc_ab (n_boxes, sizeof(DFBRegion)); if (!surface->clips) { - _cairo_region_boxes_fini (region, boxes); surface->n_clips = 0; - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_region_boxes_fini (region, boxes); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } surface->n_clips = n_boxes; @@ -1150,7 +1305,7 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface, } static cairo_int_status_t -_cairo_directfb_abstract_surface_get_extents (void *abstract_surface, +_cairo_directfb_abstract_surface_get_extents (void *abstract_surface, cairo_rectangle_int_t *rectangle) { cairo_directfb_surface_t *surface = abstract_surface; @@ -1159,55 +1314,20 @@ _cairo_directfb_abstract_surface_get_extents (void *abstract_surfac "%s( surface=%p, rectangle=%p ).\n", __FUNCTION__, surface, rectangle); - if (rectangle) { + if (rectangle) { + if (!surface->local) { + surface->dfbsurface->GetSize (surface->dfbsurface, + &surface->width, &surface->height); + } rectangle->x = 0; rectangle->y = 0; - rectangle->width = surface->width; + rectangle->width = surface->width; rectangle->height = surface->height; } return CAIRO_STATUS_SUCCESS; } -static cairo_status_t -_cairo_directfb_surface_mark_dirty_rectangle (void *abstract_surface, - int x, - int y, - int width, - int height) -{ -#if 0 - cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (Cairo_DirectFB, - "%s( surface=%p, x=%d, y=%d, width=%d, height=%d ).\n", - __FUNCTION__, surface, x, y, width, height); - if( !surface->dirty_region ) - surface->dirty_region = malloc(sizeof(DFBRegion)); - if (!dirty_region) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); -#endif - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_directfb_surface_flush (void *abstract_surface) -{ -#if 0 - cairo_directfb_surface_t *surface = abstract_surface; - - D_DEBUG_AT (Cairo_DirectFB, - "%s( surface=%p ).\n", __FUNCTION__, surface); - - if (surface->surface != surface->buffer) { - surface->surface->SetClip (surface->surface, NULL); - surface->surface->SetBlittingFlags (surface->surface, DSBLIT_NOFX); - surface->surface->Blit (surface->surface, surface->buffer, NULL, 0, 0); - } -#endif - return CAIRO_STATUS_SUCCESS; -} - #if DFB_SHOW_GLYPHS static cairo_directfb_font_cache_t* _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height) @@ -1215,21 +1335,16 @@ _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height) cairo_directfb_font_cache_t *cache; cache = calloc (1, sizeof(cairo_directfb_font_cache_t)); - if (!cache) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } + if (!cache) + return NULL; - cache->dfbsurface = _directfb_buffer_surface_create( dfb, DSPF_A8, width, height); + cache->dfb = dfb; + cache->dfbsurface = _directfb_buffer_surface_create (dfb, + _directfb_argb_font ? DSPF_ARGB : DSPF_A8, width, height); if (!cache->dfbsurface) { free (cache); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; } - - /* dfb->AddRef (dfb); */ - cache->dfb = dfb; - cache->width = width; cache->height = height; @@ -1284,6 +1399,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, switch (img->format) { case CAIRO_FORMAT_A1: case CAIRO_FORMAT_A8: + case CAIRO_FORMAT_ARGB32: break; default: D_DEBUG_AT (Cairo_DirectFB, @@ -1306,7 +1422,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, if (x+img->width > 2048) { x = 0; y = h; - h = 8; + h = 0; } rects[n].x = x; @@ -1321,7 +1437,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, /* Remember glyph location */ rect = malloc (sizeof(DFBRectangle)); if (!rect) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); *rect = rects[n]; scaled_glyph->surface_private = rect; @@ -1346,6 +1462,8 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, return CAIRO_INT_STATUS_NOTHING_TO_DO; h += y; + w = MAX (w, 8); + h = MAX (h, 8); if (cache) { if (cache->width < w || cache->height < h) { @@ -1359,10 +1477,10 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, new_cache = _directfb_allocate_font_cache (surface->dfb, w, h); if (!new_cache) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); new_cache->dfbsurface->Blit (new_cache->dfbsurface, - cache->dfbsurface, NULL, 0, 0); + cache->dfbsurface, NULL, 0, 0); _directfb_destroy_font_cache (cache); scaled_font->surface_private = cache = new_cache; @@ -1373,8 +1491,8 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, "Allocating font cache (%dx%d).\n", w, h); cache = _directfb_allocate_font_cache (surface->dfb, w, h); - if (!cache) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (!cache) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); scaled_font->surface_backend = &cairo_directfb_surface_backend; scaled_font->surface_private = cache; @@ -1385,27 +1503,57 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface, int pitch; if (cache->dfbsurface->Lock (cache->dfbsurface, - DSLF_WRITE, (void *)&data, &pitch)) + DSLF_WRITE, (void *)&data, &pitch)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - + for (i = 0; i < num_chars; i++) { cairo_image_surface_t *img = chars[i]->surface; DFBRectangle *rect = chars[i]->surface_private; - unsigned char *dst = data + rect->y*pitch + rect->x; + unsigned char *dst = data; unsigned char *src = img->data; + int j; + dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x); + if (img->format == CAIRO_FORMAT_A1) { - int j; for (h = rect->h; h; h--) { - for (j = 0; j < rect->w; j++) - dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00; + if (_directfb_argb_font) { + for (j = 0; j < rect->w; j++) + ((uint32_t *)dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0; + } + else { + for (j = 0; j < rect->w; j++) + dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0; + } + dst += pitch; src += img->stride; } } - else { + else if (img->format == CAIRO_FORMAT_A8) { for (h = rect->h; h; h--) { - direct_memcpy (dst, src, rect->w); + if (_directfb_argb_font) { + for (j = 0; j < rect->w; j++) + ((uint32_t *)dst)[j] = src[j] * 0x01010101; + } + else { + direct_memcpy (dst, src, rect->w); + } + + dst += pitch; + src += img->stride; + } + } + else { /* ARGB32 */ + for (h = rect->h; h; h--) { + if (_directfb_argb_font) { + direct_memcpy (dst, src, rect->w<<2); + } + else { + for (j = 0; j < rect->w; j++) + dst[j] = ((uint32_t *)src)[j] >> 24; + } + dst += pitch; src += img->stride; } @@ -1452,15 +1600,13 @@ _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, } } - - static cairo_int_status_t -_cairo_directfb_surface_show_glyphs ( void *abstract_dst, - cairo_operator_t op, - cairo_pattern_t *pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font) +_cairo_directfb_surface_show_glyphs (void *abstract_dst, + cairo_operator_t op, + cairo_pattern_t *pattern, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) { cairo_directfb_surface_t *dst = abstract_dst; cairo_directfb_font_cache_t *cache; @@ -1480,7 +1626,7 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst, if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) return CAIRO_INT_STATUS_UNSUPPORTED; - if (_directfb_get_operator (op, NULL, &flags, &sblend, &dblend) || + if (_directfb_get_operator (op, &sblend, &dblend) || sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1493,18 +1639,20 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst, } color.a = ((cairo_solid_pattern_t *)pattern)->color.alpha_short >> 8; - color.r = ((cairo_solid_pattern_t *)pattern)->color.red_short >> 8; + color.r = ((cairo_solid_pattern_t *)pattern)->color.red_short >> 8; color.g = ((cairo_solid_pattern_t *)pattern)->color.green_short >> 8; - color.b = ((cairo_solid_pattern_t *)pattern)->color.blue_short >> 8; + color.b = ((cairo_solid_pattern_t *)pattern)->color.blue_short >> 8; - flags |= DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE; + flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE; if (color.a != 0xff) flags |= DSBLIT_BLEND_COLORALPHA; - if (sblend == DSBF_ONE) { - sblend = DSBF_SRCALPHA; - if (dblend == DSBF_ZERO) - dblend = DSBF_INVSRCALPHA; + if (!_directfb_argb_font) { + if (sblend == DSBF_ONE) { + sblend = DSBF_SRCALPHA; + if (dblend == DSBF_ZERO) + dblend = DSBF_INVSRCALPHA; + } } dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags); @@ -1524,9 +1672,7 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst, static cairo_bool_t -_cairo_directfb_surface_is_similar (void *surface_a, - void *surface_b, - cairo_content_t content) +_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content) { cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a; cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b; @@ -1560,16 +1706,16 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = { #endif NULL, /* copy_page */ NULL, /* show_page */ - _cairo_directfb_surface_set_clip_region,/*set_clip_region*/ + _cairo_directfb_surface_set_clip_region,/* set_clip_region */ NULL, /* intersect_clip_path */ - _cairo_directfb_abstract_surface_get_extents,/*get_extents*/ + _cairo_directfb_abstract_surface_get_extents,/* get_extents */ NULL, /* old_show_glyphs */ NULL, /* get_font_options */ - _cairo_directfb_surface_flush,/*flush*/ - _cairo_directfb_surface_mark_dirty_rectangle,/*mark_dirty_rectangle*/ + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ #if DFB_SHOW_GLYPHS - _cairo_directfb_surface_scaled_font_fini,/*scaled_font_fini*/ - _cairo_directfb_surface_scaled_glyph_fini,/*scaled_glyph_fini*/ + _cairo_directfb_surface_scaled_font_fini,/* scaled_font_fini */ + _cairo_directfb_surface_scaled_glyph_fini,/* scaled_glyph_fini */ #else NULL, NULL, @@ -1579,47 +1725,61 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = { NULL, /* stroke */ NULL, /* fill */ #if DFB_SHOW_GLYPHS - _cairo_directfb_surface_show_glyphs,/*show_glyphs*/ + _cairo_directfb_surface_show_glyphs,/* show_glyphs */ #else NULL, /* show_glyphs */ #endif NULL, /* snapshot */ - _cairo_directfb_surface_is_similar, - NULL /* reset */ + _cairo_directfb_surface_is_similar, + NULL /* reset */ }; static void cairo_directfb_surface_backend_init (IDirectFB *dfb) { - DFBGraphicsDeviceDescription dsc; - static int done = 0; + static int done = 0; if (done) return; - dfb->GetDeviceDescription (dfb, &dsc); - + if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) { +#if DFB_RECTANGLES + cairo_directfb_surface_backend.fill_rectangles = NULL; +#endif #if DFB_COMPOSITE - if (!(dsc.acceleration_mask & DFXL_BLIT)) cairo_directfb_surface_backend.composite = NULL; #endif - #if DFB_COMPOSITE_TRAPEZOIDS - if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES)) cairo_directfb_surface_backend.composite_trapezoids = NULL; #endif - #if DFB_SHOW_GLYPHS - if (!(dsc.acceleration_mask & DFXL_BLIT) || - !(dsc.blitting_flags & DSBLIT_COLORIZE) || - !(dsc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL)) - { cairo_directfb_surface_backend.scaled_font_fini = NULL; cairo_directfb_surface_backend.scaled_glyph_fini = NULL; cairo_directfb_surface_backend.show_glyphs = NULL; - } #endif + D_DEBUG_AT (Cairo_DirectFB, "Acceleration disabled.\n"); + } + else { + DFBGraphicsDeviceDescription dsc; + + dfb->GetDeviceDescription (dfb, &dsc); + +#if DFB_COMPOSITE + if (!(dsc.acceleration_mask & DFXL_BLIT)) + cairo_directfb_surface_backend.composite = NULL; +#endif + +#if DFB_COMPOSITE_TRAPEZOIDS + if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES)) + cairo_directfb_surface_backend.composite_trapezoids = NULL; +#endif + } + + if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) { + _directfb_argb_font = 1; + D_DEBUG_AT (Cairo_DirectFB, "Using ARGB fonts.\n"); + } done = 1; } @@ -1628,27 +1788,29 @@ cairo_directfb_surface_backend_init (IDirectFB *dfb) cairo_surface_t * cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) { - DFBSurfacePixelFormat format; cairo_directfb_surface_t *surface; + DFBSurfacePixelFormat format; - assert(dfb); - assert(dfb); + D_ASSERT (dfb != NULL); + D_ASSERT (dfbsurface != NULL); + cairo_directfb_surface_backend_init (dfb); surface = calloc (1, sizeof(cairo_directfb_surface_t)); - if (!surface) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - + if (!surface) + return NULL; + + dfbsurface->AddRef (dfbsurface); dfbsurface->GetPixelFormat (dfbsurface, &format); - _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend, - _directfb_format_to_content(format)); - surface->owner = FALSE; + dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height); surface->dfb = dfb; - surface->dfbsurface = dfbsurface; - dfbsurface->GetSize (dfbsurface,&surface->width, &surface->height); - surface->format = directfb_to_cairo_format(format); + surface->dfbsurface = dfbsurface; + surface->format = _directfb_to_cairo_format (format); + surface->content = _directfb_format_to_content (format); + + _cairo_surface_init (&surface->base, + &cairo_directfb_surface_backend, surface->content); + return &surface->base; } diff --git a/gfx/cairo/cairo/src/cairo-directfb.h b/gfx/cairo/cairo/src/cairo-directfb.h index 5b35a443d58d..59653d32283d 100644 --- a/gfx/cairo/cairo/src/cairo-directfb.h +++ b/gfx/cairo/cairo/src/cairo-directfb.h @@ -34,6 +34,16 @@ * Carl D. Worth */ +/* + * Environment variables affecting the backend: + * + * CAIRO_DIRECTFB_NO_ACCEL (boolean) + * if found, disables acceleration at all + * + * CAIRO_DIRECTFB_ARGB_FONT (boolean) + * if found, enables using ARGB fonts instead of A8 + */ + #ifndef CAIRO_DIRECTFB_H #define CAIRO_DIRECTFB_H @@ -46,7 +56,7 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * -cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface); +cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-features.h.in b/gfx/cairo/cairo/src/cairo-features.h.in index 609f8edd567e..230ffadf3c55 100644 --- a/gfx/cairo/cairo/src/cairo-features.h.in +++ b/gfx/cairo/cairo/src/cairo-features.h.in @@ -53,9 +53,9 @@ #define CAIRO_VERSION_MAJOR 1 #define CAIRO_VERSION_MINOR 5 -#define CAIRO_VERSION_MICRO 3 +#define CAIRO_VERSION_MICRO 5 -#define CAIRO_VERSION_STRING "1.5.3" +#define CAIRO_VERSION_STRING "1.5.5" @PS_SURFACE_FEATURE@ diff --git a/gfx/cairo/cairo/src/cairo-fixed-private.h b/gfx/cairo/cairo/src/cairo-fixed-private.h index 7a08ebd8ce57..626c02a0b537 100644 --- a/gfx/cairo/cairo/src/cairo-fixed-private.h +++ b/gfx/cairo/cairo/src/cairo-fixed-private.h @@ -37,39 +37,11 @@ #ifndef CAIRO_FIXED_PRIVATE_H #define CAIRO_FIXED_PRIVATE_H +#include "cairo-fixed-type-private.h" + #include "cairo-wideint-private.h" -/* - * Fixed-point configuration - */ - -typedef int32_t cairo_fixed_16_16_t; -typedef cairo_int64_t cairo_fixed_32_32_t; -typedef cairo_int64_t cairo_fixed_48_16_t; -typedef cairo_int128_t cairo_fixed_64_64_t; -typedef cairo_int128_t cairo_fixed_96_32_t; - -/* Eventually, we should allow changing this, but I think - * there are some assumptions in the tesselator about the - * size of a fixed type. For now, it must be 32. - */ -#define CAIRO_FIXED_BITS 32 - -/* The number of fractional bits. Changing this involves - * making sure that you compute a double-to-fixed magic number. - * (see below). - */ -#define CAIRO_FIXED_FRAC_BITS 8 - -/* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */ -typedef int32_t cairo_fixed_t; - -/* An unsigned type of the same size as cairo_fixed_t */ -typedef uint32_t cairo_fixed_unsigned_t; - -/* - * No configurable bits below this. - */ +/* Implementation */ #if (CAIRO_FIXED_BITS != 32) # error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type. diff --git a/gfx/cairo/cairo/src/cairo-fixed-type-private.h b/gfx/cairo/cairo/src/cairo-fixed-type-private.h new file mode 100644 index 000000000000..6ffc1846ba30 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-fixed-type-private.h @@ -0,0 +1,70 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ +/* Cairo - a vector graphics library with display and print output + * + * Copyright © 2007 Mozilla Corporation + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.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/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Mozilla Corporation + * + * Contributor(s): + * Vladimir Vukicevic + */ + +#ifndef CAIRO_FIXED_TYPE_PRIVATE_H +#define CAIRO_FIXED_TYPE_PRIVATE_H + +#include "cairo-wideint-type-private.h" + +/* + * Fixed-point configuration + */ + +typedef int32_t cairo_fixed_16_16_t; +typedef cairo_int64_t cairo_fixed_32_32_t; +typedef cairo_int64_t cairo_fixed_48_16_t; +typedef cairo_int128_t cairo_fixed_64_64_t; +typedef cairo_int128_t cairo_fixed_96_32_t; + +/* Eventually, we should allow changing this, but I think + * there are some assumptions in the tesselator about the + * size of a fixed type. For now, it must be 32. + */ +#define CAIRO_FIXED_BITS 32 + +/* The number of fractional bits. Changing this involves + * making sure that you compute a double-to-fixed magic number. + * (see below). + */ +#define CAIRO_FIXED_FRAC_BITS 8 + +/* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */ +typedef int32_t cairo_fixed_t; + +/* An unsigned type of the same size as cairo_fixed_t */ +typedef uint32_t cairo_fixed_unsigned_t; + +#endif /* CAIRO_FIXED_TYPE_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-font-face.c b/gfx/cairo/cairo/src/cairo-font-face.c index f7294764a31a..b944534b98d0 100644 --- a/gfx/cairo/cairo/src/cairo-font-face.c +++ b/gfx/cairo/cairo/src/cairo-font-face.c @@ -476,9 +476,11 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face if (font_face->base.status) return font_face->base.status; - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) - return status; + if (options != NULL) { + status = cairo_font_options_status ((cairo_font_options_t *) options); + if (status) + return status; + } return _cairo_font_face_set_error (&font_face->base, backend->create_toy (font_face, diff --git a/gfx/cairo/cairo/src/cairo-font-options.c b/gfx/cairo/cairo/src/cairo-font-options.c index c5d5c12b578a..70057903892d 100644 --- a/gfx/cairo/cairo/src/cairo-font-options.c +++ b/gfx/cairo/cairo/src/cairo-font-options.c @@ -52,7 +52,7 @@ static const cairo_font_options_t _cairo_font_options_nil = { void _cairo_font_options_init_default (cairo_font_options_t *options) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) return; options->antialias = CAIRO_ANTIALIAS_DEFAULT; @@ -65,10 +65,13 @@ void _cairo_font_options_init_copy (cairo_font_options_t *options, const cairo_font_options_t *other) { - options->antialias = other->antialias; - options->subpixel_order = other->subpixel_order; - options->hint_style = other->hint_style; - options->hint_metrics = other->hint_metrics; + if (other != NULL) { + options->antialias = other->antialias; + options->subpixel_order = other->subpixel_order; + options->hint_style = other->hint_style; + options->hint_metrics = other->hint_metrics; + } else + _cairo_font_options_init_default (options); } /** @@ -91,7 +94,7 @@ cairo_font_options_create (void) options = malloc (sizeof (cairo_font_options_t)); if (!options) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_options_t *)&_cairo_font_options_nil; + return (cairo_font_options_t *) &_cairo_font_options_nil; } _cairo_font_options_init_default (options); @@ -118,13 +121,16 @@ cairo_font_options_copy (const cairo_font_options_t *original) { cairo_font_options_t *options; - if (original == &_cairo_font_options_nil) - return (cairo_font_options_t *)&_cairo_font_options_nil; + if (original != NULL && + cairo_font_options_status ((cairo_font_options_t *) original)) + { + return (cairo_font_options_t *) &_cairo_font_options_nil; + } options = malloc (sizeof (cairo_font_options_t)); if (!options) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_options_t *)&_cairo_font_options_nil; + return (cairo_font_options_t *) &_cairo_font_options_nil; } _cairo_font_options_init_copy (options, original); @@ -142,7 +148,7 @@ cairo_font_options_copy (const cairo_font_options_t *original) void cairo_font_options_destroy (cairo_font_options_t *options) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) return; free (options); @@ -161,7 +167,9 @@ slim_hidden_def (cairo_font_options_destroy); cairo_status_t cairo_font_options_status (cairo_font_options_t *options) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (options == NULL) + return CAIRO_STATUS_NULL_POINTER; + else if (options == (cairo_font_options_t *) &_cairo_font_options_nil) return CAIRO_STATUS_NO_MEMORY; else return CAIRO_STATUS_SUCCESS; @@ -182,7 +190,11 @@ void cairo_font_options_merge (cairo_font_options_t *options, const cairo_font_options_t *other) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) + return; + + /* A NULL other maps to the defaults and would not overwrite options */ + if (cairo_font_options_status ((cairo_font_options_t *) other)) return; if (other->antialias != CAIRO_ANTIALIAS_DEFAULT) @@ -209,6 +221,14 @@ cairo_bool_t cairo_font_options_equal (const cairo_font_options_t *options, const cairo_font_options_t *other) { + if (options == NULL) + options = &_cairo_font_options_nil; + if (other == NULL) + other = &_cairo_font_options_nil; + + if (options == other) + return TRUE; + return (options->antialias == other->antialias && options->subpixel_order == other->subpixel_order && options->hint_style == other->hint_style && @@ -231,6 +251,9 @@ slim_hidden_def (cairo_font_options_equal); unsigned long cairo_font_options_hash (const cairo_font_options_t *options) { + if (options == NULL) + options = &_cairo_font_options_nil; + return ((options->antialias) | (options->subpixel_order << 4) | (options->hint_style << 8) | @@ -250,7 +273,7 @@ void cairo_font_options_set_antialias (cairo_font_options_t *options, cairo_antialias_t antialias) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) return; options->antialias = antialias; @@ -268,6 +291,9 @@ slim_hidden_def (cairo_font_options_set_antialias); cairo_antialias_t cairo_font_options_get_antialias (const cairo_font_options_t *options) { + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_ANTIALIAS_DEFAULT; + return options->antialias; } @@ -286,7 +312,7 @@ void cairo_font_options_set_subpixel_order (cairo_font_options_t *options, cairo_subpixel_order_t subpixel_order) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) return; options->subpixel_order = subpixel_order; @@ -305,6 +331,9 @@ slim_hidden_def (cairo_font_options_set_subpixel_order); cairo_subpixel_order_t cairo_font_options_get_subpixel_order (const cairo_font_options_t *options) { + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_SUBPIXEL_ORDER_DEFAULT; + return options->subpixel_order; } @@ -322,7 +351,7 @@ void cairo_font_options_set_hint_style (cairo_font_options_t *options, cairo_hint_style_t hint_style) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) return; options->hint_style = hint_style; @@ -341,6 +370,9 @@ slim_hidden_def (cairo_font_options_set_hint_style); cairo_hint_style_t cairo_font_options_get_hint_style (const cairo_font_options_t *options) { + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_HINT_STYLE_DEFAULT; + return options->hint_style; } @@ -358,7 +390,7 @@ void cairo_font_options_set_hint_metrics (cairo_font_options_t *options, cairo_hint_metrics_t hint_metrics) { - if (options == (cairo_font_options_t *)&_cairo_font_options_nil) + if (cairo_font_options_status (options)) return; options->hint_metrics = hint_metrics; @@ -377,5 +409,8 @@ slim_hidden_def (cairo_font_options_set_hint_metrics); cairo_hint_metrics_t cairo_font_options_get_hint_metrics (const cairo_font_options_t *options) { + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_HINT_METRICS_DEFAULT; + return options->hint_metrics; } diff --git a/gfx/cairo/cairo/src/cairo-freelist-private.h b/gfx/cairo/cairo/src/cairo-freelist-private.h index 7e2036c23b02..0d021270d853 100644 --- a/gfx/cairo/cairo/src/cairo-freelist-private.h +++ b/gfx/cairo/cairo/src/cairo-freelist-private.h @@ -22,8 +22,7 @@ #ifndef CAIRO_FREELIST_H #define CAIRO_FREELIST_H -#include "cairoint.h" -#include +#include "cairo-types-private.h" /* Opaque implementation types. */ typedef struct _cairo_freelist cairo_freelist_t; diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c index ad1d994e875e..a3e9df6b92f0 100644 --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -1365,7 +1365,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret) if (!hinting) { ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; } -#endif /* FC_FHINT_STYLE */ +#endif /* FC_HINT_STYLE */ } else { ft_options.base.antialias = CAIRO_ANTIALIAS_NONE; } @@ -1467,6 +1467,8 @@ _cairo_ft_options_merge (cairo_ft_options_t *options, options->load_flags = load_flags | load_target; options->extra_flags = other->extra_flags; + if (options->base.hint_metrics != CAIRO_HINT_METRICS_OFF) + options->extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS; } static cairo_status_t @@ -1497,9 +1499,6 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, _cairo_unscaled_font_reference (&unscaled->base); scaled_font->unscaled = unscaled; - if (options->hint_metrics != CAIRO_HINT_METRICS_OFF) - ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS; - _cairo_font_options_init_copy (&scaled_font->ft_options.base, options); _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options); @@ -1508,6 +1507,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, font_matrix, ctm, options, &cairo_ft_scaled_font_backend); if (status) { + _cairo_unscaled_font_destroy (&unscaled->base); free (scaled_font); goto FAIL; } @@ -1515,34 +1515,11 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, status = _cairo_ft_unscaled_font_set_scale (unscaled, &scaled_font->base.scale); if (status) { + _cairo_unscaled_font_destroy (&unscaled->base); free (scaled_font); goto FAIL; } - /* - * Force non-AA drawing when using a bitmap strike that - * won't be resampled due to non-scaling transform - */ - if (!unscaled->have_shape && - (scaled_font->ft_options.load_flags & FT_LOAD_NO_BITMAP) == 0 && - scaled_font->ft_options.base.antialias != CAIRO_ANTIALIAS_NONE && - (face->face_flags & FT_FACE_FLAG_FIXED_SIZES)) - { - int i; - FT_Size_Metrics *size_metrics = &face->size->metrics; - - for (i = 0; i < face->num_fixed_sizes; i++) - { - FT_Bitmap_Size *bitmap_size = &face->available_sizes[i]; - - if (bitmap_size->x_ppem == size_metrics->x_ppem * 64 && - bitmap_size->y_ppem == size_metrics->y_ppem * 64) - { - scaled_font->ft_options.base.antialias = CAIRO_ANTIALIAS_NONE; - break; - } - } - } metrics = &face->size->metrics; @@ -1670,7 +1647,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, cairo_matrix_multiply (&scale, font_matrix, ctm); _compute_transform (&sf, &scale); - if (! FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale)) { + if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FREE_PATTERN; } @@ -1680,9 +1657,11 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, goto FREE_PATTERN; } - status = _cairo_ft_font_options_substitute (font_options, pattern); - if (status) - goto FREE_PATTERN; + if (font_options != NULL) { + status = _cairo_ft_font_options_substitute (font_options, pattern); + if (status) + goto FREE_PATTERN; + } FcDefaultSubstitute (pattern); @@ -2170,7 +2149,7 @@ _cairo_ft_load_truetype_table (void *abstract_font, return status; } -static void +static cairo_int_status_t _cairo_ft_map_glyphs_to_unicode (void *abstract_font, cairo_scaled_font_subset_t *font_subset) { @@ -2184,7 +2163,7 @@ _cairo_ft_map_glyphs_to_unicode (void *abstract_font, face = _cairo_ft_unscaled_font_lock_face (unscaled); if (!face) - return; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); count = font_subset->num_glyphs; charcode = FT_Get_First_Char( face, &glyph); @@ -2197,9 +2176,11 @@ _cairo_ft_map_glyphs_to_unicode (void *abstract_font, break; } } - charcode = FT_Get_Next_Char(face, charcode, &glyph); + charcode = FT_Get_Next_Char (face, charcode, &glyph); } _cairo_ft_unscaled_font_unlock_face (unscaled); + + return CAIRO_STATUS_SUCCESS; } const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { @@ -2466,6 +2447,9 @@ void cairo_ft_font_options_substitute (const cairo_font_options_t *options, FcPattern *pattern) { + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return; + _cairo_ft_font_options_substitute (options, pattern); } diff --git a/gfx/cairo/cairo/src/cairo-glitz-surface.c b/gfx/cairo/cairo/src/cairo-glitz-surface.c index eb68b4345950..51448954a7f2 100644 --- a/gfx/cairo/cairo/src/cairo-glitz-surface.c +++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c @@ -88,20 +88,16 @@ _cairo_glitz_surface_create_similar (void *abstract_src, gformat = glitz_find_standard_format (drawable, _glitz_format_from_content (content)); - if (!gformat) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (!gformat) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); surface = glitz_surface_create (drawable, gformat, width <= 0 ? 1 : width, height <= 0 ? 1 : height, 0, NULL); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); crsurface = cairo_glitz_surface_create (surface); @@ -150,36 +146,39 @@ _CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format) return FALSE; } -static glitz_box_t * -_cairo_glitz_get_boxes_from_region (cairo_region_t *region, int *nboxes) +static cairo_status_t +_cairo_glitz_get_boxes_from_region (cairo_region_t *region, glitz_box_t **boxes, int *nboxes) { cairo_box_int_t *cboxes; - glitz_box_t *gboxes; + cairo_status_t status; int n, i; - if (_cairo_region_get_boxes (region, &n, &cboxes) != CAIRO_STATUS_SUCCESS) - return NULL; + status = _cairo_region_get_boxes (region, &n, &cboxes); + if (status) + return status; - *nboxes = n; - if (n == 0) - return NULL; + if (n == 0) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto done; + } - gboxes = _cairo_malloc_ab (n, sizeof(glitz_box_t)); - if (gboxes == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - goto done; + *boxes = _cairo_malloc_ab (n, sizeof(glitz_box_t)); + if (*boxes == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto done; } for (i = 0; i < n; i++) { - gboxes[i].x1 = cboxes[i].p1.x; - gboxes[i].y1 = cboxes[i].p1.y; - gboxes[i].x2 = cboxes[i].p2.x; - gboxes[i].y2 = cboxes[i].p2.y; + (*boxes)[i].x1 = cboxes[i].p1.x; + (*boxes)[i].y1 = cboxes[i].p1.y; + (*boxes)[i].x2 = cboxes[i].p2.x; + (*boxes)[i].y2 = cboxes[i].p2.y; } + *nboxes = n; done: _cairo_region_boxes_fini (region, cboxes); - return gboxes; + return status; } static cairo_status_t @@ -296,12 +295,13 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface, /* restore the clip, if any */ if (surface->has_clip) { glitz_box_t *box; + cairo_status_t status; int n; - box = _cairo_glitz_get_boxes_from_region (&surface->clip, &n); - if (box == NULL && n != 0) { + status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n); + if (status) { free (pixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return status; } glitz_surface_set_clip_region (surface->surface, 0, 0, box, n); @@ -1305,9 +1305,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, { if (data_size < size) { + void *p; data_size = size; - data = realloc (data, data_size); - if (!data) + p = realloc (data, data_size); + if (!p) { _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); @@ -1315,6 +1316,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, _cairo_pattern_fini (&tmp_src_pattern.base); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } + data = p; if (buffer) glitz_buffer_destroy (buffer); @@ -1465,11 +1467,11 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface, return status; } - box = _cairo_glitz_get_boxes_from_region (&surface->clip, &n); - if (box == NULL && n != 0) { + status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n); + if (status) { _cairo_region_fini (&surface->clip); surface->has_clip = FALSE; - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return status; } glitz_surface_set_clip_region (surface->surface, 0, 0, box, n); @@ -2454,13 +2456,11 @@ cairo_glitz_surface_create (glitz_surface_t *surface) glitz_format_t *format; if (surface == NULL) - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); crsurface = malloc (sizeof (cairo_glitz_surface_t)); - if (crsurface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (crsurface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); format = glitz_surface_get_format (surface); _cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend, diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index c2ab8a283fc2..a00a52c12da3 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -35,11 +35,19 @@ * Carl D. Worth */ +#define _GNU_SOURCE + #include "cairoint.h" #include "cairo-clip-private.h" #include "cairo-gstate-private.h" +#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE +#define ISFINITE(x) isfinite (x) +#else +#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ +#endif + static cairo_status_t _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other); @@ -623,7 +631,7 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty) { cairo_matrix_t tmp; - if (! (tx * tx >= 0.) || ! (ty * ty >= 0.)) /* check for NaNs */ + if (! ISFINITE (tx) || ! ISFINITE (ty)) return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); _cairo_gstate_unset_scaled_font (gstate); @@ -631,6 +639,10 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty) cairo_matrix_init_translate (&tmp, tx, ty); cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); + /* paranoid check against gradual numerical instability */ + if (! _cairo_matrix_is_invertible (&gstate->ctm)) + return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); + cairo_matrix_init_translate (&tmp, -tx, -ty); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); @@ -644,7 +656,7 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy) if (sx * sy == 0.) /* either sx or sy is 0, or det == 0 due to underflow */ return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - if (! (sx * sx > 0.) || ! (sy * sy > 0.)) /* check for NaNs */ + if (! ISFINITE (sx) || ! ISFINITE (sy)) return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); _cairo_gstate_unset_scaled_font (gstate); @@ -652,6 +664,10 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy) cairo_matrix_init_scale (&tmp, sx, sy); cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); + /* paranoid check against gradual numerical instability */ + if (! _cairo_matrix_is_invertible (&gstate->ctm)) + return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); + cairo_matrix_init_scale (&tmp, 1/sx, 1/sy); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); @@ -666,7 +682,7 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle) if (angle == 0.) return CAIRO_STATUS_SUCCESS; - if (! (angle * angle >= 0.)) /* check for NaNs */ + if (! ISFINITE (angle)) return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); _cairo_gstate_unset_scaled_font (gstate); @@ -674,6 +690,10 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle) cairo_matrix_init_rotate (&tmp, angle); cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); + /* paranoid check against gradual numerical instability */ + if (! _cairo_matrix_is_invertible (&gstate->ctm)) + return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); + cairo_matrix_init_rotate (&tmp, -angle); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); @@ -687,16 +707,20 @@ _cairo_gstate_transform (cairo_gstate_t *gstate, cairo_matrix_t tmp; cairo_status_t status; - _cairo_gstate_unset_scaled_font (gstate); - tmp = *matrix; - cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm); - status = cairo_matrix_invert (&tmp); if (status) return status; + + _cairo_gstate_unset_scaled_font (gstate); + + cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm); cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp); + /* paranoid check against gradual numerical instability */ + if (! _cairo_matrix_is_invertible (&gstate->ctm)) + return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); + return CAIRO_STATUS_SUCCESS; } @@ -706,14 +730,15 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate, { cairo_status_t status; + if (! _cairo_matrix_is_invertible (matrix)) + return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); + _cairo_gstate_unset_scaled_font (gstate); gstate->ctm = *matrix; - gstate->ctm_inverse = *matrix; status = cairo_matrix_invert (&gstate->ctm_inverse); - if (status) - return status; + assert (status == CAIRO_STATUS_SUCCESS); return CAIRO_STATUS_SUCCESS; } @@ -793,6 +818,17 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate) } */ +void +_cairo_gstate_path_extents (cairo_gstate_t *gstate, + cairo_path_fixed_t *path, + double *x1, double *y1, + double *x2, double *y2) +{ + _cairo_path_fixed_bounds (path, x1, y1, x2, y2, gstate->tolerance); + + _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL); +} + static cairo_status_t _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern, @@ -1132,9 +1168,7 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate, { cairo_box_t extents; - _cairo_traps_extents (traps, &extents); - - if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) { + if (traps->num_traps == 0) { /* no traps, so we actually won't draw anything */ if (x1) *x1 = 0.0; @@ -1145,6 +1179,8 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate, if (y2) *y2 = 0.0; } else { + _cairo_traps_extents (traps, &extents); + if (x1) *x1 = _cairo_fixed_to_double (extents.p1.x); if (y1) @@ -1340,7 +1376,7 @@ _cairo_gstate_set_font_options (cairo_gstate_t *gstate, { _cairo_gstate_unset_scaled_font (gstate); - gstate->font_options = *options; + _cairo_font_options_init_copy (&gstate->font_options, options); } void @@ -1575,7 +1611,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate, return cairo_scaled_font_status (gstate->scaled_font); } -#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t))) cairo_status_t _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, const cairo_glyph_t *glyphs, @@ -1584,7 +1619,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, cairo_status_t status; cairo_pattern_union_t source_pattern; cairo_glyph_t *transformed_glyphs; - cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN]; + cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; if (gstate->source->status) return gstate->source->status; @@ -1597,7 +1632,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, if (status) return status; - if (num_glyphs <= STACK_GLYPHS_LEN) { + if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) { transformed_glyphs = stack_transformed_glyphs; } else { transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t)); @@ -1636,13 +1671,13 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, { cairo_status_t status; cairo_glyph_t *transformed_glyphs; - cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN]; + cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; - if (num_glyphs < STACK_GLYPHS_LEN) + if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs)) transformed_glyphs = stack_transformed_glyphs; else transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t)); @@ -1663,7 +1698,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, return status; } -#undef STACK_GLYPHS_LEN cairo_status_t _cairo_gstate_set_antialias (cairo_gstate_t *gstate, diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c index ec3477b32d3b..5f31d93bce39 100644 --- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -37,101 +37,6 @@ #include "cairoint.h" -static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = { - { - &cairo_image_surface_backend, /* backend */ - CAIRO_SURFACE_TYPE_IMAGE, - CAIRO_CONTENT_COLOR, - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - CAIRO_STATUS_INVALID_FORMAT, /* status */ - FALSE, /* finished */ - { 0, /* size */ - 0, /* num_elements */ - 0, /* element_size */ - NULL, /* elements */ - }, /* user_data */ - { 1.0, 0.0, - 0.0, 1.0, - 0.0, 0.0 - }, /* device_transform */ - { 1.0, 0.0, - 0.0, 1.0, - 0.0, 0.0 - }, /* device_transform_inverse */ - 0.0, /* x_resolution */ - 0.0, /* y_resolution */ - 0.0, /* x_fallback_resolution */ - 0.0, /* y_fallback_resolution */ - NULL, /* clip */ - 0, /* next_clip_serial */ - 0, /* current_clip_serial */ - FALSE, /* is_snapshot */ - FALSE, /* has_font_options */ - { CAIRO_ANTIALIAS_DEFAULT, - CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_HINT_STYLE_DEFAULT, - CAIRO_HINT_METRICS_DEFAULT - } /* font_options */ - }, /* base */ - PIXMAN_a8r8g8b8, /* pixman_format */ - CAIRO_FORMAT_ARGB32, /* format */ - NULL, /* data */ - FALSE, /* owns_data */ - FALSE, /* has_clip */ - 0, /* width */ - 0, /* height */ - 0, /* stride */ - 0, /* depth */ - NULL /* pixman_image */ -}; -static const cairo_image_surface_t _cairo_image_surface_nil_invalid_content = { - { - &cairo_image_surface_backend, /* backend */ - CAIRO_SURFACE_TYPE_IMAGE, - CAIRO_CONTENT_COLOR, - CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ - CAIRO_STATUS_INVALID_CONTENT, /* status */ - FALSE, /* finished */ - { 0, /* size */ - 0, /* num_elements */ - 0, /* element_size */ - NULL, /* elements */ - }, /* user_data */ - { 1.0, 0.0, - 0.0, 1.0, - 0.0, 0.0 - }, /* device_transform */ - { 1.0, 0.0, - 0.0, 1.0, - 0.0, 0.0 - }, /* device_transform_inverse */ - 0.0, /* x_resolution */ - 0.0, /* y_resolution */ - 0.0, /* x_fallback_resolution */ - 0.0, /* y_fallback_resolution */ - NULL, /* clip */ - 0, /* next_clip_serial */ - 0, /* current_clip_serial */ - FALSE, /* is_snapshot */ - FALSE, /* has_font_options */ - { CAIRO_ANTIALIAS_DEFAULT, - CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_HINT_STYLE_DEFAULT, - CAIRO_HINT_METRICS_DEFAULT - } /* font_options */ - }, /* base */ - PIXMAN_a8r8g8b8, /* pixman_format */ - CAIRO_FORMAT_ARGB32, /* format */ - NULL, /* data */ - FALSE, /* owns_data */ - FALSE, /* has_clip */ - 0, /* width */ - 0, /* height */ - 0, /* stride */ - 0, /* depth */ - NULL /* pixman_image */ -}; - static cairo_format_t _cairo_format_from_pixman_format (pixman_format_code_t pixman_format) { @@ -213,10 +118,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, cairo_image_surface_t *surface; surface = malloc (sizeof (cairo_image_surface_t)); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_image_surface_backend, _cairo_content_from_pixman_format (pixman_format)); @@ -399,7 +302,7 @@ _cairo_image_surface_create_with_masks (unsigned char *data, static pixman_format_code_t _cairo_format_to_pixman_format_code (cairo_format_t format) { - int ret = 0; + pixman_format_code_t ret; switch (format) { case CAIRO_FORMAT_A1: ret = PIXMAN_a1; @@ -415,7 +318,6 @@ _cairo_format_to_pixman_format_code (cairo_format_t format) ret = PIXMAN_a8r8g8b8; break; } - assert (ret); return ret; } @@ -432,16 +334,13 @@ _cairo_image_surface_create_with_pixman_format (unsigned char *data, pixman_image = pixman_image_create_bits (pixman_format, width, height, (uint32_t *) data, stride); - if (pixman_image == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (pixman_image == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); surface = _cairo_image_surface_create_for_pixman_image (pixman_image, pixman_format); - if (cairo_surface_status (surface)) { + if (cairo_surface_status (surface)) pixman_image_unref (pixman_image); - } return surface; } @@ -473,10 +372,8 @@ cairo_image_surface_create (cairo_format_t format, { pixman_format_code_t pixman_format; - if (! CAIRO_FORMAT_VALID (format)) { - _cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format; - } + if (! CAIRO_FORMAT_VALID (format)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); pixman_format = _cairo_format_to_pixman_format_code (format); @@ -490,10 +387,8 @@ _cairo_image_surface_create_with_content (cairo_content_t content, int width, int height) { - if (! CAIRO_CONTENT_VALID (content)) { - _cairo_error_throw (CAIRO_STATUS_INVALID_CONTENT); - return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_content; - } + if (! CAIRO_CONTENT_VALID (content)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); return cairo_image_surface_create (_cairo_format_from_content (content), width, height); @@ -541,10 +436,8 @@ cairo_image_surface_create_for_data (unsigned char *data, /* XXX pixman does not support images with arbitrary strides and * attempting to create such surfaces will failure but we will interpret * such failure as CAIRO_STATUS_NO_MEMORY. */ - if (! CAIRO_FORMAT_VALID (format) || stride % sizeof (uint32_t) != 0) { - _cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format; - } + if (! CAIRO_FORMAT_VALID (format) || stride % sizeof (uint32_t) != 0) + return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_INVALID_FORMAT)); pixman_format = _cairo_format_to_pixman_format_code (format); @@ -560,10 +453,8 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data, int height, int stride) { - if (! CAIRO_CONTENT_VALID (content)) { - _cairo_error_throw (CAIRO_STATUS_INVALID_CONTENT); - return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_content; - } + if (! CAIRO_CONTENT_VALID (content)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); return cairo_image_surface_create_for_data (data, _cairo_format_from_content (content), @@ -724,6 +615,24 @@ _cairo_content_from_format (cairo_format_t format) return CAIRO_CONTENT_COLOR_ALPHA; } +cairo_private cairo_format_t +_cairo_format_width (cairo_format_t format) +{ + switch (format) { + case CAIRO_FORMAT_ARGB32: + return 32; + case CAIRO_FORMAT_RGB24: + return 24; + case CAIRO_FORMAT_A8: + return 8; + case CAIRO_FORMAT_A1: + return 1; + default: + ASSERT_NOT_REACHED; + return 0; + } +} + static cairo_surface_t * _cairo_image_surface_create_similar (void *abstract_src, cairo_content_t content, @@ -1034,8 +943,6 @@ _cairo_image_surface_composite (cairo_operator_t op, return status; } -#define STACK_RECTS_LEN (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_rectangle16_t)) - static cairo_int_status_t _cairo_image_surface_fill_rectangles (void *abstract_surface, cairo_operator_t op, @@ -1046,7 +953,7 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface, cairo_image_surface_t *surface = abstract_surface; pixman_color_t pixman_color; - pixman_rectangle16_t stack_rects[STACK_RECTS_LEN]; + pixman_rectangle16_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (pixman_rectangle16_t)]; pixman_rectangle16_t *pixman_rects = stack_rects; int i; @@ -1085,10 +992,6 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface, return status; } -#undef STACK_RECTS_LEN - -#define STACK_TRAPS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_trapezoid_t))) - static cairo_int_status_t _cairo_image_surface_composite_trapezoids (cairo_operator_t op, cairo_pattern_t *pattern, @@ -1110,7 +1013,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, pixman_image_t *mask; pixman_format_code_t format; uint32_t *mask_data; - pixman_trapezoid_t stack_traps[STACK_TRAPS_LEN]; + pixman_trapezoid_t stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)]; pixman_trapezoid_t *pixman_traps = stack_traps; int mask_stride; int mask_bpp; @@ -1179,7 +1082,6 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, case CAIRO_ANTIALIAS_NONE: format = PIXMAN_a1; ret = 1; - assert (ret); mask_stride = ((width + 31) / 8) & ~0x03; mask_bpp = 1; break; @@ -1189,7 +1091,6 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, default: format = PIXMAN_a8; ret = 1; - assert (ret); mask_stride = (width + 3) & ~3; mask_bpp = 8; break; @@ -1244,8 +1145,6 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op, return status; } -#undef STACK_TRAPS_LEN - cairo_int_status_t _cairo_image_surface_set_clip_region (void *abstract_surface, cairo_region_t *region) @@ -1372,7 +1271,7 @@ _cairo_image_surface_clone (cairo_image_surface_t *surface, if (status) { cairo_surface_destroy (&clone->base); - return (cairo_image_surface_t *) &_cairo_surface_nil; + return (cairo_image_surface_t *) _cairo_surface_create_in_error (status); } return clone; diff --git a/gfx/cairo/cairo/src/cairo-matrix.c b/gfx/cairo/cairo/src/cairo-matrix.c index 00c2d486685f..c3578a298b28 100644 --- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -38,6 +38,12 @@ #include "cairoint.h" +#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE +#define ISFINITE(x) isfinite (x) +#else +#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ +#endif + static void _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar); @@ -475,8 +481,7 @@ cairo_matrix_invert (cairo_matrix_t *matrix) if (det == 0) return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); - /* this weird construct is for detecting NaNs */ - if (! (det * det > 0.)) + if (! ISFINITE (det)) return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); _cairo_matrix_compute_adjoint (matrix); @@ -493,7 +498,7 @@ _cairo_matrix_is_invertible (const cairo_matrix_t *matrix) _cairo_matrix_compute_determinant (matrix, &det); - return det != 0. && det * det > 0.; + return det != 0. && ISFINITE (det); } void @@ -517,6 +522,8 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix, _cairo_matrix_compute_determinant (matrix, &det); + assert (ISFINITE (det)); + if (det == 0) { *sx = *sy = 0; @@ -746,6 +753,10 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, *pixman_transform = pixman_identity_transform; } else { + cairo_matrix_t inv = *matrix; + double x = 0, y = 0; + pixman_vector_t vector; + pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx); pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy); pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0); @@ -757,5 +768,36 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix, pixman_transform->matrix[2][0] = 0; pixman_transform->matrix[2][1] = 0; pixman_transform->matrix[2][2] = 1 << 16; + + /* The conversion above breaks cairo's translation invariance: + * a translation of (a, b) in device space translates to + * a translation of (xx * a + xy * b, yx * a + yy * b) + * for cairo, while pixman uses rounded versions of xx ... yy. + * This error increases as a and b get larger. + * + * To compensate for this, we fix the point (0, 0) in pattern + * space and adjust pixman's transform to agree with cairo's at + * that point. */ + + /* Note: If we can't invert the transformation, skip the adjustment. */ + if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS) + return; + + /* find the device space coordinate that maps to (0, 0) */ + cairo_matrix_transform_point (&inv, &x, &y); + + /* transform the resulting device space coordinate back + * to the pattern space, using pixman's transform */ + vector.vector[0] = _cairo_fixed_16_16_from_double (x); + vector.vector[1] = _cairo_fixed_16_16_from_double (y); + vector.vector[2] = 1 << 16; + + if (!pixman_transform_point_3d (pixman_transform, &vector)) + return; + + /* Ideally, the vector should now be (0, 0). We can now compensate + * for the resulting error */ + pixman_transform->matrix[0][2] -= vector.vector[0]; + pixman_transform->matrix[1][2] -= vector.vector[1]; } } diff --git a/gfx/cairo/cairo/src/cairo-meta-surface.c b/gfx/cairo/cairo/src/cairo-meta-surface.c index 0b03cc711528..51ed3829e39c 100644 --- a/gfx/cairo/cairo/src/cairo-meta-surface.c +++ b/gfx/cairo/cairo/src/cairo-meta-surface.c @@ -61,8 +61,7 @@ typedef enum { CAIRO_META_REPLAY, - CAIRO_META_CREATE_REGIONS, - CAIRO_META_ANALYZE_META_PATTERN + CAIRO_META_CREATE_REGIONS } cairo_meta_replay_type_t; static const cairo_surface_backend_t cairo_meta_surface_backend; @@ -84,10 +83,8 @@ _cairo_meta_surface_create (cairo_content_t content, cairo_meta_surface_t *meta; meta = malloc (sizeof (cairo_meta_surface_t)); - if (meta == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (meta == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&meta->base, &cairo_meta_surface_backend, content); @@ -476,7 +473,7 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface, _cairo_pattern_fini (&command->source.base); CLEANUP_COMMAND: free (command); - return _cairo_error (status); + return status; } /** @@ -499,10 +496,8 @@ _cairo_meta_surface_snapshot (void *abstract_other) cairo_meta_surface_t *meta; meta = malloc (sizeof (cairo_meta_surface_t)); - if (meta == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (meta == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&meta->base, &cairo_meta_surface_backend, other->base.content); @@ -853,11 +848,6 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface, } } - if (type == CAIRO_META_ANALYZE_META_PATTERN) { - if (status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY) - status = CAIRO_STATUS_SUCCESS; - } - if (status) break; } @@ -877,16 +867,6 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, CAIRO_META_REGION_ALL); } -cairo_status_t -_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface, - cairo_surface_t *target) -{ - return _cairo_meta_surface_replay_internal (surface, - target, - CAIRO_META_ANALYZE_META_PATTERN, - CAIRO_META_REGION_ALL); -} - /* Replay meta to surface. When the return status of each operation is * one of CAIRO_STATUS_SUCCESS, CAIRO_INT_STATUS_UNSUPPORTED, or * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation diff --git a/gfx/cairo/cairo/src/cairo-operator.c b/gfx/cairo/cairo/src/cairo-operator.c deleted file mode 100644 index 1a3c3d150301..000000000000 --- a/gfx/cairo/cairo/src/cairo-operator.c +++ /dev/null @@ -1,119 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2006 Keith Packard - * Copyright © 2006 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.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/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Keith Packard - */ - -#include "cairoint.h" - -/* The analysis here assumes destination alpha semantics (that is - * CAIRO_CONTENT_COLOR_ALPHA). More things can be considered opaque - * otherwise (CAIRO_CONTENT_COLOR) so we'll probably want to add a - * cairo_content_t parameter to this function - * - * We also need a definition of what "opaque" means. Is it, "does not - * requiring 'knowing' the original contents of destination, nor does - * it set the destination alpha to anything but 1.0" ? - */ -cairo_bool_t -_cairo_operator_always_opaque (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return FALSE; - - case CAIRO_OPERATOR_SOURCE: - return FALSE; - - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - return FALSE; - - case CAIRO_OPERATOR_DEST: - return TRUE; - - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - return FALSE; - - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - return FALSE; - } - return FALSE; -} - -/* As above, we'll probably want to add a cairo_content_t parameter to - * this function - * - * We also need a definition of what "translucent" means. - */ -cairo_bool_t -_cairo_operator_always_translucent (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return TRUE; - - case CAIRO_OPERATOR_SOURCE: - return FALSE; - - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - return FALSE; - - case CAIRO_OPERATOR_DEST: - return FALSE; - - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - return FALSE; - - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - return TRUE; - } - return TRUE; -} diff --git a/gfx/cairo/cairo/src/cairo-os2-surface.c b/gfx/cairo/cairo/src/cairo-os2-surface.c index 0d888ed3cd7c..f3824849dc8e 100644 --- a/gfx/cairo/cairo/src/cairo-os2-surface.c +++ b/gfx/cairo/cairo/src/cairo-os2-surface.c @@ -135,6 +135,74 @@ cairo_os2_fini (void) * as much as possible. */ _heapshrink (); +#else + /* GCC has a heapmin function that approximately corresponds to + * what the Watcom function does + */ + _heapmin (); +#endif +} + +/* + * This function calls the allocation function depending on which + * method was compiled into the library: it can be native allocation + * (DosAllocMem/DosFreeMem) or C-Library based allocation (malloc/free). + * Actually, for pixel buffers that we use this function for, cairo + * uses _cairo_malloc_abc, so we use that here, too. And use the + * change to check the size argument + */ +void *_buffer_alloc (size_t a, size_t b, const unsigned int size) +{ + /* check length like in the _cairo_malloc_abc macro, but we can leave + * away the unsigned casts as our arguments are unsigned already + */ + size_t nbytes = b && + a >= INT32_MAX / b ? 0 : size && + a*b >= INT32_MAX / size ? 0 : a * b * size; + void *buffer = NULL; +#ifdef OS2_USE_PLATFORM_ALLOC + APIRET rc = NO_ERROR; + + rc = DosAllocMem ((PPVOID)&buffer, + nbytes, +#ifdef OS2_HIGH_MEMORY /* only if compiled with high-memory support, */ + OBJ_ANY | /* we can allocate anywhere! */ +#endif + PAG_READ | PAG_WRITE | PAG_COMMIT); + if (rc != NO_ERROR) { + /* should there for some reason be another error, let's return + * a null surface and free the buffer again, because that's + * how a malloc failure would look like + */ + if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) { + DosFreeMem (buffer); + } + return NULL; + } +#else + buffer = malloc (nbytes); +#endif + + /* This does not seem to be needed, malloc'd space is usually + * already zero'd out! + */ + /* + * memset (buffer, 0x00, nbytes); + */ + + return buffer; +} + +/* + * This function selects the free function depending on which + * allocation method was compiled into the library + */ +void _buffer_free (void *buffer) +{ +#ifdef OS2_USE_PLATFORM_ALLOC + DosFreeMem (buffer); +#else + free (buffer); #endif } @@ -296,9 +364,9 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface, ULONG ulPixels; /* allocate temporary pixel buffer */ - pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy, - surface->bitmap_info.cx, - 3); + pchPixBuf = (unsigned char *) _buffer_alloc (surface->bitmap_info.cy, + surface->bitmap_info.cx, + 3); pchPixSource = surface->pixels; /* start at beginning of pixel buffer */ pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */ @@ -330,7 +398,7 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface, ROP_SRCCOPY, BBO_IGNORE); - free (pchPixBuf); + _buffer_free (pchPixBuf); } /* Restore Y inversion */ @@ -654,6 +722,7 @@ cairo_os2_surface_create (HPS hps_client_window, int height) { cairo_os2_surface_t *local_os2_surface; + cairo_status_t status; int rc; /* Check the size of the window */ @@ -661,15 +730,13 @@ cairo_os2_surface_create (HPS hps_client_window, (height <= 0)) { /* Invalid window size! */ - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } local_os2_surface = (cairo_os2_surface_t *) malloc (sizeof (cairo_os2_surface_t)); if (!local_os2_surface) { /* Not enough memory! */ - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } /* Initialize the OS/2 specific parts of the surface! */ @@ -681,8 +748,7 @@ cairo_os2_surface_create (HPS hps_client_window, FALSE); if (rc != NO_ERROR) { /* Could not create mutex semaphore! */ - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } /* Save PS handle */ @@ -701,8 +767,7 @@ cairo_os2_surface_create (HPS hps_client_window, /* Could not create event semaphore! */ DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); free (local_os2_surface); - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } /* Prepare BITMAPINFO2 structure for our buffer */ @@ -714,23 +779,15 @@ cairo_os2_surface_create (HPS hps_client_window, local_os2_surface->bitmap_info.cBitCount = 32; /* Allocate memory for pixels */ - local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4); + local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4); if (!(local_os2_surface->pixels)) { /* Not enough memory for the pixels! */ DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); free (local_os2_surface); - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } - /* This is possibly not needed, malloc'd space is - * usually zero'd out! - */ - /* - memset (local_os2_surface->pixels, 0x00, swpTemp.cx * swpTemp.cy * 4); - */ - /* Create image surface from pixel array */ local_os2_surface->image_surface = (cairo_image_surface_t *) cairo_image_surface_create_for_data (local_os2_surface->pixels, @@ -739,14 +796,14 @@ cairo_os2_surface_create (HPS hps_client_window, height, /* Height */ width * 4); /* Rowstride */ - if (local_os2_surface->image_surface->base.status) { + status = local_os2_surface->image_surface->base.status; + if (status) { /* Could not create image surface! */ - free (local_os2_surface->pixels); + _buffer_free (local_os2_surface->pixels); DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); free (local_os2_surface); - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); } /* Initialize base surface */ @@ -784,7 +841,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, } /* Allocate memory for new stuffs */ - pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 4); + pchNewPixels = (unsigned char *) _buffer_alloc (new_height, new_width, 4); if (!pchNewPixels) { /* Not enough memory for the pixels! * Everything remains the same! @@ -792,13 +849,6 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - /* This is possibly not needed, malloc'd space is usually - * already zero'd out! - */ - /* - memset (pchNewPixels, 0x00, new_width * new_height * 4); - */ - /* Create image surface from new pixel array */ pNewImageSurface = (cairo_image_surface_t *) cairo_image_surface_create_for_data (pchNewPixels, @@ -811,7 +861,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, /* Could not create image surface! * Everything remains the same! */ - free (pchNewPixels); + _buffer_free (pchNewPixels); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -823,7 +873,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, * Everything remains the same! */ cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - free (pchNewPixels); + _buffer_free (pchNewPixels); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -839,7 +889,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, if (rc != NO_ERROR) { /* Either timeout or something wrong... Exit. */ cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - free (pchNewPixels); + _buffer_free (pchNewPixels); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } /* Okay, grab mutex and check counter again! */ @@ -850,7 +900,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, * Everything remains the same! */ cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - free (pchNewPixels); + _buffer_free (pchNewPixels); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } } @@ -858,7 +908,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface, /* Destroy old image surface */ cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); /* Destroy old pixel buffer */ - free (local_os2_surface->pixels); + _buffer_free (local_os2_surface->pixels); /* Set new image surface */ local_os2_surface->image_surface = pNewImageSurface; /* Set new pixel buffer */ @@ -957,7 +1007,7 @@ _cairo_os2_surface_finish (void *abstract_surface) /* Destroy old image surface */ cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); /* Destroy old pixel buffer */ - free (local_os2_surface->pixels); + _buffer_free (local_os2_surface->pixels); DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); diff --git a/gfx/cairo/cairo/src/cairo-output-stream-private.h b/gfx/cairo/cairo/src/cairo-output-stream-private.h index 0e7d4dbe4172..8377eca4a856 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream-private.h +++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h @@ -87,6 +87,9 @@ _cairo_output_stream_create (cairo_write_func_t write_func, cairo_close_func_t close_func, void *closure); +cairo_private cairo_output_stream_t * +_cairo_output_stream_create_in_error (cairo_status_t status); + /* Returns the final status value associated with this object, just * before its last gasp. This final status value will capture any * status failure returned by the stream's close_func as well. */ diff --git a/gfx/cairo/cairo/src/cairo-output-stream.c b/gfx/cairo/cairo/src/cairo-output-stream.c index b8fb706bffb1..2cb9e03bcdec 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream.c +++ b/gfx/cairo/cairo/src/cairo-output-stream.c @@ -38,8 +38,10 @@ #include "cairo-output-stream-private.h" +#include #include #include +#include #ifdef _MSC_VER #define snprintf _snprintf @@ -132,6 +134,29 @@ _cairo_output_stream_create (cairo_write_func_t write_func, return &stream->base; } +cairo_output_stream_t * +_cairo_output_stream_create_in_error (cairo_status_t status) +{ + cairo_output_stream_t *stream; + + /* check for the common ones */ + if (status == CAIRO_STATUS_NO_MEMORY) + return (cairo_output_stream_t *) &_cairo_output_stream_nil; + if (status == CAIRO_STATUS_WRITE_ERROR) + return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; + + stream = malloc (sizeof (cairo_output_stream_t)); + if (stream == NULL) { + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return (cairo_output_stream_t *) &_cairo_output_stream_nil; + } + + _cairo_output_stream_init (stream, NULL, NULL); + stream->status = status; + + return stream; +} + cairo_status_t _cairo_output_stream_close (cairo_output_stream_t *stream) { @@ -163,8 +188,7 @@ _cairo_output_stream_destroy (cairo_output_stream_t *stream) { cairo_status_t status; - if (stream == NULL) - return _cairo_error (CAIRO_STATUS_NULL_POINTER); + assert (stream != NULL); if (stream == &_cairo_output_stream_nil || stream == &_cairo_output_stream_nil_write_error) @@ -538,8 +562,14 @@ _cairo_output_stream_create_for_filename (const char *filename) file = fopen (filename, "wb"); if (file == NULL) { - _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR); - return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; + switch (errno) { + case ENOMEM: + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return (cairo_output_stream_t *) &_cairo_output_stream_nil; + default: + _cairo_error_throw (CAIRO_STATUS_WRITE_ERROR); + return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; + } } stream = malloc (sizeof *stream); diff --git a/gfx/cairo/cairo/src/cairo-paginated-private.h b/gfx/cairo/cairo/src/cairo-paginated-private.h index 1ecb01420afe..7b411915e3d5 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-private.h +++ b/gfx/cairo/cairo/src/cairo-paginated-private.h @@ -110,18 +110,22 @@ struct _cairo_paginated_surface_backend { * * 6. Replays a subset of the meta-surface operations to the target surface * - * 7. Replays the remaining operations to an image surface, sets an + * 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK + * + * 8. Replays the remaining operations to an image surface, sets an * appropriate clip on the target, then paints the resulting image * surface to the target. * - * So, the target will see drawing operations during two separate - * stages, (ANALYZE and RENDER). During the ANALYZE phase the target - * should not actually perform any rendering, (for example, if - * performing output to a file, no output should be generated during - * this stage). Instead the drawing functions simply need to return - * CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate - * whether rendering would be supported. And it should do this as - * quickly as possible. + * So, the target will see drawing operations during three separate + * stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase + * the target should not actually perform any rendering, (for example, + * if performing output to a file, no output should be generated + * during this stage). Instead the drawing functions simply need to + * return CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to + * indicate whether rendering would be supported. And it should do + * this as quickly as possible. The FALLBACK phase allows the surface + * to distinguish fallback images from native rendering in case they + * need to be handled as a special case. * * NOTE: The paginated surface layer assumes that the target surface * is "blank" by default at the beginning of each page, without any diff --git a/gfx/cairo/cairo/src/cairo-paginated-surface.c b/gfx/cairo/cairo/src/cairo-paginated-surface.c index e14c25b5f195..953f4630f7a5 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-surface.c +++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c @@ -74,10 +74,11 @@ _cairo_paginated_surface_create (cairo_surface_t *target, const cairo_paginated_surface_backend_t *backend) { cairo_paginated_surface_t *surface; + cairo_status_t status; surface = malloc (sizeof (cairo_paginated_surface_t)); if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FAIL; } @@ -97,7 +98,8 @@ _cairo_paginated_surface_create (cairo_surface_t *target, surface->backend = backend; surface->meta = _cairo_meta_surface_create (content, width, height); - if (cairo_surface_status (surface->meta)) + status = cairo_surface_status (surface->meta); + if (status) goto FAIL_CLEANUP_SURFACE; surface->page_num = 1; @@ -108,7 +110,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, FAIL_CLEANUP_SURFACE: free (surface); FAIL: - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); } cairo_bool_t @@ -149,7 +151,7 @@ _cairo_paginated_surface_set_size (cairo_surface_t *surface, width, height); status = cairo_surface_status (paginated_surface->meta); if (status) - return status; + return _cairo_surface_set_error (surface, status); return CAIRO_STATUS_SUCCESS; } @@ -161,7 +163,7 @@ _cairo_paginated_surface_finish (void *abstract_surface) cairo_status_t status = CAIRO_STATUS_SUCCESS; if (surface->page_is_blank == FALSE || surface->page_num == 1) - status = _cairo_paginated_surface_show_page (abstract_surface); + status = cairo_surface_show_page (abstract_surface); if (status == CAIRO_STATUS_SUCCESS) { cairo_surface_finish (surface->target); @@ -292,8 +294,8 @@ _paint_page (cairo_paginated_surface_t *surface) analysis = _cairo_analysis_surface_create (surface->target, surface->width, surface->height); - if (analysis == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (analysis->status) + return _cairo_surface_set_error (surface->target, analysis->status); surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis); @@ -325,6 +327,16 @@ _paint_page (cairo_paginated_surface_t *surface) has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis); break; + case CAIRO_SURFACE_TYPE_IMAGE: + case CAIRO_SURFACE_TYPE_XLIB: + case CAIRO_SURFACE_TYPE_XCB: + case CAIRO_SURFACE_TYPE_GLITZ: + case CAIRO_SURFACE_TYPE_QUARTZ: + case CAIRO_SURFACE_TYPE_WIN32: + case CAIRO_SURFACE_TYPE_BEOS: + case CAIRO_SURFACE_TYPE_DIRECTFB: + case CAIRO_SURFACE_TYPE_SVG: + case CAIRO_SURFACE_TYPE_OS2: default: if (_cairo_analysis_surface_has_unsupported (analysis)) { has_supported = FALSE; @@ -341,6 +353,7 @@ _paint_page (cairo_paginated_surface_t *surface) status = _cairo_meta_surface_replay_region (surface->meta, surface->target, CAIRO_META_REGION_NATIVE); + assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (status) goto FAIL; } @@ -364,7 +377,9 @@ _paint_page (cairo_paginated_surface_t *surface) cairo_box_int_t *boxes; int num_boxes, i; - /* Reset clip region before drawing the fall back images */ + surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK); + + /* Reset clip region before drawing the fall back images */ status = _cairo_surface_intersect_clip_path (surface->target, NULL, CAIRO_FILL_RULE_WINDING, @@ -614,43 +629,9 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface, static cairo_surface_t * _cairo_paginated_surface_snapshot (void *abstract_other) { - cairo_status_t status; cairo_paginated_surface_t *other = abstract_other; - /* XXX: Just making a snapshot of other->meta is what we really - * want. But this currently triggers a bug somewhere (the "mask" - * test from the test suite segfaults). - * - * For now, we'll create a new image surface and replay onto - * that. It would be tempting to replay into other->image and then - * return a snapshot of that, but that will cause the self-copy - * test to fail, (since our replay will be affected by a clip that - * should not have any effect on the use of the resulting snapshot - * as a source). - */ - -#if 0 return _cairo_surface_snapshot (other->meta); -#else - cairo_rectangle_int_t extents; - cairo_surface_t *surface; - - status = _cairo_surface_get_extents (other->target, &extents); - if (status) - return (cairo_surface_t*) &_cairo_surface_nil; - - surface = _cairo_paginated_surface_create_image_surface (other, - extents.width, - extents.height); - - status = _cairo_meta_surface_replay (other->meta, surface); - if (status) { - cairo_surface_destroy (surface); - surface = (cairo_surface_t*) &_cairo_surface_nil; - } - - return surface; -#endif } static const cairo_surface_backend_t cairo_paginated_surface_backend = { diff --git a/gfx/cairo/cairo/src/cairo-path-bounds.c b/gfx/cairo/cairo/src/cairo-path-bounds.c index 5b60cf1c3931..581244b4919b 100644 --- a/gfx/cairo/cairo/src/cairo-path-bounds.c +++ b/gfx/cairo/cairo/src/cairo-path-bounds.c @@ -37,7 +37,9 @@ #include "cairoint.h" typedef struct cairo_path_bounder { - int has_point; + cairo_point_t move_to_point; + cairo_bool_t has_move_to_point; + cairo_bool_t has_point; cairo_fixed_t min_x; cairo_fixed_t min_y; @@ -60,25 +62,21 @@ _cairo_path_bounder_move_to (void *closure, cairo_point_t *point); static cairo_status_t _cairo_path_bounder_line_to (void *closure, cairo_point_t *point); -static cairo_status_t -_cairo_path_bounder_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d); - static cairo_status_t _cairo_path_bounder_close_path (void *closure); static void _cairo_path_bounder_init (cairo_path_bounder_t *bounder) { - bounder->has_point = 0; + bounder->has_move_to_point = FALSE; + bounder->has_point = FALSE; } static void _cairo_path_bounder_fini (cairo_path_bounder_t *bounder) { - bounder->has_point = 0; + bounder->has_move_to_point = FALSE; + bounder->has_point = FALSE; } static void @@ -102,7 +100,7 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *poi bounder->max_x = point->x; bounder->max_y = point->y; - bounder->has_point = 1; + bounder->has_point = TRUE; } } @@ -111,7 +109,8 @@ _cairo_path_bounder_move_to (void *closure, cairo_point_t *point) { cairo_path_bounder_t *bounder = closure; - _cairo_path_bounder_add_point (bounder, point); + bounder->move_to_point = *point; + bounder->has_move_to_point = TRUE; return CAIRO_STATUS_SUCCESS; } @@ -121,26 +120,17 @@ _cairo_path_bounder_line_to (void *closure, cairo_point_t *point) { cairo_path_bounder_t *bounder = closure; + if (bounder->has_move_to_point) { + _cairo_path_bounder_add_point (bounder, + &bounder->move_to_point); + bounder->has_move_to_point = FALSE; + } + _cairo_path_bounder_add_point (bounder, point); return CAIRO_STATUS_SUCCESS; } -static cairo_status_t -_cairo_path_bounder_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - cairo_path_bounder_t *bounder = closure; - - _cairo_path_bounder_add_point (bounder, b); - _cairo_path_bounder_add_point (bounder, c); - _cairo_path_bounder_add_point (bounder, d); - - return CAIRO_STATUS_SUCCESS; -} - static cairo_status_t _cairo_path_bounder_close_path (void *closure) { @@ -148,10 +138,11 @@ _cairo_path_bounder_close_path (void *closure) } /* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */ -cairo_status_t +void _cairo_path_fixed_bounds (cairo_path_fixed_t *path, double *x1, double *y1, - double *x2, double *y2) + double *x2, double *y2, + double tolerance) { cairo_status_t status; @@ -159,24 +150,25 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path, _cairo_path_bounder_init (&bounder); - status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, - _cairo_path_bounder_move_to, - _cairo_path_bounder_line_to, - _cairo_path_bounder_curve_to, - _cairo_path_bounder_close_path, - &bounder); - if (status) { - *x1 = *y1 = *x2 = *y2 = 0.0; - _cairo_path_bounder_fini (&bounder); - return status; + status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD, + _cairo_path_bounder_move_to, + _cairo_path_bounder_line_to, + _cairo_path_bounder_close_path, + &bounder, + tolerance); + assert (status == CAIRO_STATUS_SUCCESS); + + if (bounder.has_point) { + *x1 = _cairo_fixed_to_double (bounder.min_x); + *y1 = _cairo_fixed_to_double (bounder.min_y); + *x2 = _cairo_fixed_to_double (bounder.max_x); + *y2 = _cairo_fixed_to_double (bounder.max_y); + } else { + *x1 = 0.0; + *y1 = 0.0; + *x2 = 0.0; + *y2 = 0.0; } - *x1 = _cairo_fixed_to_double (bounder.min_x); - *y1 = _cairo_fixed_to_double (bounder.min_y); - *x2 = _cairo_fixed_to_double (bounder.max_x); - *y2 = _cairo_fixed_to_double (bounder.max_y); - _cairo_path_bounder_fini (&bounder); - - return CAIRO_STATUS_SUCCESS; } diff --git a/gfx/cairo/cairo/src/cairo-path-fixed.c b/gfx/cairo/cairo/src/cairo-path-fixed.c index e18ecc34b3bc..91b8c0e27755 100644 --- a/gfx/cairo/cairo/src/cairo-path-fixed.c +++ b/gfx/cairo/cairo/src/cairo-path-fixed.c @@ -622,3 +622,102 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path, } return TRUE; } + +/* Closure for path flattening */ +typedef struct cairo_path_flattener { + double tolerance; + cairo_point_t current_point; + cairo_path_fixed_move_to_func_t *move_to; + cairo_path_fixed_line_to_func_t *line_to; + cairo_path_fixed_close_path_func_t *close_path; + void *closure; +} cpf_t; + +static cairo_status_t +_cpf_move_to (void *closure, cairo_point_t *point) +{ + cpf_t *cpf = closure; + + cpf->current_point = *point; + + return cpf->move_to (cpf->closure, point); +} + +static cairo_status_t +_cpf_line_to (void *closure, cairo_point_t *point) +{ + cpf_t *cpf = closure; + + cpf->current_point = *point; + + return cpf->line_to (cpf->closure, point); +} + +static cairo_status_t +_cpf_curve_to (void *closure, + cairo_point_t *p1, + cairo_point_t *p2, + cairo_point_t *p3) +{ + cpf_t *cpf = closure; + cairo_status_t status; + cairo_spline_t spline; + int i; + + cairo_point_t *p0 = &cpf->current_point; + + status = _cairo_spline_init (&spline, p0, p1, p2, p3); + if (status == CAIRO_INT_STATUS_DEGENERATE) + return CAIRO_STATUS_SUCCESS; + + status = _cairo_spline_decompose (&spline, cpf->tolerance); + if (status) + goto out; + + for (i=1; i < spline.num_points; i++) { + status = cpf->line_to (cpf->closure, &spline.points[i]); + if (status) + goto out; + } + + cpf->current_point = *p3; + + status = CAIRO_STATUS_SUCCESS; + + out: + _cairo_spline_fini (&spline); + return status; +} + +static cairo_status_t +_cpf_close_path (void *closure) +{ + cpf_t *cpf = closure; + + return cpf->close_path (cpf->closure); +} + + +cairo_status_t +_cairo_path_fixed_interpret_flat (cairo_path_fixed_t *path, + cairo_direction_t dir, + cairo_path_fixed_move_to_func_t *move_to, + cairo_path_fixed_line_to_func_t *line_to, + cairo_path_fixed_close_path_func_t *close_path, + void *closure, + double tolerance) +{ + cpf_t flattener; + + flattener.tolerance = tolerance; + flattener.move_to = move_to; + flattener.line_to = line_to; + flattener.close_path = close_path; + flattener.closure = closure; + return _cairo_path_fixed_interpret (path, dir, + _cpf_move_to, + _cpf_line_to, + _cpf_curve_to, + _cpf_close_path, + &flattener); +} diff --git a/gfx/cairo/cairo/src/cairo-path-stroke.c b/gfx/cairo/cairo/src/cairo-path-stroke.c index fb12f157f9aa..5705e0a4431a 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -205,6 +205,22 @@ _cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out return _cairo_slope_clockwise (&in_slope, &out_slope); } +/** + * _cairo_slope_compare_sgn + * + * Return -1, 0 or 1 depending on the relative slopes of + * two lines. + */ +static int +_cairo_slope_compare_sgn (double dx1, double dy1, double dx2, double dy2) +{ + double c = (dx1 * dy2 - dx2 * dy1); + + if (c > 0) return 1; + if (c < 0) return -1; + return 0; +} + static cairo_status_t _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out) { @@ -272,9 +288,6 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st double in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+ (-in->usr_vector.y * out->usr_vector.y)); double ml = stroker->style->miter_limit; - double tolerance_squared = stroker->tolerance * stroker->tolerance; - double line_width_squared = (stroker->style->line_width * - stroker->style->line_width); /* Check the miter limit -- lines meeting at an acute angle * can generate long miters, the limit converts them to bevel @@ -332,84 +345,17 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st * * 2 <= ml² (1 - in · out) * - * - * That gives us the condition to avoid generating miters that - * are too large from angles that are too large. But we also - * need to avoid generating miters when the angle is very small. - * - * The miter formed from a tiny angle is also tiny, so the - * miter limit is not a concern. But with a tiny angle we will - * be computing the intersection of two lines that are very - * near parallel. Also, the limits of the fixed-point grid on - * the input face coordinates mean that the resulting - * intersection could be wildly wrong. (See the - * get-path-extents test case for a call to cairo_arc that - * results in two problematic faces.) - * - * Fortunately we can also derive an expression for when using - * a bevel join instead of a miter will introduce an error no - * larger than the tolerance. Consider the same join from - * before but with the miter now chopped off and replaced with - * a bevel join. The drawing is zoomed in a bit again, the - * point marked as '*' is the center of the stroke---the point - * where the two line segments of interest intersect: - * - * ----- . - * ^ .. - * | . . - * | . . - * 1/2 . . - * miter . . | - * length . . | - * | .______. ___v___ - * | | . \ 1/2 bevel - * v | . \ width - * ---- * \ ------- - * | \ ^ - * - * - * The length of interest here is the vertical length of the - * miter that is eliminated. It's length can be obtained by - * starting with 1/2 the miter length and the subtracting off - * the vertical length that is included by the bevel join, - * (here termed 1/2 bevel width). To determine this new bevel - * width, we have a small right triangle shown, the hypotenuse - * of which has a length of 1/2 the line width, and the small - * angle at the upper right of the figure is psi/2. - * - * So we have: - * - * sin (psi/2) = (bevel_width / 2) / (line_width / 2) - * - * And we can determine when the miter is required by - * calculating when the eliminated portion of the miter is - * greater than the tolerance: - * - * (miter_length / 2) - (bevel_width / 2) > tolerance - * - * Substituting in the above expressions for miter_length and - * bevel_width: - * - * (line_width/2) / sin (psi/2) - (line_width/2) * sin (psi/2) > tolerance - * 1 / sin(psi/2) - sin (psi/2) > 2 * tolerance / line_width - * 1 / sin²(psi/2) -2 + sin²(psi/2) > 4 * (tolerance/line_width)² - * - * Use identity: sin²(psi/2) = (1-cos(psi))/2 - - * 2/(1 - cos(psi)) - 2 + (1-cos(psi))/2 > 4 * (tolerance/line_width)² - * 4/(1 - cos(psi)) - 4 + (1-cos(psi)) > 8 * (tolerance/line_width)² - * 4/(1 - cos(psi)) + (1-cos(psi)) > 8 * ((tolerance/line_width)² + 0.5) */ - if ((2 <= ml * ml * (1 - in_dot_out)) && - ((8 * (tolerance_squared / line_width_squared + 0.5)) < - 4 / (1 - in_dot_out) + (1 - in_dot_out)) - ) + if (2 <= ml * ml * (1 - in_dot_out)) { double x1, y1, x2, y2; double mx, my; double dx1, dx2, dy1, dy2; cairo_point_t outer; cairo_point_t quad[4]; + double ix, iy; + double fdx1, fdy1, fdx2, fdy2; + double mdx, mdy; /* * we've got the points already transformed to device @@ -447,17 +393,46 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st mx = (my - y2) * dx2 / dy2 + x2; /* - * Draw the quadrilateral + * When the two outer edges are nearly parallel, slight + * perturbations in the position of the outer points of the lines + * caused by representing them in fixed point form can cause the + * intersection point of the miter to move a large amount. If + * that moves the miter intersection from between the two faces, + * then draw a bevel instead. */ - outer.x = _cairo_fixed_from_double (mx); - outer.y = _cairo_fixed_from_double (my); - quad[0] = in->point; - quad[1] = *inpt; - quad[2] = outer; - quad[3] = *outpt; + ix = _cairo_fixed_to_double (in->point.x); + iy = _cairo_fixed_to_double (in->point.y); - return _cairo_traps_tessellate_convex_quad (stroker->traps, quad); + /* slope of one face */ + fdx1 = x1 - ix; fdy1 = y1 - iy; + + /* slope of the other face */ + fdx2 = x2 - ix; fdy2 = y2 - iy; + + /* slope from the intersection to the miter point */ + mdx = mx - ix; mdy = my - iy; + + /* + * Make sure the miter point line lies between the two + * faces by comparing the slopes + */ + if (_cairo_slope_compare_sgn (fdx1, fdy1, mdx, mdy) != + _cairo_slope_compare_sgn (fdx2, fdy2, mdx, mdy)) + { + /* + * Draw the quadrilateral + */ + outer.x = _cairo_fixed_from_double (mx); + outer.y = _cairo_fixed_from_double (my); + + quad[0] = in->point; + quad[1] = *inpt; + quad[2] = outer; + quad[3] = *outpt; + + return _cairo_traps_tessellate_convex_quad (stroker->traps, quad); + } } /* fall through ... */ } @@ -907,7 +882,7 @@ _cairo_stroker_curve_to (void *closure, status = _cairo_spline_init (&spline, a, b, c, d); if (status == CAIRO_INT_STATUS_DEGENERATE) - return CAIRO_STATUS_SUCCESS; + return _cairo_stroker_line_to (closure, d); status = _cairo_pen_init_copy (&pen, &stroker->pen); if (status) @@ -991,7 +966,7 @@ _cairo_stroker_curve_to_dashed (void *closure, status = _cairo_spline_init (&spline, a, b, c, d); if (status == CAIRO_INT_STATUS_DEGENERATE) - return CAIRO_STATUS_SUCCESS; + return _cairo_stroker_line_to_dashed (closure, d); /* If the line width is so small that the pen is reduced to a single point, then we have nothing to do. */ @@ -1383,6 +1358,12 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path, return CAIRO_INT_STATUS_UNSUPPORTED; if (stroke_style->line_join != CAIRO_LINE_JOIN_MITER) return CAIRO_INT_STATUS_UNSUPPORTED; + /* If the miter limit turns right angles into bevels, then we + * can't use this optimization. Remember, the ratio is + * 1/sin(ɸ/2). So the cutoff is 1/sin(Ï€/4.0) or ⎷2, + * which we round for safety. */ + if (stroke_style->miter_limit < M_SQRT2) + return CAIRO_INT_STATUS_UNSUPPORTED; if (stroke_style->dash) return CAIRO_INT_STATUS_UNSUPPORTED; if (! (stroke_style->line_cap == CAIRO_LINE_CAP_BUTT || diff --git a/gfx/cairo/cairo/src/cairo-path.c b/gfx/cairo/cairo/src/cairo-path.c index b9086c4db945..96ecbb355617 100644 --- a/gfx/cairo/cairo/src/cairo-path.c +++ b/gfx/cairo/cairo/src/cairo-path.c @@ -44,7 +44,6 @@ static const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 }; /* Closure for path interpretation. */ typedef struct cairo_path_count { int count; - double tolerance; cairo_point_t current_point; } cpc_t; @@ -87,39 +86,6 @@ _cpc_curve_to (void *closure, return CAIRO_STATUS_SUCCESS; } -static cairo_status_t -_cpc_curve_to_flatten (void *closure, - cairo_point_t *p1, - cairo_point_t *p2, - cairo_point_t *p3) -{ - cpc_t *cpc = closure; - cairo_status_t status; - cairo_spline_t spline; - int i; - - cairo_point_t *p0 = &cpc->current_point; - - status = _cairo_spline_init (&spline, p0, p1, p2, p3); - if (status == CAIRO_INT_STATUS_DEGENERATE) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_spline_decompose (&spline, cpc->tolerance); - if (status) - goto out; - - for (i=1; i < spline.num_points; i++) - _cpc_line_to (cpc, &spline.points[i]); - - cpc->current_point = *p3; - - status = CAIRO_STATUS_SUCCESS; - - out: - _cairo_spline_fini (&spline); - return status; -} - static cairo_status_t _cpc_close_path (void *closure) { @@ -140,19 +106,27 @@ _cairo_path_count (cairo_path_t *path, cpc_t cpc; cpc.count = 0; - cpc.tolerance = tolerance; cpc.current_point.x = 0; cpc.current_point.y = 0; - status = _cairo_path_fixed_interpret (path_fixed, - CAIRO_DIRECTION_FORWARD, - _cpc_move_to, - _cpc_line_to, - flatten ? - _cpc_curve_to_flatten : - _cpc_curve_to, - _cpc_close_path, - &cpc); + if (flatten) { + status = _cairo_path_fixed_interpret_flat (path_fixed, + CAIRO_DIRECTION_FORWARD, + _cpc_move_to, + _cpc_line_to, + _cpc_close_path, + &cpc, + tolerance); + } else { + status = _cairo_path_fixed_interpret (path_fixed, + CAIRO_DIRECTION_FORWARD, + _cpc_move_to, + _cpc_line_to, + _cpc_curve_to, + _cpc_close_path, + &cpc); + } + if (status) return -1; @@ -262,40 +236,6 @@ _cpp_curve_to (void *closure, return CAIRO_STATUS_SUCCESS; } -static cairo_status_t -_cpp_curve_to_flatten (void *closure, - cairo_point_t *p1, - cairo_point_t *p2, - cairo_point_t *p3) -{ - cpp_t *cpp = closure; - cairo_status_t status; - cairo_spline_t spline; - int i; - - cairo_point_t *p0 = &cpp->current_point; - - status = _cairo_spline_init (&spline, p0, p1, p2, p3); - if (status == CAIRO_INT_STATUS_DEGENERATE) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_spline_decompose (&spline, - _cairo_gstate_get_tolerance (cpp->gstate)); - if (status) - goto out; - - for (i=1; i < spline.num_points; i++) - _cpp_line_to (cpp, &spline.points[i]); - - cpp->current_point = *p3; - - status = CAIRO_STATUS_SUCCESS; - - out: - _cairo_spline_fini (&spline); - return status; -} - static cairo_status_t _cpp_close_path (void *closure) { @@ -324,15 +264,25 @@ _cairo_path_populate (cairo_path_t *path, cpp.current_point.x = 0; cpp.current_point.y = 0; - status = _cairo_path_fixed_interpret (path_fixed, + if (flatten) { + double tolerance = _cairo_gstate_get_tolerance (gstate); + status = _cairo_path_fixed_interpret_flat (path_fixed, + CAIRO_DIRECTION_FORWARD, + _cpp_move_to, + _cpp_line_to, + _cpp_close_path, + &cpp, + tolerance); + } else { + status = _cairo_path_fixed_interpret (path_fixed, CAIRO_DIRECTION_FORWARD, _cpp_move_to, _cpp_line_to, - flatten ? - _cpp_curve_to_flatten : _cpp_curve_to, _cpp_close_path, &cpp); + } + if (status) return status; diff --git a/gfx/cairo/cairo/src/cairo-pattern.c b/gfx/cairo/cairo/src/cairo-pattern.c index 488177b118f8..ccd762239ae0 100644 --- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -91,8 +91,6 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern, static void _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) { - CAIRO_MUTEX_INITIALIZE (); - pattern->type = type; CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1); pattern->status = CAIRO_STATUS_SUCCESS; @@ -213,6 +211,42 @@ _cairo_pattern_fini (cairo_pattern_t *pattern) } } +cairo_status_t +_cairo_pattern_create_copy (cairo_pattern_t **pattern, + const cairo_pattern_t *other) +{ + cairo_status_t status; + + if (other->status) + return other->status; + + switch (other->type) { + case CAIRO_PATTERN_TYPE_SOLID: + *pattern = malloc (sizeof (cairo_solid_pattern_t)); + break; + case CAIRO_PATTERN_TYPE_SURFACE: + *pattern = malloc (sizeof (cairo_surface_pattern_t)); + break; + case CAIRO_PATTERN_TYPE_LINEAR: + *pattern = malloc (sizeof (cairo_linear_pattern_t)); + break; + case CAIRO_PATTERN_TYPE_RADIAL: + *pattern = malloc (sizeof (cairo_radial_pattern_t)); + break; + } + if (*pattern == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_pattern_init_copy (*pattern, other); + if (status) { + free (*pattern); + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + + void _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, const cairo_color_t *color, @@ -339,6 +373,8 @@ _cairo_pattern_create_in_error (cairo_status_t status) if (status == CAIRO_STATUS_NO_MEMORY) return (cairo_pattern_t *)&_cairo_pattern_nil.base; + CAIRO_MUTEX_INITIALIZE (); + pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK), CAIRO_CONTENT_COLOR); if (pattern->status == CAIRO_STATUS_SUCCESS) @@ -379,6 +415,8 @@ cairo_pattern_create_rgb (double red, double green, double blue) _cairo_color_init_rgb (&color, red, green, blue); + CAIRO_MUTEX_INITIALIZE (); + pattern = _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR); if (pattern->status) @@ -423,6 +461,8 @@ cairo_pattern_create_rgba (double red, double green, double blue, _cairo_color_init_rgba (&color, red, green, blue, alpha); + CAIRO_MUTEX_INITIALIZE (); + pattern = _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR_ALPHA); if (pattern->status) @@ -464,6 +504,8 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) return (cairo_pattern_t *)&_cairo_pattern_nil.base; } + CAIRO_MUTEX_INITIALIZE (); + _cairo_pattern_init_for_surface (pattern, surface); return &pattern->base; @@ -507,6 +549,8 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) return (cairo_pattern_t *) &_cairo_pattern_nil.base; } + CAIRO_MUTEX_INITIALIZE (); + _cairo_pattern_init_linear (pattern, x0, y0, x1, y1); return &pattern->base.base; @@ -552,6 +596,8 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, return (cairo_pattern_t *) &_cairo_pattern_nil.base; } + CAIRO_MUTEX_INITIALIZE (); + _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1); return &pattern->base.base; @@ -1782,7 +1828,8 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, attributes); } break; default: - status = CAIRO_INT_STATUS_UNSUPPORTED; + ASSERT_NOT_REACHED; + status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); } return status; diff --git a/gfx/cairo/cairo/src/cairo-pdf-operators-private.h b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h new file mode 100644 index 000000000000..83ef73cd072a --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-pdf-operators-private.h @@ -0,0 +1,107 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2004 Red Hat, Inc + * Copyright © 2006 Red Hat, Inc + * Copyright © 2007 Adrian Johnson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.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/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Kristian Høgsberg + * Carl Worth + * Adrian Johnson + */ + +#ifndef CAIRO_PDF_OPERATORS_H +#define CAIRO_PDF_OPERATORS_H + +#include "cairo-compiler-private.h" +#include "cairo-types-private.h" + +typedef cairo_status_t +(*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id, + unsigned int subset_id, + void *closure); + +typedef struct _cairo_pdf_operators { + cairo_output_stream_t *stream; + cairo_matrix_t cairo_to_pdf; + cairo_scaled_font_subsets_t *font_subsets; + cairo_pdf_operators_use_font_subset_t use_font_subset; + void *use_font_subset_closure; +} cairo_pdf_operators_t; + +cairo_private void +_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators, + cairo_output_stream_t *stream, + cairo_matrix_t cairo_to_pdf, + cairo_scaled_font_subsets_t *font_subsets); + +cairo_private void +_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators); + +cairo_private void +_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators, + cairo_pdf_operators_use_font_subset_t use_font_subset, + void *closure); + +cairo_private void +_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators, + cairo_output_stream_t *stream); + + +cairo_private void +_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators, + cairo_matrix_t cairo_to_pdf); + +cairo_private cairo_int_status_t +_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule); + +cairo_private cairo_int_status_t +_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse); + +cairo_private cairo_int_status_t +_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule); + +cairo_private cairo_int_status_t +_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font); + +#endif /* CAIRO_PDF_OPERATORS_H */ diff --git a/gfx/cairo/cairo/src/cairo-pdf-operators.c b/gfx/cairo/cairo/src/cairo-pdf-operators.c new file mode 100644 index 000000000000..a049d44d98d1 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c @@ -0,0 +1,532 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2004 Red Hat, Inc + * Copyright © 2006 Red Hat, Inc + * Copyright © 2007 Adrian Johnson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.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/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Kristian Høgsberg + * Carl Worth + * Adrian Johnson + */ + +#include "cairoint.h" +#include "cairo-pdf-operators-private.h" +#include "cairo-path-fixed-private.h" +#include "cairo-output-stream-private.h" +#include "cairo-scaled-font-subsets-private.h" + +void +_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators, + cairo_output_stream_t *stream, + cairo_matrix_t cairo_to_pdf, + cairo_scaled_font_subsets_t *font_subsets) +{ + pdf_operators->stream = stream; + pdf_operators->cairo_to_pdf = cairo_to_pdf; + pdf_operators->font_subsets = font_subsets; + pdf_operators->use_font_subset = NULL; + pdf_operators->use_font_subset_closure = NULL; +} + +void +_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators) +{ +} + +void +_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators, + cairo_pdf_operators_use_font_subset_t use_font_subset, + void *closure) +{ + pdf_operators->use_font_subset = use_font_subset; + pdf_operators->use_font_subset_closure = closure; +} + +void +_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators, + cairo_output_stream_t *stream) +{ + pdf_operators->stream = stream; +} + +void +_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators, + cairo_matrix_t cairo_to_pdf) +{ + pdf_operators->cairo_to_pdf = cairo_to_pdf; +} + +typedef struct _pdf_path_info { + cairo_output_stream_t *output; + cairo_matrix_t *cairo_to_pdf; + cairo_matrix_t *ctm_inverse; +} pdf_path_info_t; + +static cairo_status_t +_cairo_pdf_path_move_to (void *closure, cairo_point_t *point) +{ + pdf_path_info_t *info = closure; + double x = _cairo_fixed_to_double (point->x); + double y = _cairo_fixed_to_double (point->y); + + if (info->cairo_to_pdf) + cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y); + if (info->ctm_inverse) + cairo_matrix_transform_point (info->ctm_inverse, &x, &y); + + _cairo_output_stream_printf (info->output, + "%f %f m ", x, y); + + return _cairo_output_stream_get_status (info->output); +} + +static cairo_status_t +_cairo_pdf_path_line_to (void *closure, cairo_point_t *point) +{ + pdf_path_info_t *info = closure; + double x = _cairo_fixed_to_double (point->x); + double y = _cairo_fixed_to_double (point->y); + + if (info->cairo_to_pdf) + cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y); + if (info->ctm_inverse) + cairo_matrix_transform_point (info->ctm_inverse, &x, &y); + + _cairo_output_stream_printf (info->output, + "%f %f l ", x, y); + + return _cairo_output_stream_get_status (info->output); +} + +static cairo_status_t +_cairo_pdf_path_curve_to (void *closure, + cairo_point_t *b, + cairo_point_t *c, + cairo_point_t *d) +{ + pdf_path_info_t *info = closure; + double bx = _cairo_fixed_to_double (b->x); + double by = _cairo_fixed_to_double (b->y); + double cx = _cairo_fixed_to_double (c->x); + double cy = _cairo_fixed_to_double (c->y); + double dx = _cairo_fixed_to_double (d->x); + double dy = _cairo_fixed_to_double (d->y); + + if (info->cairo_to_pdf) { + cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by); + cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy); + cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy); + } + if (info->ctm_inverse) { + cairo_matrix_transform_point (info->ctm_inverse, &bx, &by); + cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy); + cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy); + } + + _cairo_output_stream_printf (info->output, + "%f %f %f %f %f %f c ", + bx, by, cx, cy, dx, dy); + return _cairo_output_stream_get_status (info->output); +} + +static cairo_status_t +_cairo_pdf_path_close_path (void *closure) +{ + pdf_path_info_t *info = closure; + + _cairo_output_stream_printf (info->output, + "h\r\n"); + + return _cairo_output_stream_get_status (info->output); +} + +cairo_int_status_t +_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule) +{ + const char *pdf_operator; + + if (! path->has_current_point) { + /* construct an empty path */ + _cairo_output_stream_printf (pdf_operators->stream, "0 0 m "); + } else { + pdf_path_info_t info; + cairo_status_t status; + + info.output = pdf_operators->stream; + info.cairo_to_pdf = &pdf_operators->cairo_to_pdf; + info.ctm_inverse = NULL; + + status = _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cairo_pdf_path_move_to, + _cairo_pdf_path_line_to, + _cairo_pdf_path_curve_to, + _cairo_pdf_path_close_path, + &info); + if (status) + return status; + } + + switch (fill_rule) { + case CAIRO_FILL_RULE_WINDING: + pdf_operator = "W"; + break; + case CAIRO_FILL_RULE_EVEN_ODD: + pdf_operator = "W*"; + break; + default: + ASSERT_NOT_REACHED; + } + + _cairo_output_stream_printf (pdf_operators->stream, + "%s n\r\n", + pdf_operator); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} + +static int +_cairo_pdf_line_cap (cairo_line_cap_t cap) +{ + switch (cap) { + case CAIRO_LINE_CAP_BUTT: + return 0; + case CAIRO_LINE_CAP_ROUND: + return 1; + case CAIRO_LINE_CAP_SQUARE: + return 2; + default: + ASSERT_NOT_REACHED; + return 0; + } +} + +static int +_cairo_pdf_line_join (cairo_line_join_t join) +{ + switch (join) { + case CAIRO_LINE_JOIN_MITER: + return 0; + case CAIRO_LINE_JOIN_ROUND: + return 1; + case CAIRO_LINE_JOIN_BEVEL: + return 2; + default: + ASSERT_NOT_REACHED; + return 0; + } +} + +static cairo_int_status_t +_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators, + cairo_stroke_style_t *style) +{ + _cairo_output_stream_printf (pdf_operators->stream, + "%f w\r\n", + style->line_width); + + _cairo_output_stream_printf (pdf_operators->stream, + "%d J\r\n", + _cairo_pdf_line_cap (style->line_cap)); + + _cairo_output_stream_printf (pdf_operators->stream, + "%d j\r\n", + _cairo_pdf_line_join (style->line_join)); + + if (style->num_dashes) { + unsigned int d; + _cairo_output_stream_printf (pdf_operators->stream, "["); + for (d = 0; d < style->num_dashes; d++) + _cairo_output_stream_printf (pdf_operators->stream, " %f", style->dash[d]); + _cairo_output_stream_printf (pdf_operators->stream, "] %f d\r\n", + style->dash_offset); + } else { + _cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\r\n"); + } + + _cairo_output_stream_printf (pdf_operators->stream, + "%f M ", + style->miter_limit); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} + + +cairo_int_status_t +_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators, + cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + cairo_matrix_t *ctm, + cairo_matrix_t *ctm_inverse) +{ + pdf_path_info_t info; + cairo_status_t status; + cairo_matrix_t m; + + status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style); + if (status) + return status; + + info.output = pdf_operators->stream; + info.cairo_to_pdf = NULL; + info.ctm_inverse = ctm_inverse; + + cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf); + _cairo_output_stream_printf (pdf_operators->stream, + "q %f %f %f %f %f %f cm\r\n", + m.xx, m.yx, m.xy, m.yy, + m.x0, m.y0); + + status = _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cairo_pdf_path_move_to, + _cairo_pdf_path_line_to, + _cairo_pdf_path_curve_to, + _cairo_pdf_path_close_path, + &info); + if (status) + return status; + + _cairo_output_stream_printf (pdf_operators->stream, "S Q\r\n"); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} + +cairo_int_status_t +_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule) +{ + const char *pdf_operator; + cairo_status_t status; + pdf_path_info_t info; + + info.output = pdf_operators->stream; + info.cairo_to_pdf = &pdf_operators->cairo_to_pdf; + info.ctm_inverse = NULL; + status = _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cairo_pdf_path_move_to, + _cairo_pdf_path_line_to, + _cairo_pdf_path_curve_to, + _cairo_pdf_path_close_path, + &info); + if (status) + return status; + + switch (fill_rule) { + case CAIRO_FILL_RULE_WINDING: + pdf_operator = "f"; + break; + case CAIRO_FILL_RULE_EVEN_ODD: + pdf_operator = "f*"; + break; + default: + ASSERT_NOT_REACHED; + } + + _cairo_output_stream_printf (pdf_operators->stream, + "%s\r\n", + pdf_operator); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} + +#define GLYPH_POSITION_TOLERANCE 0.001 + +cairo_int_status_t +_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + unsigned int current_subset_id = (unsigned int)-1; + cairo_scaled_font_subsets_glyph_t subset_glyph; + cairo_bool_t diagonal, in_TJ; + cairo_status_t status; + double Tlm_x = 0, Tlm_y = 0; + double Tm_x = 0, y; + int i, hex_width; + + for (i = 0; i < num_glyphs; i++) + cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y); + + _cairo_output_stream_printf (pdf_operators->stream, + "BT\r\n"); + + if (scaled_font->scale.xy == 0.0 && + scaled_font->scale.yx == 0.0) + diagonal = TRUE; + else + diagonal = FALSE; + + in_TJ = FALSE; + for (i = 0; i < num_glyphs; i++) { + status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets, + scaled_font, glyphs[i].index, + &subset_glyph); + if (status) + return status; + + if (subset_glyph.is_composite) + hex_width = 4; + else + hex_width = 2; + + if (subset_glyph.is_scaled == FALSE) { + y = 0.0; + cairo_matrix_transform_distance (&scaled_font->scale, + &subset_glyph.x_advance, + &y); + } + + if (subset_glyph.subset_id != current_subset_id) { + if (in_TJ) { + _cairo_output_stream_printf (pdf_operators->stream, ">] TJ\r\n"); + in_TJ = FALSE; + } + _cairo_output_stream_printf (pdf_operators->stream, + "/f-%d-%d 1 Tf\r\n", + subset_glyph.font_id, + subset_glyph.subset_id); + if (pdf_operators->use_font_subset) { + status = pdf_operators->use_font_subset (subset_glyph.font_id, + subset_glyph.subset_id, + pdf_operators->use_font_subset_closure); + if (status) + return status; + } + } + + if (subset_glyph.subset_id != current_subset_id || !diagonal) { + _cairo_output_stream_printf (pdf_operators->stream, + "%f %f %f %f %f %f Tm\r\n", + scaled_font->scale.xx, + -scaled_font->scale.yx, + -scaled_font->scale.xy, + scaled_font->scale.yy, + glyphs[i].x, + glyphs[i].y); + current_subset_id = subset_glyph.subset_id; + Tlm_x = glyphs[i].x; + Tlm_y = glyphs[i].y; + Tm_x = Tlm_x; + } + + if (diagonal) { + if (i < num_glyphs - 1 && + fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE && + fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10) + { + if (!in_TJ) { + if (i != 0) { + _cairo_output_stream_printf (pdf_operators->stream, + "%f %f Td\r\n", + (glyphs[i].x - Tlm_x)/scaled_font->scale.xx, + (glyphs[i].y - Tlm_y)/scaled_font->scale.yy); + + Tlm_x = glyphs[i].x; + Tlm_y = glyphs[i].y; + Tm_x = Tlm_x; + } + _cairo_output_stream_printf (pdf_operators->stream, + "[<%0*x", + hex_width, + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + in_TJ = TRUE; + } else { + if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) { + double delta = glyphs[i].x - Tm_x; + + _cairo_output_stream_printf (pdf_operators->stream, + "> %f <", + -1000.0*delta/scaled_font->scale.xx); + Tm_x += delta; + } + _cairo_output_stream_printf (pdf_operators->stream, + "%0*x", + hex_width, + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + } + } + else + { + if (in_TJ) { + if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) { + double delta = glyphs[i].x - Tm_x; + + _cairo_output_stream_printf (pdf_operators->stream, + "> %f <", + -1000.0*delta/scaled_font->scale.xx); + Tm_x += delta; + } + _cairo_output_stream_printf (pdf_operators->stream, + "%0*x>] TJ\r\n", + hex_width, + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + in_TJ = FALSE; + } else { + if (i != 0) { + _cairo_output_stream_printf (pdf_operators->stream, + "%f %f Td ", + (glyphs[i].x - Tlm_x)/scaled_font->scale.xx, + (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy); + Tlm_x = glyphs[i].x; + Tlm_y = glyphs[i].y; + Tm_x = Tlm_x; + } + _cairo_output_stream_printf (pdf_operators->stream, + "<%0*x> Tj ", + hex_width, + subset_glyph.subset_glyph_index); + Tm_x += subset_glyph.x_advance; + } + } + } else { + _cairo_output_stream_printf (pdf_operators->stream, + "<%0*x> Tj\r\n", + hex_width, + subset_glyph.subset_glyph_index); + } + } + + _cairo_output_stream_printf (pdf_operators->stream, + "ET\r\n"); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h index 28b6fd1bb481..233b01d0fe53 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h @@ -1,8 +1,9 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2004 Red Hat, Inc * Copyright © 2006 Red Hat, Inc - * Copyright © 2007 Adrian Johnson + * Copyright © 2007, 2008 Adrian Johnson * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -44,6 +45,8 @@ #include "cairo-pdf.h" #include "cairo-surface-private.h" +#include "cairo-pdf-operators-private.h" +#include "cairo-path-fixed-private.h" typedef struct _cairo_pdf_resource { unsigned int id; @@ -57,6 +60,37 @@ typedef struct _cairo_pdf_group_resources { cairo_array_t fonts; } cairo_pdf_group_resources_t; +typedef struct _cairo_pdf_pattern { + cairo_pattern_t *pattern; + cairo_pdf_resource_t pattern_res; + cairo_pdf_resource_t gstate_res; +} cairo_pdf_pattern_t; + +typedef enum _cairo_pdf_operation { + PDF_PAINT, + PDF_MASK, + PDF_FILL, + PDF_STROKE, + PDF_SHOW_GLYPHS +} cairo_pdf_operation_t; + +typedef struct _cairo_pdf_smask_group +{ + cairo_pdf_resource_t group_res; + cairo_pdf_operation_t operation; + cairo_pattern_t *source; + cairo_pdf_resource_t source_res; + cairo_pattern_t *mask; + cairo_path_fixed_t path; + cairo_fill_rule_t fill_rule; + cairo_stroke_style_t *style; + cairo_matrix_t ctm; + cairo_matrix_t ctm_inverse; + cairo_glyph_t *glyphs; + int num_glyphs; + cairo_scaled_font_t *scaled_font; +} cairo_pdf_smask_group_t; + typedef struct _cairo_pdf_surface cairo_pdf_surface_t; struct _cairo_pdf_surface { @@ -74,8 +108,9 @@ struct _cairo_pdf_surface { cairo_array_t pages; cairo_array_t rgb_linear_functions; cairo_array_t alpha_linear_functions; + cairo_array_t patterns; + cairo_array_t smask_groups; cairo_array_t knockout_group; - cairo_array_t content_group; cairo_scaled_font_subsets_t *font_subsets; cairo_array_t fonts; @@ -85,6 +120,11 @@ struct _cairo_pdf_surface { cairo_bool_t compress_content; + cairo_pdf_resource_t content; + cairo_pdf_resource_t content_resources; + cairo_pdf_group_resources_t resources; + cairo_bool_t has_fallback_images; + struct { cairo_bool_t active; cairo_pdf_resource_t self; @@ -99,32 +139,11 @@ struct _cairo_pdf_surface { cairo_output_stream_t *stream; cairo_output_stream_t *mem_stream; cairo_output_stream_t *old_output; - cairo_pdf_group_resources_t resources; + cairo_pdf_resource_t resource; cairo_bool_t is_knockout; - cairo_pdf_resource_t first_object; } group_stream; - struct { - cairo_bool_t active; - cairo_output_stream_t *stream; - cairo_output_stream_t *mem_stream; - cairo_output_stream_t *old_output; - cairo_pdf_group_resources_t resources; - } content_stream; - - struct { - cairo_pattern_type_t type; - double red; - double green; - double blue; - double alpha; - cairo_pdf_resource_t smask; - cairo_pdf_resource_t pattern; - } emitted_pattern; - - cairo_array_t *current_group; - cairo_pdf_group_resources_t *current_resources; - + cairo_pdf_operators_t pdf_operators; cairo_paginated_mode_t paginated_mode; cairo_bool_t force_fallbacks; diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface.c b/gfx/cairo/cairo/src/cairo-pdf-surface.c index 695e6e952f7b..77fd95b997c0 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface.c +++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c @@ -1,8 +1,9 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2004 Red Hat, Inc * Copyright © 2006 Red Hat, Inc - * Copyright © 2007 Adrian Johnson + * Copyright © 2007, 2008 Adrian Johnson * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -41,9 +42,9 @@ #include "cairoint.h" #include "cairo-pdf.h" #include "cairo-pdf-surface-private.h" +#include "cairo-pdf-operators-private.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-paginated-private.h" -#include "cairo-path-fixed-private.h" #include "cairo-output-stream-private.h" #include "cairo-meta-surface-private.h" @@ -87,37 +88,6 @@ * that fallback images do not composite with any content under the * fallback images. * - * The group containing the supported operations (content_group_list - * in the example below) does not do any drawing directly. Instead it - * paints groups containing the drawing operations and performs - * clipping. The reason for this is that clipping operations performed - * in a group do not affect the parent group. - * - * Example PDF Page Structure: - * - * Page Content - * ------------ - * /knockout_group Do - * - * knockout_group - * -------------- - * /content_group_list Do - * /fallback_image_1 Do - * /fallback_image_2 Do - * ... - * - * content_group_list - * ------------------ - * q - * /content_group_1 Do - * /content_group_2 Do - * 10 10 m 10 20 l 20 20 l 20 10 l h W # clip - * /content_group_3 Do - * Q q # reset clip - * /content_group_4 Do - * Q - * - * * Streams: * * This PDF surface has three types of streams: @@ -130,7 +100,7 @@ * * PDF Stream: * A PDF Stream may be opened and closed with the following functions: - * _cairo_pdf_surface_open_stream () + * _cairo_pdf_surface_open stream () * _cairo_pdf_surface_close_stream () * * PDF Streams are written directly to the PDF file. They are used for @@ -138,49 +108,23 @@ * * Content Stream: * The Content Stream is opened and closed with the following functions: - * _cairo_pdf_surface_start_content_stream () - * _cairo_pdf_surface_stop_content_stream () + * _cairo_pdf_surface_open_content_stream () + * _cairo_pdf_surface_close_content_stream () * - * The Content Stream is written to content_group_n groups (as shown - * in the page structure example). The Content Stream may be paused - * and resumed with the following functions: - * _cairo_pdf_surface_pause_content_stream () - * _cairo_pdf_surface_resume_content_stream () - * - * When the Content Stream is paused, a PDF Stream or Group Stream - * may be opened. After closing the PDF Stream or Group Stream the - * Content Stream may be resumed. - * - * The Content Stream contains the text and graphics operators. When - * a pattern is required the Content Stream is paused, a PDF Stream - * is opened, the pattern is written to a PDF Stream, the PDF Stream - * is closed, then the Content Stream is resumed. - * - * Each group comprising the Content Stream is stored in memory - * until the stream is closed or the maximum group size is - * exceeded. This is due to the need to list all resources used in - * the group in the group's stream dictionary. + * The Content Stream contains the text and graphics operators. * * Group Stream: * A Group Stream may be opened and closed with the following functions: * _cairo_pdf_surface_open_group () * _cairo_pdf_surface_close_group () * - * A Group Stream is written to a separate group in the PDF file - * that is not part of the Content Stream. Group Streams are also - * stored in memory until the stream is closed due to the need to - * list the resources used in the group in the group's stream - * dictionary. - * - * Group Streams are used for short sequences of graphics operations - * that need to be in a separate group from the Content Stream. + * A Group Stream is a Form XObject. It is used for short sequences + * of operators. As the content is very short the group is stored in + * memory until it is closed. This allows some optimization such as + * including the Resource dictionary and stream length inside the + * XObject instead of using an indirect object. */ -/* The group stream length is checked after each operation. When this - * limit is exceeded the group is written out to the pdf stream and a - * new group is created. */ -#define GROUP_STREAM_LIMIT 65536 - typedef struct _cairo_pdf_object { long offset; } cairo_pdf_object_t; @@ -203,36 +147,29 @@ typedef struct _cairo_pdf_alpha_linear_function { double alpha2; } cairo_pdf_alpha_linear_function_t; -typedef enum group_element_type { - ELEM_GROUP, - ELEM_CLIP -} group_element_type_t; - -typedef struct _cairo_pdf_group_element { - group_element_type_t type; - cairo_pdf_resource_t group; - cairo_path_fixed_t *clip_path; - cairo_fill_rule_t fill_rule; -} cairo_pdf_group_element_t; - - static cairo_pdf_resource_t _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface); -static void -_cairo_pdf_group_element_array_finish (cairo_array_t *array); - static void _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface); +static void +_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group); + +static cairo_status_t +_cairo_pdf_surface_add_font (unsigned int font_id, + unsigned int subset_id, + void *closure); + static void _cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res); -static cairo_pdf_resource_t +static cairo_status_t _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, + cairo_pdf_resource_t *resource, cairo_bool_t compressed, const char *fmt, - ...) CAIRO_PRINTF_FORMAT(3, 4); + ...) CAIRO_PRINTF_FORMAT(4, 5); static cairo_status_t _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface); @@ -251,11 +188,6 @@ _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface); static long _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface); -static cairo_status_t -_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule); - static cairo_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); @@ -302,21 +234,19 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, double height) { cairo_pdf_surface_t *surface; - cairo_status_t status; + cairo_status_t status, status_ignored; surface = malloc (sizeof (cairo_pdf_surface_t)); if (surface == NULL) { /* destroy stream on behalf of caller */ status = _cairo_output_stream_destroy (output); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend, CAIRO_CONTENT_COLOR_ALPHA); surface->output = output; - surface->width = width; surface->height = height; cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height); @@ -326,40 +256,44 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t)); _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t)); _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t)); - _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_group_element_t)); - _cairo_array_init (&surface->content_group, sizeof (cairo_pdf_group_element_t)); + _cairo_array_init (&surface->patterns, sizeof (cairo_pdf_pattern_t)); + _cairo_array_init (&surface->smask_groups, sizeof (cairo_pdf_smask_group_t *)); + _cairo_array_init (&surface->knockout_group, sizeof (cairo_pdf_resource_t)); - _cairo_pdf_group_resources_init (&surface->group_stream.resources); - _cairo_pdf_group_resources_init (&surface->content_stream.resources); + _cairo_pdf_group_resources_init (&surface->resources); surface->font_subsets = _cairo_scaled_font_subsets_create_composite (); if (! surface->font_subsets) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL0; } surface->next_available_resource.id = 1; surface->pages_resource = _cairo_pdf_surface_new_object (surface); - if (surface->pages_resource.id == 0) + if (surface->pages_resource.id == 0) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL1; + } surface->compress_content = TRUE; surface->pdf_stream.active = FALSE; surface->pdf_stream.old_output = NULL; - surface->content_stream.active = FALSE; - surface->content_stream.stream = NULL; - surface->content_stream.mem_stream = NULL; surface->group_stream.active = FALSE; surface->group_stream.stream = NULL; surface->group_stream.mem_stream = NULL; - surface->current_group = NULL; - surface->current_resources = NULL; - surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; surface->force_fallbacks = FALSE; + _cairo_pdf_operators_init (&surface->pdf_operators, + surface->output, + surface->cairo_to_pdf, + surface->font_subsets); + _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators, + _cairo_pdf_surface_add_font, + surface); + /* Document header */ _cairo_output_stream_printf (surface->output, "%%PDF-1.4\r\n"); @@ -371,7 +305,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, CAIRO_CONTENT_COLOR_ALPHA, width, height, &cairo_pdf_surface_paginated_backend); - if (surface->paginated_surface->status == CAIRO_STATUS_SUCCESS) + status = surface->paginated_surface->status; + if (status == CAIRO_STATUS_SUCCESS) return surface->paginated_surface; BAIL1: @@ -381,9 +316,9 @@ BAIL0: free (surface); /* destroy stream on behalf of caller */ - status = _cairo_output_stream_destroy (output); + status_ignored = _cairo_output_stream_destroy (output); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); } /** @@ -412,13 +347,11 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, double width_in_points, double height_in_points) { - cairo_status_t status; cairo_output_stream_t *output; output = _cairo_output_stream_create (write_func, NULL, closure); - status = _cairo_output_stream_get_status (output); - if (status) - return (cairo_surface_t*) &_cairo_surface_nil; + if (_cairo_output_stream_get_status (output)) + return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output)); return _cairo_pdf_surface_create_for_stream_internal (output, width_in_points, @@ -449,15 +382,11 @@ cairo_pdf_surface_create (const char *filename, double width_in_points, double height_in_points) { - cairo_status_t status; cairo_output_stream_t *output; output = _cairo_output_stream_create_for_filename (filename); - status = _cairo_output_stream_get_status (output); - if (status) - return (status == CAIRO_STATUS_WRITE_ERROR) ? - (cairo_surface_t*) &_cairo_surface_nil_write_error : - (cairo_surface_t*) &_cairo_surface_nil; + if (_cairo_output_stream_get_status (output)) + return _cairo_surface_create_in_error (_cairo_output_stream_destroy (output)); return _cairo_pdf_surface_create_for_stream_internal (output, width_in_points, @@ -527,6 +456,8 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface, pdf_surface->width = width_in_points; pdf_surface->height = height_in_points; cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points); + _cairo_pdf_operators_set_cairo_to_pdf_matrix (&pdf_surface->pdf_operators, + pdf_surface->cairo_to_pdf); status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface, width_in_points, height_in_points); @@ -537,9 +468,23 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface, static void _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) { - _cairo_pdf_group_element_array_finish (&surface->content_group); - _cairo_pdf_group_element_array_finish (&surface->knockout_group); - _cairo_array_truncate (&surface->content_group, 0); + int i, size; + cairo_pdf_pattern_t *pattern; + cairo_pdf_smask_group_t *group; + + size = _cairo_array_num_elements (&surface->patterns); + for (i = 0; i < size; i++) { + pattern = (cairo_pdf_pattern_t *) _cairo_array_index (&surface->patterns, i); + cairo_pattern_destroy (pattern->pattern); + } + _cairo_array_truncate (&surface->patterns, 0); + + size = _cairo_array_num_elements (&surface->smask_groups); + for (i = 0; i < size; i++) { + _cairo_array_copy_element (&surface->smask_groups, i, &group); + _cairo_pdf_smask_group_destroy (group); + } + _cairo_array_truncate (&surface->smask_groups, 0); _cairo_array_truncate (&surface->knockout_group, 0); } @@ -581,7 +526,7 @@ _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface, int num_alphas, i; double other; cairo_status_t status; - cairo_pdf_group_resources_t *res = surface->current_resources; + cairo_pdf_group_resources_t *res = &surface->resources; num_alphas = _cairo_array_num_elements (&res->alphas); for (i = 0; i < num_alphas; i++) { @@ -605,32 +550,33 @@ static cairo_status_t _cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface, cairo_pdf_resource_t smask) { - return _cairo_array_append (&surface->current_resources->smasks, &smask); + return _cairo_array_append (&(surface->resources.smasks), &smask); } static cairo_status_t _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface, cairo_pdf_resource_t pattern) { - return _cairo_array_append (&surface->current_resources->patterns, &pattern); + return _cairo_array_append (&(surface->resources.patterns), &pattern); } static cairo_status_t _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface, cairo_pdf_resource_t xobject) { - return _cairo_array_append (&surface->current_resources->xobjects, &xobject); + return _cairo_array_append (&(surface->resources.xobjects), &xobject); } static cairo_status_t -_cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface, - unsigned int font_id, - unsigned int subset_id) +_cairo_pdf_surface_add_font (unsigned int font_id, + unsigned int subset_id, + void *closure) { + cairo_pdf_surface_t *surface = closure; cairo_pdf_font_t font; int num_fonts, i; cairo_status_t status; - cairo_pdf_group_resources_t *res = surface->current_resources; + cairo_pdf_group_resources_t *res = &surface->resources; num_fonts = _cairo_array_num_elements (&res->fonts); for (i = 0; i < num_fonts; i++) { @@ -668,7 +614,6 @@ _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface, { cairo_pdf_font_t font; int num_fonts, i; - cairo_pdf_resource_t resource; num_fonts = _cairo_array_num_elements (&surface->fonts); for (i = 0; i < num_fonts; i++) { @@ -676,9 +621,9 @@ _cairo_pdf_surface_get_font_resource (cairo_pdf_surface_t *surface, if (font.font_id == font_id && font.subset_id == subset_id) return font.subset_resource; } - resource.id = 0; - return resource; + font.subset_resource.id = 0; + return font.subset_resource; } static void @@ -690,36 +635,36 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface, cairo_pdf_resource_t *smask, *pattern, *xobject; cairo_pdf_font_t *font; - _cairo_output_stream_printf (surface->output, " /Resources <<\r\n"); + _cairo_output_stream_printf (surface->output, "<<\r\n"); num_alphas = _cairo_array_num_elements (&res->alphas); num_smasks = _cairo_array_num_elements (&res->smasks); if (num_alphas > 0 || num_smasks > 0) { _cairo_output_stream_printf (surface->output, - " /ExtGState <<\r\n"); + " /ExtGState <<\r\n"); for (i = 0; i < num_alphas; i++) { _cairo_array_copy_element (&res->alphas, i, &alpha); _cairo_output_stream_printf (surface->output, - " /a%d << /CA %f /ca %f >>\r\n", + " /a%d << /CA %f /ca %f >>\r\n", i, alpha, alpha); } for (i = 0; i < num_smasks; i++) { smask = _cairo_array_index (&res->smasks, i); _cairo_output_stream_printf (surface->output, - " /s%d %d 0 R\r\n", + " /s%d %d 0 R\r\n", smask->id, smask->id); } _cairo_output_stream_printf (surface->output, - " >>\r\n"); + " >>\r\n"); } num_resources = _cairo_array_num_elements (&res->patterns); if (num_resources > 0) { _cairo_output_stream_printf (surface->output, - " /Pattern <<"); + " /Pattern <<"); for (i = 0; i < num_resources; i++) { pattern = _cairo_array_index (&res->patterns, i); _cairo_output_stream_printf (surface->output, @@ -734,7 +679,7 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface, num_resources = _cairo_array_num_elements (&res->xobjects); if (num_resources > 0) { _cairo_output_stream_printf (surface->output, - " /XObject <<"); + " /XObject <<"); for (i = 0; i < num_resources; i++) { xobject = _cairo_array_index (&res->xobjects, i); @@ -749,24 +694,127 @@ _cairo_pdf_surface_emit_group_resources (cairo_pdf_surface_t *surface, num_resources = _cairo_array_num_elements (&res->fonts); if (num_resources > 0) { - _cairo_output_stream_printf (surface->output," /Font <<\r\n"); + _cairo_output_stream_printf (surface->output," /Font <<\r\n"); for (i = 0; i < num_resources; i++) { font = _cairo_array_index (&res->fonts, i); _cairo_output_stream_printf (surface->output, - " /f-%d-%d %d 0 R\r\n", + " /f-%d-%d %d 0 R\r\n", font->font_id, font->subset_id, font->subset_resource.id); } - _cairo_output_stream_printf (surface->output, " >>\r\n"); + _cairo_output_stream_printf (surface->output, " >>\r\n"); } _cairo_output_stream_printf (surface->output, - " >>\r\n"); + ">>\r\n"); } -static cairo_pdf_resource_t +static cairo_pdf_smask_group_t * +_cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface) +{ + cairo_pdf_smask_group_t *group; + + group = calloc (1, sizeof (cairo_pdf_smask_group_t)); + if (group == NULL) { + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return NULL; + } + + group->group_res = _cairo_pdf_surface_new_object (surface); + if (group->group_res.id == 0) { + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + free (group); + return NULL; + } + + return group; +} + +static void +_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group) +{ + if (group->operation == PDF_FILL || group->operation == PDF_STROKE) + _cairo_path_fixed_fini (&group->path); + if (group->source) + cairo_pattern_destroy (group->source); + if (group->mask) + cairo_pattern_destroy (group->mask); + if (group->scaled_font) + cairo_scaled_font_destroy (group->scaled_font); + free (group); +} + +static cairo_status_t +_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface, + cairo_pdf_smask_group_t *group) +{ + return _cairo_array_append (&surface->smask_groups, &group); +} + +static cairo_status_t +_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface, + cairo_pattern_t *pattern, + cairo_pdf_resource_t *pattern_res, + cairo_pdf_resource_t *gstate_res) +{ + cairo_pdf_pattern_t pdf_pattern; + cairo_status_t status; + + /* Solid colors are emitted into the content stream */ + if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { + pattern_res->id = 0; + gstate_res->id = 0; + return CAIRO_STATUS_SUCCESS; + } + + /* Gradients with zero stops do not produce any output */ + if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || + pattern->type == CAIRO_PATTERN_TYPE_RADIAL) + { + cairo_gradient_pattern_t *gradient; + + gradient = (cairo_gradient_pattern_t *) pattern; + if (gradient->n_stops == 0) + return CAIRO_INT_STATUS_NOTHING_TO_DO; + } + + pdf_pattern.pattern = cairo_pattern_reference (pattern); + pdf_pattern.pattern_res = _cairo_pdf_surface_new_object (surface); + if (pdf_pattern.pattern_res.id == 0) { + cairo_pattern_destroy (pattern); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + pdf_pattern.gstate_res.id = 0; + + /* gradient patterns require an smask object to implement transparency */ + if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || + pattern->type == CAIRO_PATTERN_TYPE_RADIAL) { + if (_cairo_pattern_is_opaque (pattern) == FALSE) { + pdf_pattern.gstate_res = _cairo_pdf_surface_new_object (surface); + if (pdf_pattern.gstate_res.id == 0) { + cairo_pattern_destroy (pattern); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + } + } + + *pattern_res = pdf_pattern.pattern_res; + *gstate_res = pdf_pattern.gstate_res; + + status = _cairo_array_append (&surface->patterns, &pdf_pattern); + if (status) { + cairo_pattern_destroy (pattern); + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, + cairo_pdf_resource_t *resource, cairo_bool_t compressed, const char *fmt, ...) @@ -775,20 +823,23 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, cairo_pdf_resource_t self, length; cairo_output_stream_t *output = NULL; - self = _cairo_pdf_surface_new_object (surface); - if (self.id == 0) - return self; + if (resource) { + self = *resource; + _cairo_pdf_surface_update_object (surface, self); + } else { + self = _cairo_pdf_surface_new_object (surface); + if (self.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } length = _cairo_pdf_surface_new_object (surface); if (length.id == 0) - return length; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (compressed) { output = _cairo_deflate_stream_create (surface->output); - if (_cairo_output_stream_get_status (output)) { - self.id = 0; - return self; - } + if (_cairo_output_stream_get_status (output)) + return _cairo_output_stream_destroy (output); } surface->pdf_stream.active = TRUE; @@ -821,9 +872,10 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, assert (surface->pdf_stream.old_output == NULL); surface->pdf_stream.old_output = surface->output; surface->output = output; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); } - return surface->pdf_stream.self; + return _cairo_output_stream_get_status (surface->output); } static cairo_status_t @@ -838,6 +890,7 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface) if (surface->pdf_stream.compressed) { status = _cairo_output_stream_destroy (surface->output); surface->output = surface->pdf_stream.old_output; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); surface->pdf_stream.old_output = NULL; _cairo_output_stream_printf (surface->output, "\r\n"); @@ -860,26 +913,26 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface) surface->pdf_stream.active = FALSE; + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_output_stream_get_status (surface->output); + return status; } -static cairo_pdf_resource_t +static void _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface, cairo_output_stream_t *mem_stream, + cairo_pdf_resource_t resource, cairo_pdf_group_resources_t *resources, cairo_bool_t is_knockout_group) { - cairo_pdf_resource_t group; - - group = _cairo_pdf_surface_new_object (surface); - if (group.id == 0) - return group; + _cairo_pdf_surface_update_object (surface, resource); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" "<< /Type /XObject\r\n" " /Length %d\r\n", - group.id, + resource.id, _cairo_memory_stream_length (mem_stream)); if (surface->compress_content) { @@ -898,11 +951,12 @@ _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface, surface->height); if (is_knockout_group) - _cairo_output_stream_printf (surface->output, - " /K true\r\n"); + _cairo_output_stream_printf (surface->output, + " /K true\r\n"); _cairo_output_stream_printf (surface->output, - " >>\r\n"); + " >>\r\n" + " /Resources\r\n"); _cairo_pdf_surface_emit_group_resources (surface, resources); _cairo_output_stream_printf (surface->output, ">>\r\n" @@ -911,17 +965,15 @@ _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, "endstream\r\n" "endobj\r\n"); - - return group; } static cairo_status_t -_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface) +_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface, + cairo_pdf_resource_t *resource) { cairo_status_t status; assert (surface->pdf_stream.active == FALSE); - assert (surface->content_stream.active == FALSE); assert (surface->group_stream.active == FALSE); surface->group_stream.active = TRUE; @@ -935,30 +987,34 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface) surface->group_stream.stream = surface->group_stream.mem_stream; } status = _cairo_output_stream_get_status (surface->group_stream.stream); - if (status) - return status; surface->group_stream.old_output = surface->output; surface->output = surface->group_stream.stream; - _cairo_pdf_group_resources_clear (&surface->group_stream.resources); - surface->current_resources = &surface->group_stream.resources; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); + _cairo_pdf_group_resources_clear (&surface->resources); + + if (resource) { + surface->group_stream.resource = *resource; + } else { + surface->group_stream.resource = _cairo_pdf_surface_new_object (surface); + if (surface->group_stream.resource.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } surface->group_stream.is_knockout = FALSE; - return CAIRO_STATUS_SUCCESS; + return status; } static cairo_status_t -_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t *first_object) +_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface) { cairo_status_t status; - status = _cairo_pdf_surface_open_group (surface); + status = _cairo_pdf_surface_open_group (surface, NULL); if (status) return status; surface->group_stream.is_knockout = TRUE; - surface->group_stream.first_object = *first_object; return CAIRO_STATUS_SUCCESS; } @@ -967,209 +1023,110 @@ static cairo_status_t _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface, cairo_pdf_resource_t *group) { - cairo_status_t status; + cairo_status_t status = CAIRO_STATUS_SUCCESS, status2; assert (surface->pdf_stream.active == FALSE); assert (surface->group_stream.active == TRUE); if (surface->compress_content) { status = _cairo_output_stream_destroy (surface->group_stream.stream); - if (status) - return status; + surface->group_stream.stream = NULL; _cairo_output_stream_printf (surface->group_stream.mem_stream, "\r\n"); } surface->output = surface->group_stream.old_output; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); surface->group_stream.active = FALSE; - *group = _cairo_pdf_surface_write_memory_stream (surface, - surface->group_stream.mem_stream, - &surface->group_stream.resources, - surface->group_stream.is_knockout); - if (group->id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_pdf_surface_write_memory_stream (surface, + surface->group_stream.mem_stream, + surface->group_stream.resource, + &surface->resources, + surface->group_stream.is_knockout); + if (group) + *group = surface->group_stream.resource; - return _cairo_output_stream_close (surface->group_stream.mem_stream); + status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + + surface->group_stream.mem_stream = NULL; + surface->group_stream.stream = NULL; + + return status; } static cairo_status_t -_cairo_pdf_surface_write_group_list (cairo_pdf_surface_t *surface, - cairo_array_t *group_list) +_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, + cairo_bool_t is_form) { - int i, len; - cairo_pdf_group_element_t *elem; cairo_status_t status; - _cairo_output_stream_printf (surface->output, "q\r\n"); - if (surface->group_stream.is_knockout) { - _cairo_output_stream_printf (surface->output, - "/x%d Do\r\n", - surface->group_stream.first_object.id); - status = _cairo_pdf_surface_add_xobject (surface, surface->group_stream.first_object); + assert (surface->pdf_stream.active == FALSE); + assert (surface->group_stream.active == FALSE); + + surface->content_resources = _cairo_pdf_surface_new_object (surface); + if (surface->content_resources.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + if (is_form) { + status = + _cairo_pdf_surface_open_stream (surface, + NULL, + surface->compress_content, + " /Type /XObject\r\n" + " /Subtype /Form\r\n" + " /BBox [ 0 0 %f %f ]\r\n" + " /Group <<\r\n" + " /Type /Group\r\n" + " /S /Transparency\r\n" + " /CS /DeviceRGB\r\n" + " >>\r\n" + " /Resources %d 0 R\r\n", + surface->width, + surface->height, + surface->content_resources.id); + if (status) + return status; + } else { + status = + _cairo_pdf_surface_open_stream (surface, + NULL, + surface->compress_content, + NULL); if (status) return status; } - len = _cairo_array_num_elements (group_list); - for (i = 0; i < len; i++) { - elem = _cairo_array_index (group_list, i); - if (elem->type == ELEM_GROUP) { - _cairo_output_stream_printf (surface->output, - "/x%d Do\r\n", - elem->group.id); - status = _cairo_pdf_surface_add_xobject (surface, elem->group); - if (status) - return status; - } else if (elem->type == ELEM_CLIP) { - status = _cairo_pdf_surface_emit_clip (surface, elem->clip_path, elem->fill_rule); - if (status) - return status; - } - } - _cairo_output_stream_printf (surface->output, "Q\r\n"); - return CAIRO_STATUS_SUCCESS; + surface->content = surface->pdf_stream.self; + + _cairo_output_stream_printf (surface->output, "q\r\n"); + + return _cairo_output_stream_get_status (surface->output); } static cairo_status_t -_cairo_pdf_surface_start_content_stream (cairo_pdf_surface_t *surface) +_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface) { cairo_status_t status; - if (surface->content_stream.active) - return CAIRO_STATUS_SUCCESS; - - assert (surface->pdf_stream.active == FALSE); - assert (surface->content_stream.active == FALSE); + assert (surface->pdf_stream.active == TRUE); assert (surface->group_stream.active == FALSE); - surface->content_stream.active = TRUE; - surface->content_stream.mem_stream = _cairo_memory_stream_create (); - - if (surface->compress_content) { - surface->content_stream.stream = - _cairo_deflate_stream_create (surface->content_stream.mem_stream); - } else { - surface->content_stream.stream = surface->content_stream.mem_stream; - } - status = _cairo_output_stream_get_status (surface->content_stream.stream); + _cairo_output_stream_printf (surface->output, "Q\r\n"); + status = _cairo_pdf_surface_close_stream (surface); if (status) return status; - surface->content_stream.old_output = surface->output; - surface->output = surface->content_stream.stream; - _cairo_pdf_group_resources_clear (&surface->content_stream.resources); - surface->current_resources = &surface->content_stream.resources; + _cairo_pdf_surface_update_object (surface, surface->content_resources); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n", + surface->content_resources.id); + _cairo_pdf_surface_emit_group_resources (surface, &surface->resources); + _cairo_output_stream_printf (surface->output, + "endobj\r\n"); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_surface_add_group_to_content_stream (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t group) -{ - cairo_pdf_group_element_t elem; - - memset (&elem, 0, sizeof elem); - elem.type = ELEM_GROUP; - elem.group = group; - - return _cairo_array_append (surface->current_group, &elem); -} - -static void -_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface) -{ - assert (surface->pdf_stream.active == FALSE); - - if (surface->content_stream.active == FALSE) - return; - - surface->output = surface->content_stream.old_output; - surface->content_stream.active = FALSE; -} - -static void -_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface) -{ - assert (surface->pdf_stream.active == FALSE); - - if (surface->content_stream.active == TRUE) - return; - - surface->output = surface->content_stream.stream; - surface->current_resources = &surface->content_stream.resources; - surface->content_stream.active = TRUE; -} - -static cairo_status_t -_cairo_pdf_surface_stop_content_stream (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t group; - cairo_status_t status; - - assert (surface->pdf_stream.active == FALSE); - assert (surface->content_stream.active == TRUE); - - if (surface->compress_content) { - status = _cairo_output_stream_destroy (surface->content_stream.stream); - if (status) - return status; - - _cairo_output_stream_printf (surface->content_stream.mem_stream, - "\r\n"); - } - surface->output = surface->content_stream.old_output; - surface->content_stream.active = FALSE; - if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > 0) { - group = _cairo_pdf_surface_write_memory_stream (surface, - surface->content_stream.mem_stream, - &surface->content_stream.resources, - FALSE); - if (group.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_pdf_surface_add_group_to_content_stream (surface, group); - if (status) - return status; - } - surface->content_stream.active = FALSE; - - return _cairo_output_stream_close (surface->content_stream.mem_stream); -} - -static cairo_status_t -_cairo_pdf_surface_check_content_stream_size (cairo_pdf_surface_t *surface) -{ - cairo_status_t status; - - if (surface->content_stream.active == FALSE) - return CAIRO_STATUS_SUCCESS; - - if (_cairo_memory_stream_length (surface->content_stream.mem_stream) > GROUP_STREAM_LIMIT) { - status = _cairo_pdf_surface_stop_content_stream (surface); - if (status) - return status; - - status = _cairo_pdf_surface_start_content_stream (surface); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_pdf_group_element_array_finish (cairo_array_t *array) -{ - int i, len; - cairo_pdf_group_element_t *elem; - - len = _cairo_array_num_elements (array); - for (i = 0; i < len; i++) { - elem = _cairo_array_index (array, i); - if (elem->type == ELEM_CLIP && elem->clip_path) - _cairo_path_fixed_destroy (elem->clip_path); - } + return _cairo_output_stream_get_status (surface->output); } static cairo_surface_t * @@ -1184,12 +1141,14 @@ _cairo_pdf_surface_create_similar (void *abstract_surface, static cairo_status_t _cairo_pdf_surface_finish (void *abstract_surface) { - cairo_status_t status, status2; cairo_pdf_surface_t *surface = abstract_surface; long offset; cairo_pdf_resource_t info, catalog; + cairo_status_t status, status2; - status = _cairo_pdf_surface_emit_font_subsets (surface); + status = surface->base.status; + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_pdf_surface_emit_font_subsets (surface); _cairo_pdf_surface_write_pages (surface); @@ -1219,25 +1178,45 @@ _cairo_pdf_surface_finish (void *abstract_surface) "%%%%EOF\r\n", offset); + _cairo_pdf_operators_fini (&surface->pdf_operators); + + /* close any active streams still open due to fatal errors */ + status2 = _cairo_pdf_surface_close_stream (surface); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + + if (surface->group_stream.stream != NULL) { + status2 = _cairo_output_stream_destroy (surface->group_stream.stream); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + } + if (surface->group_stream.mem_stream != NULL) { + status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream); + if (status == CAIRO_STATUS_SUCCESS) + status = status2; + } + if (surface->pdf_stream.active) + surface->output = surface->pdf_stream.old_output; + if (surface->group_stream.active) + surface->output = surface->group_stream.old_output; + + /* and finish the pdf surface */ status2 = _cairo_output_stream_destroy (surface->output); if (status == CAIRO_STATUS_SUCCESS) status = status2; + _cairo_pdf_surface_clear (surface); + _cairo_pdf_group_resources_fini (&surface->resources); + _cairo_array_fini (&surface->objects); _cairo_array_fini (&surface->pages); _cairo_array_fini (&surface->rgb_linear_functions); _cairo_array_fini (&surface->alpha_linear_functions); + _cairo_array_fini (&surface->patterns); + _cairo_array_fini (&surface->smask_groups); _cairo_array_fini (&surface->fonts); - - _cairo_pdf_group_resources_fini (&surface->group_stream.resources); - _cairo_pdf_group_resources_fini (&surface->content_stream.resources); - - _cairo_pdf_group_element_array_finish (&surface->knockout_group); _cairo_array_fini (&surface->knockout_group); - _cairo_pdf_group_element_array_finish (&surface->content_group); - _cairo_array_fini (&surface->content_group); - if (surface->font_subsets) { _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; @@ -1252,12 +1231,12 @@ _cairo_pdf_surface_start_page (void *abstract_surface) cairo_status_t status; cairo_pdf_surface_t *surface = abstract_surface; - surface->current_group = &surface->content_group; - status = _cairo_pdf_surface_start_content_stream (surface); + surface->has_fallback_images = FALSE; + _cairo_pdf_group_resources_clear (&surface->resources); + status = _cairo_pdf_surface_open_content_stream (surface, TRUE); if (status) return status; - return CAIRO_STATUS_SUCCESS; } @@ -1305,11 +1284,13 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface, uint8_t a; int src_bit, dst_bit; - /* This is the only image format we support, which simplfies things. */ + /* This is the only image format we support, which simplifies things. */ assert (image->format == CAIRO_FORMAT_ARGB32 || image->format == CAIRO_FORMAT_A8 || image->format == CAIRO_FORMAT_A1 ); + stream_ret->id = 0; + if (image->format == CAIRO_FORMAT_A1) alpha_size = (image->height * image->width + 7)/8; else @@ -1366,10 +1347,8 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface, } /* Bail out without emitting smask if it's all opaque. */ - if (opaque) { - stream_ret->id = 0; + if (opaque) goto CLEANUP_ALPHA; - } alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size); if (alpha_compressed == NULL) { @@ -1377,21 +1356,22 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface, goto CLEANUP_ALPHA; } - *stream_ret = _cairo_pdf_surface_open_stream (surface, - FALSE, - " /Type /XObject\r\n" - " /Subtype /Image\r\n" - " /Width %d\r\n" - " /Height %d\r\n" - " /ColorSpace /DeviceGray\r\n" - " /BitsPerComponent %d\r\n" - " /Filter /FlateDecode\r\n", - image->width, image->height, - image->format == CAIRO_FORMAT_A1 ? 1 : 8); - if (stream_ret->id == 0) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_pdf_surface_open_stream (surface, + NULL, + FALSE, + " /Type /XObject\r\n" + " /Subtype /Image\r\n" + " /Width %d\r\n" + " /Height %d\r\n" + " /ColorSpace /DeviceGray\r\n" + " /BitsPerComponent %d\r\n" + " /Filter /FlateDecode\r\n", + image->width, image->height, + image->format == CAIRO_FORMAT_A1 ? 1 : 8); + if (status) goto CLEANUP_ALPHA_COMPRESSED; - } + + *stream_ret = surface->pdf_stream.self; _cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size); _cairo_output_stream_printf (surface->output, "\r\n"); @@ -1503,24 +1483,26 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface, " /Filter /FlateDecode\r\n" if (need_smask) - *image_ret = _cairo_pdf_surface_open_stream (surface, - FALSE, - IMAGE_DICTIONARY - " /SMask %d 0 R\r\n", - image->width, image->height, - smask.id); + status = _cairo_pdf_surface_open_stream (surface, + NULL, + FALSE, + IMAGE_DICTIONARY + " /SMask %d 0 R\r\n", + image->width, image->height, + smask.id); else - *image_ret = _cairo_pdf_surface_open_stream (surface, - FALSE, - IMAGE_DICTIONARY, - image->width, image->height); - if (image_ret->id == 0){ - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_pdf_surface_open_stream (surface, + NULL, + FALSE, + IMAGE_DICTIONARY, + image->width, image->height); + if (status) goto CLEANUP_COMPRESSED; - } #undef IMAGE_DICTIONARY + *image_ret = surface->pdf_stream.self; + _cairo_output_stream_write (surface->output, compressed, compressed_size); _cairo_output_stream_printf (surface->output, "\r\n"); status = _cairo_pdf_surface_close_stream (surface); @@ -1540,22 +1522,13 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, int *width, int *height) { - cairo_surface_t *pat_surface; - cairo_surface_attributes_t pat_attr; cairo_image_surface_t *image; void *image_extra; - cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_status_t status; - status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern, - (cairo_surface_t *)surface, - 0, 0, -1, -1, - &pat_surface, &pat_attr); + status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); if (status) - return status; - - status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra); - if (status) - goto BAIL2; + goto BAIL; status = _cairo_pdf_surface_emit_image (surface, image, resource); if (status) @@ -1565,9 +1538,7 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, *height = image->height; BAIL: - _cairo_surface_release_source_image (pat_surface, image, image_extra); -BAIL2: - _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr); + _cairo_surface_release_source_image (pattern->surface, image, image_extra); return status; } @@ -1577,11 +1548,10 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface, cairo_surface_t *meta_surface, cairo_pdf_resource_t *resource) { - cairo_array_t group; - cairo_array_t *old_group; double old_width, old_height; cairo_matrix_t old_cairo_to_pdf; - cairo_rectangle_int16_t meta_extents; + cairo_paginated_mode_t old_paginated_mode; + cairo_rectangle_int_t meta_extents; cairo_status_t status; int alpha = 0; @@ -1589,25 +1559,27 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface, if (status) return status; - _cairo_pdf_surface_resume_content_stream (surface); - status = _cairo_pdf_surface_stop_content_stream (surface); - if (status) - return status; - - _cairo_array_init (&group, sizeof (cairo_pdf_group_element_t)); - old_group = surface->current_group; old_width = surface->width; old_height = surface->height; old_cairo_to_pdf = surface->cairo_to_pdf; - surface->current_group = &group; + old_paginated_mode = surface->paginated_mode; surface->width = meta_extents.width; surface->height = meta_extents.height; + /* Patterns are emitted after fallback images. The paginated mode + * needs to be set to _RENDER while the meta surface is replayed + * back to this surface. + */ + surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER; cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height); + _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, + surface->cairo_to_pdf); - status = _cairo_pdf_surface_start_content_stream (surface); + _cairo_pdf_group_resources_clear (&surface->resources); + status = _cairo_pdf_surface_open_content_stream (surface, TRUE); if (status) - goto CLEANUP_GROUP; + return status; + *resource = surface->content; if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) { status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); if (status) @@ -1620,79 +1592,44 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface, surface->height); } - status = _cairo_meta_surface_replay (meta_surface, &surface->base); + status = _cairo_meta_surface_replay_region (meta_surface, &surface->base, + CAIRO_META_REGION_NATIVE); + assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (status) goto CLEANUP_GROUP; - status = _cairo_pdf_surface_stop_content_stream (surface); - if (status) - goto CLEANUP_GROUP; - - status = _cairo_pdf_surface_open_group (surface); - if (status) - goto CLEANUP_GROUP; - - status = _cairo_pdf_surface_write_group_list (surface, &group); - if (status) - goto CLEANUP_GROUP; - - status = _cairo_pdf_surface_close_group (surface, resource); - if (status) - goto CLEANUP_GROUP; + status = _cairo_pdf_surface_close_content_stream (surface); CLEANUP_GROUP: - surface->current_group = old_group; surface->width = old_width; surface->height = old_height; + surface->paginated_mode = old_paginated_mode; surface->cairo_to_pdf = old_cairo_to_pdf; + _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, + surface->cairo_to_pdf); - _cairo_pdf_group_element_array_finish (&group); - _cairo_array_fini (&group); - if (status) - return status; - - status = _cairo_pdf_surface_start_content_stream (surface); - if (status) - return status; - - _cairo_pdf_surface_pause_content_stream (surface); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface, - cairo_solid_pattern_t *pattern) -{ - surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SOLID; - surface->emitted_pattern.red = pattern->color.red; - surface->emitted_pattern.green = pattern->color.green; - surface->emitted_pattern.blue = pattern->color.blue; - surface->emitted_pattern.alpha = pattern->color.alpha; - surface->emitted_pattern.smask.id = 0; - surface->emitted_pattern.pattern.id = 0; + return status; } static cairo_status_t -_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, - cairo_surface_pattern_t *pattern) +_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, + cairo_pdf_pattern_t *pdf_pattern) { - cairo_pdf_resource_t stream; - cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern; + cairo_status_t status; cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */ cairo_matrix_t cairo_p2d, pdf_p2d; cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base); double xstep, ystep; - cairo_rectangle_int16_t surface_extents; + cairo_rectangle_int_t surface_extents; int pattern_width = 0; /* squelch bogus compiler warning */ int pattern_height = 0; /* squelch bogus compiler warning */ int bbox_x, bbox_y; - - _cairo_pdf_surface_pause_content_stream (surface); + char draw_surface[200]; if (_cairo_surface_is_meta (pattern->surface)) { cairo_surface_t *meta_surface = pattern->surface; - cairo_rectangle_int16_t pattern_extents; + cairo_rectangle_int_t pattern_extents; status = _cairo_pdf_surface_emit_meta_surface (surface, meta_surface, @@ -1810,12 +1747,14 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height); cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); - stream = _cairo_pdf_surface_open_stream (surface, + _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); + status = _cairo_pdf_surface_open_stream (surface, + &pdf_pattern->pattern_res, FALSE, + " /PatternType 1\r\n" " /BBox [0 0 %d %d]\r\n" " /XStep %f\r\n" " /YStep %f\r\n" - " /PatternType 1\r\n" " /TilingType 1\r\n" " /PaintType 1\r\n" " /Matrix [ %f %f %f %f %f %f ]\r\n" @@ -1827,48 +1766,48 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, pdf_p2d.x0, pdf_p2d.y0, pattern_resource.id, pattern_resource.id); - if (stream.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (status) + return status; if (_cairo_surface_is_meta (pattern->surface)) { - if (extend == CAIRO_EXTEND_REFLECT) { - _cairo_output_stream_printf (surface->output, - "q 0 0 %d %d re W n /x%d Do Q\r\n" - "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n /x%d Do Q\r\n" - "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n /x%d Do Q\r\n" - "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n /x%d Do Q\r\n", - pattern_width, pattern_height, - pattern_resource.id, - pattern_width*2, pattern_width, pattern_height, - pattern_resource.id, - pattern_height*2, pattern_width, pattern_height, - pattern_resource.id, - pattern_width*2, pattern_height*2, pattern_width, pattern_height, - pattern_resource.id); - } else { - _cairo_output_stream_printf (surface->output, - "/x%d Do\r\n", - pattern_resource.id); - } + snprintf(draw_surface, + sizeof (draw_surface), + "/x%d Do\r\n", + pattern_resource.id); + } else { + snprintf(draw_surface, + sizeof (draw_surface), + "q %d 0 0 %d 0 0 cm /x%d Do Q", + pattern_width, + pattern_height, + pattern_resource.id); + } + + if (extend == CAIRO_EXTEND_REFLECT) { + _cairo_output_stream_printf (surface->output, + "q 0 0 %d %d re W n %s Q\r\n" + "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\r\n" + "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\r\n" + "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\r\n", + pattern_width, pattern_height, + draw_surface, + pattern_width*2, pattern_width, pattern_height, + draw_surface, + pattern_height*2, pattern_width, pattern_height, + draw_surface, + pattern_width*2, pattern_height*2, pattern_width, pattern_height, + draw_surface); } else { _cairo_output_stream_printf (surface->output, - "q %d 0 0 %d 0 0 cm /x%d Do Q\r\n", - pattern_width, pattern_height, - pattern_resource.id); + " %s \r\n", + draw_surface); } status = _cairo_pdf_surface_close_stream (surface); if (status) return status; - _cairo_pdf_surface_resume_content_stream (surface); - - surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_SURFACE; - surface->emitted_pattern.smask.id = 0; - surface->emitted_pattern.pattern = stream; - surface->emitted_pattern.alpha = 1.0; - - return CAIRO_STATUS_SUCCESS; + return _cairo_output_stream_get_status (surface->output); } typedef struct _cairo_pdf_color_stop { @@ -1981,7 +1920,7 @@ cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface, static cairo_status_t _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, - unsigned int n_stops, + unsigned int n_stops, cairo_pdf_color_stop_t *stops, cairo_bool_t is_alpha, cairo_pdf_resource_t *function) @@ -2028,7 +1967,7 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, "%d 0 R ", stops[i].resource.id); _cairo_output_stream_printf (surface->output, - "]\r\n"); + "]\r\n"); _cairo_output_stream_printf (surface->output, " /Bounds [ "); @@ -2036,7 +1975,7 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, "%f ", stops[i].offset); _cairo_output_stream_printf (surface->output, - "]\r\n"); + "]\r\n"); _cairo_output_stream_printf (surface->output, " /Encode [ "); @@ -2044,15 +1983,15 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, "0 1 "); _cairo_output_stream_printf (surface->output, - "]\r\n"); + "]\r\n"); _cairo_output_stream_printf (surface->output, - ">>\r\n" + ">>\r\n" "endobj\r\n"); *function = res; - return CAIRO_STATUS_SUCCESS; + return _cairo_output_stream_get_status (surface->output); } @@ -2145,7 +2084,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, goto BAIL; } } else { - /* multiple stops: stitch. XXX possible optimization: regulary spaced + /* multiple stops: stitch. XXX possible optimization: regularly spaced * stops do not require stitching. XXX */ status = _cairo_pdf_surface_emit_stitched_colorgradient (surface, n_stops, @@ -2229,39 +2168,42 @@ _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface, *function = res; - return CAIRO_STATUS_SUCCESS; + return _cairo_output_stream_get_status (surface->output); } -static cairo_pdf_resource_t +static cairo_status_t cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, - cairo_pdf_resource_t gradient_mask) + cairo_pdf_resource_t gstate_resource, + cairo_pdf_resource_t gradient_mask) { - cairo_pdf_resource_t xobj_resource, smask_resource, gstate_resource; + cairo_pdf_resource_t smask_resource; + cairo_status_t status; - xobj_resource = _cairo_pdf_surface_open_stream (surface, - surface->compress_content, - " /Type /XObject\r\n" - " /Subtype /Form\r\n" - " /FormType 1\r\n" - " /BBox [ 0 0 %f %f ]\r\n" - " /Resources\r\n" - " << /ExtGState\r\n" - " << /a0 << /ca 1 /CA 1 >>" - " >>\r\n" - " /Pattern\r\n" - " << /p%d %d 0 R >>\r\n" - " >>\r\n" - " /Group\r\n" - " << /Type /Group\r\n" - " /S /Transparency\r\n" - " /CS /DeviceGray\r\n" - " >>\r\n", - surface->width, - surface->height, - gradient_mask.id, - gradient_mask.id); - if (xobj_resource.id == 0) - return xobj_resource; + status = _cairo_pdf_surface_open_stream (surface, + NULL, + surface->compress_content, + " /Type /XObject\r\n" + " /Subtype /Form\r\n" + " /FormType 1\r\n" + " /BBox [ 0 0 %f %f ]\r\n" + " /Resources\r\n" + " << /ExtGState\r\n" + " << /a0 << /ca 1 /CA 1 >>" + " >>\r\n" + " /Pattern\r\n" + " << /p%d %d 0 R >>\r\n" + " >>\r\n" + " /Group\r\n" + " << /Type /Group\r\n" + " /S /Transparency\r\n" + " /CS /DeviceGray\r\n" + " >>\r\n", + surface->width, + surface->height, + gradient_mask.id, + gradient_mask.id); + if (status) + return status; _cairo_output_stream_printf (surface->output, "q\r\n" @@ -2274,14 +2216,13 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, surface->width, surface->height); - if (_cairo_pdf_surface_close_stream (surface)) { - smask_resource.id = 0; - return smask_resource; - } + status = _cairo_pdf_surface_close_stream (surface); + if (status) + return status; smask_resource = _cairo_pdf_surface_new_object (surface); if (smask_resource.id == 0) - return smask_resource; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -2291,12 +2232,10 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n", smask_resource.id, - xobj_resource.id); + surface->pdf_stream.self.id); /* Create GState which uses the transparency group as an SMask. */ - gstate_resource = _cairo_pdf_surface_new_object (surface); - if (gstate_resource.id == 0) - return gstate_resource; + _cairo_pdf_surface_update_object (surface, gstate_resource); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -2310,14 +2249,14 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, gstate_resource.id, smask_resource.id); - return gstate_resource; + return _cairo_output_stream_get_status (surface->output); } static cairo_status_t _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, - cairo_linear_pattern_t *pattern) + cairo_pdf_pattern_t *pdf_pattern) { - cairo_pdf_resource_t pattern_resource, smask; + cairo_linear_pattern_t *pattern = (cairo_linear_pattern_t *) pdf_pattern->pattern; cairo_pdf_resource_t color_function, alpha_function; double x1, y1, x2, y2; double _x1, _y1, _x2, _y2; @@ -2328,8 +2267,9 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, double first_stop, last_stop; int repeat_begin = 0, repeat_end = 1; - extend = cairo_pattern_get_extend (&pattern->base.base); - _cairo_pdf_surface_pause_content_stream (surface); + assert (pattern->base.n_stops != 0); + + extend = cairo_pattern_get_extend (pdf_pattern->pattern); pat_to_pdf = pattern->base.base.matrix; status = cairo_matrix_invert (&pat_to_pdf); @@ -2424,10 +2364,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, } } - pattern_resource = _cairo_pdf_surface_new_object (surface); - if (pattern_resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - + _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" "<< /Type /Pattern\r\n" @@ -2439,7 +2376,7 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, " /Coords [ %f %f %f %f ]\r\n" " /Domain [ %f %f ]\r\n" " /Function %d 0 R\r\n", - pattern_resource.id, + pdf_pattern->pattern_res.id, pat_to_pdf.xx, pat_to_pdf.yx, pat_to_pdf.xy, pat_to_pdf.yy, pat_to_pdf.x0, pat_to_pdf.y0, @@ -2460,10 +2397,10 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n"); - if (alpha_function.id == 0) { - surface->emitted_pattern.smask.id = 0; - } else { - cairo_pdf_resource_t mask_resource; + if (alpha_function.id != 0) { + cairo_pdf_resource_t mask_resource; + + assert (pdf_pattern->gstate_res.id != 0); /* Create pattern for SMask. */ mask_resource = _cairo_pdf_surface_new_object (surface); @@ -2505,35 +2442,30 @@ _cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, if (status) return status; - smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource); - if (smask.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - surface->emitted_pattern.smask = smask; + status = cairo_pdf_surface_emit_transparency_group (surface, + pdf_pattern->gstate_res, + mask_resource); + if (status) + return status; } - surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_LINEAR; - surface->emitted_pattern.pattern = pattern_resource; - surface->emitted_pattern.alpha = 1.0; - - _cairo_pdf_surface_resume_content_stream (surface); - - return status; + return _cairo_output_stream_get_status (surface->output); } static cairo_status_t _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, - cairo_radial_pattern_t *pattern) + cairo_pdf_pattern_t *pdf_pattern) { - cairo_pdf_resource_t pattern_resource, smask; cairo_pdf_resource_t color_function, alpha_function; double x1, y1, x2, y2, r1, r2; cairo_matrix_t pat_to_pdf; cairo_extend_t extend; cairo_status_t status; + cairo_radial_pattern_t *pattern = (cairo_radial_pattern_t *) pdf_pattern->pattern; - extend = cairo_pattern_get_extend (&pattern->base.base); - _cairo_pdf_surface_pause_content_stream (surface); + assert (pattern->base.n_stops != 0); + + extend = cairo_pattern_get_extend (pdf_pattern->pattern); status = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base, @@ -2555,9 +2487,7 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, y2 = _cairo_fixed_to_double (pattern->c2.y); r2 = _cairo_fixed_to_double (pattern->r2); - pattern_resource = _cairo_pdf_surface_new_object (surface); - if (pattern_resource.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -2569,7 +2499,7 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, " /ColorSpace /DeviceRGB\r\n" " /Coords [ %f %f %f %f %f %f ]\r\n" " /Function %d 0 R\r\n", - pattern_resource.id, + pdf_pattern->pattern_res.id, pat_to_pdf.xx, pat_to_pdf.yx, pat_to_pdf.xy, pat_to_pdf.yy, pat_to_pdf.x0, pat_to_pdf.y0, @@ -2589,12 +2519,12 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n"); - if (alpha_function.id == 0) { - surface->emitted_pattern.smask.id = 0; - } else { - cairo_pdf_resource_t mask_resource; + if (alpha_function.id != 0) { + cairo_pdf_resource_t mask_resource; - /* Create pattern for SMask. */ + assert (pdf_pattern->gstate_res.id != 0); + + /* Create pattern for SMask. */ mask_resource = _cairo_pdf_surface_new_object (surface); if (mask_resource.id == 0) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2629,38 +2559,32 @@ _cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n"); - smask = cairo_pdf_surface_emit_transparency_group (surface, mask_resource); - if (smask.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - surface->emitted_pattern.smask = smask; + status = cairo_pdf_surface_emit_transparency_group (surface, + pdf_pattern->gstate_res, + mask_resource); + if (status) + return status; } - surface->emitted_pattern.type = CAIRO_PATTERN_TYPE_RADIAL; - surface->emitted_pattern.pattern = pattern_resource; - surface->emitted_pattern.alpha = 1.0; - - _cairo_pdf_surface_resume_content_stream (surface); - - return status; + return _cairo_output_stream_get_status (surface->output); } static cairo_status_t -_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern) +_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern) { - switch (pattern->type) { + switch (pdf_pattern->pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - _cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); - return CAIRO_STATUS_SUCCESS; + ASSERT_NOT_REACHED; + break; case CAIRO_PATTERN_TYPE_SURFACE: - return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern); + return _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern); case CAIRO_PATTERN_TYPE_LINEAR: - return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); + return _cairo_pdf_surface_emit_linear_pattern (surface, pdf_pattern); case CAIRO_PATTERN_TYPE_RADIAL: - return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); + return _cairo_pdf_surface_emit_radial_pattern (surface, pdf_pattern); } ASSERT_NOT_REACHED; @@ -2669,23 +2593,27 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t * static cairo_status_t _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface, - cairo_bool_t is_stroke) + cairo_pattern_t *pattern, + cairo_pdf_resource_t pattern_res, + cairo_bool_t is_stroke) { cairo_status_t status; int alpha; - status = _cairo_pdf_surface_add_alpha (surface, surface->emitted_pattern.alpha, &alpha); - if (status) - return status; + if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { + cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *) pattern; + + status = _cairo_pdf_surface_add_alpha (surface, solid_pattern->color.alpha, &alpha); + if (status) + return status; - if (surface->emitted_pattern.type == CAIRO_PATTERN_TYPE_SOLID) { _cairo_output_stream_printf (surface->output, - "%f %f %f ", - surface->emitted_pattern.red, - surface->emitted_pattern.green, - surface->emitted_pattern.blue); + "q %f %f %f ", + solid_pattern->color.red, + solid_pattern->color.green, + solid_pattern->color.blue); - if (is_stroke) + if (is_stroke) _cairo_output_stream_printf (surface->output, "RG "); else _cairo_output_stream_printf (surface->output, "rg "); @@ -2694,40 +2622,35 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface, "/a%d gs\r\n", alpha); } else { - if (is_stroke) { - _cairo_output_stream_printf (surface->output, - "/Pattern CS /p%d SCN ", - surface->emitted_pattern.pattern.id); - } else { - _cairo_output_stream_printf (surface->output, - "/Pattern cs /p%d scn ", - surface->emitted_pattern.pattern.id); - } - status = _cairo_pdf_surface_add_pattern (surface, surface->emitted_pattern.pattern); + status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); if (status) return status; - _cairo_output_stream_printf (surface->output, - "/a%d gs ", - alpha); + status = _cairo_pdf_surface_add_pattern (surface, pattern_res); + if (status) + return status; - _cairo_output_stream_printf (surface->output, "\r\n"); + if (is_stroke) { + _cairo_output_stream_printf (surface->output, + "q /Pattern CS /p%d SCN ", + pattern_res.id); + } else { + _cairo_output_stream_printf (surface->output, + "q /Pattern cs /p%d scn ", + pattern_res.id); + } + _cairo_output_stream_printf (surface->output, + "/a%d gs\r\n", + alpha); } return _cairo_output_stream_get_status (surface->output); } -static cairo_int_status_t -_cairo_pdf_surface_copy_page (void *abstract_surface) +static void +_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface) { - cairo_pdf_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - status = _cairo_pdf_surface_stop_content_stream (surface); - if (status) - return status; - - return _cairo_pdf_surface_write_page (surface); + _cairo_output_stream_printf (surface->output, "Q\r\n"); } static cairo_int_status_t @@ -2736,7 +2659,7 @@ _cairo_pdf_surface_show_page (void *abstract_surface) cairo_pdf_surface_t *surface = abstract_surface; cairo_int_status_t status; - status = _cairo_pdf_surface_stop_content_stream (surface); + status = _cairo_pdf_surface_close_content_stream (surface); if (status) return status; @@ -2759,7 +2682,7 @@ _cairo_pdf_surface_get_extents (void *abstract_surface, rectangle->y = 0; /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the aribitray limitation of width to a short(!). We + * mention the arbitrary limitation of width to a short(!). We * may need to come up with a better interface for get_size. */ rectangle->width = (int) ceil (surface->width); @@ -2768,136 +2691,6 @@ _cairo_pdf_surface_get_extents (void *abstract_surface, return CAIRO_STATUS_SUCCESS; } -typedef struct _pdf_path_info { - cairo_output_stream_t *output; - cairo_matrix_t *cairo_to_pdf; - cairo_matrix_t *ctm_inverse; -} pdf_path_info_t; - -static cairo_status_t -_cairo_pdf_path_move_to (void *closure, cairo_point_t *point) -{ - pdf_path_info_t *info = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (info->cairo_to_pdf) - cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y); - if (info->ctm_inverse) - cairo_matrix_transform_point (info->ctm_inverse, &x, &y); - - _cairo_output_stream_printf (info->output, - "%f %f m ", x, y); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_path_line_to (void *closure, cairo_point_t *point) -{ - pdf_path_info_t *info = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (info->cairo_to_pdf) - cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y); - if (info->ctm_inverse) - cairo_matrix_transform_point (info->ctm_inverse, &x, &y); - - _cairo_output_stream_printf (info->output, - "%f %f l ", x, y); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_path_curve_to (void *closure, - cairo_point_t *b, - cairo_point_t *c, - cairo_point_t *d) -{ - pdf_path_info_t *info = closure; - double bx = _cairo_fixed_to_double (b->x); - double by = _cairo_fixed_to_double (b->y); - double cx = _cairo_fixed_to_double (c->x); - double cy = _cairo_fixed_to_double (c->y); - double dx = _cairo_fixed_to_double (d->x); - double dy = _cairo_fixed_to_double (d->y); - - if (info->cairo_to_pdf) { - cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by); - cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy); - cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy); - } - if (info->ctm_inverse) { - cairo_matrix_transform_point (info->ctm_inverse, &bx, &by); - cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy); - cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy); - } - - _cairo_output_stream_printf (info->output, - "%f %f %f %f %f %f c ", - bx, by, cx, cy, dx, dy); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_path_close_path (void *closure) -{ - pdf_path_info_t *info = closure; - - _cairo_output_stream_printf (info->output, - "h\r\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_pdf_surface_add_clip (cairo_pdf_surface_t *surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule) -{ - cairo_pdf_group_element_t elem; - cairo_status_t status; - - memset (&elem, 0, sizeof elem); - elem.type = ELEM_CLIP; - - if (path == NULL) { - elem.clip_path = NULL; - } else { - elem.clip_path = _cairo_path_fixed_create (); - if (elem.clip_path == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_path_fixed_init_copy (elem.clip_path, path); - if (status) { - _cairo_path_fixed_destroy (elem.clip_path); - return status; - } - } - elem.fill_rule = fill_rule; - - status = _cairo_pdf_surface_stop_content_stream (surface); - if (status) { - if (elem.clip_path != NULL) - _cairo_path_fixed_destroy (elem.clip_path); - return status; - } - - status = _cairo_array_append (surface->current_group, &elem); - if (status) { - if (elem.clip_path != NULL) - _cairo_path_fixed_destroy (elem.clip_path); - return status; - } - - status = _cairo_pdf_surface_start_content_stream (surface); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t _cairo_pdf_surface_intersect_clip_path (void *abstract_surface, cairo_path_fixed_t *path, @@ -2907,7 +2700,12 @@ _cairo_pdf_surface_intersect_clip_path (void *abstract_surface, { cairo_pdf_surface_t *surface = abstract_surface; - return _cairo_pdf_surface_add_clip (surface, path, fill_rule); + if (path == NULL) { + _cairo_output_stream_printf (surface->output, "Q q\r\n"); + return CAIRO_STATUS_SUCCESS; + } + + return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule); } static void @@ -2966,7 +2764,7 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) _cairo_output_stream_printf (surface->output, " /Count %d\r\n", num_pages); - /* TODO: Figure out wich other defaults to be inherited by /Page + /* TODO: Figure out which other defaults to be inherited by /Page * objects. */ _cairo_output_stream_printf (surface->output, ">>\r\n" @@ -2981,24 +2779,33 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface, { const cairo_scaled_font_backend_t *backend; unsigned int i, num_bfchar; + cairo_int_status_t status; stream->id = 0; if (font_subset->to_unicode == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; - if (_cairo_truetype_create_glyph_to_unicode_map (font_subset) != CAIRO_STATUS_SUCCESS) { + status = _cairo_truetype_create_glyph_to_unicode_map (font_subset); + if (status) { + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + backend = font_subset->scaled_font->backend; if (backend->map_glyphs_to_unicode == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; - backend->map_glyphs_to_unicode (font_subset->scaled_font, font_subset); + status = backend->map_glyphs_to_unicode (font_subset->scaled_font, + font_subset); + if (status) + return status; } - *stream = _cairo_pdf_surface_open_stream (surface, - surface->compress_content, - NULL); - if (stream->id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_pdf_surface_open_stream (surface, + NULL, + surface->compress_content, + NULL); + if (status) + return status; _cairo_output_stream_printf (surface->output, "/CIDInit /ProcSet findresource begin\r\n" @@ -3055,6 +2862,7 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface, "end\r\n" "end\r\n"); + *stream = surface->pdf_stream.self; return _cairo_pdf_surface_close_stream (surface); } @@ -3071,6 +2879,12 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface, unsigned int i; cairo_status_t status; + subset_resource = _cairo_pdf_surface_get_font_resource (surface, + font_subset->font_id, + font_subset->subset_id); + if (subset_resource.id == 0) + return CAIRO_STATUS_SUCCESS; + compressed = compress_dup (subset->data, subset->data_length, &compressed_length); if (compressed == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3162,9 +2976,6 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n"); - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); _cairo_pdf_surface_update_object (surface, subset_resource); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -3248,6 +3059,11 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface, char *compressed; unsigned int i; + subset_resource = _cairo_pdf_surface_get_font_resource (surface, + font_subset->font_id, + font_subset->subset_id); + if (subset_resource.id == 0) + return CAIRO_STATUS_SUCCESS; /* We ignore the zero-trailer and set Length3 to 0. */ length = subset->header_length + subset->data_length; @@ -3316,9 +3132,6 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface, subset->descent, stream.id); - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); _cairo_pdf_surface_update_object (surface, subset_resource); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -3367,7 +3180,7 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, char name[64]; snprintf (name, sizeof name, "CairoFont-%d-%d", - font_subset->font_id, font_subset->subset_id); + font_subset->font_id, font_subset->subset_id); status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE); if (status) return status; @@ -3414,6 +3227,12 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, char *compressed; unsigned int i; + subset_resource = _cairo_pdf_surface_get_font_resource (surface, + font_subset->font_id, + font_subset->subset_id); + if (subset_resource.id == 0) + return CAIRO_STATUS_SUCCESS; + status = _cairo_truetype_subset_init (&subset, font_subset); if (status) return status; @@ -3520,9 +3339,6 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, ">>\r\n" "endobj\r\n"); - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); _cairo_pdf_surface_update_object (surface, subset_resource); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" @@ -3554,60 +3370,6 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, return status; } -static cairo_int_status_t -_cairo_pdf_surface_emit_outline_glyph (cairo_pdf_surface_t *surface, - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index, - cairo_pdf_resource_t *glyph_ret) -{ - cairo_scaled_glyph_t *scaled_glyph; - pdf_path_info_t info; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS| - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - if (status) - return status; - - *glyph_ret = _cairo_pdf_surface_open_stream (surface, - surface->compress_content, - NULL); - if (glyph_ret->id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f %f %f d1\r\n", - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), - -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y), - _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), - -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); - - info.output = surface->output; - info.cairo_to_pdf = &surface->cairo_to_pdf; - info.ctm_inverse = NULL; - - status = _cairo_path_fixed_interpret (scaled_glyph->path, - CAIRO_DIRECTION_FORWARD, - _cairo_pdf_path_move_to, - _cairo_pdf_path_line_to, - _cairo_pdf_path_curve_to, - _cairo_pdf_path_close_path, - &info); - if (status) { - /* ignore status return as we are on the error path... */ - _cairo_pdf_surface_close_stream (surface); - return status; - } - - _cairo_output_stream_printf (surface->output, - " f"); - - return _cairo_pdf_surface_close_stream (surface); -} - static cairo_int_status_t _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, cairo_scaled_font_t *scaled_font, @@ -3640,19 +3402,23 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, image = scaled_glyph->surface; if (image->format != CAIRO_FORMAT_A1) { image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); - if (cairo_surface_status (&image->base)) - return cairo_surface_status (&image->base); + status = cairo_surface_status (&image->base); + if (status) + return status; } - *glyph_ret = _cairo_pdf_surface_open_stream (surface, - surface->compress_content, - NULL); - if (glyph_ret->id == 0) { + status = _cairo_pdf_surface_open_stream (surface, + NULL, + surface->compress_content, + NULL); + if (status) { if (image != scaled_glyph->surface) cairo_surface_destroy (&image->base); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + return status; } + *glyph_ret = surface->pdf_stream.self; + _cairo_output_stream_printf (surface->output, "%f 0 %f %f %f %f d1\r\n", x_advance, @@ -3697,37 +3463,11 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface, return status; } -static void -_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface, - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index, - cairo_pdf_resource_t *glyph_ret, - cairo_box_t *bbox, - double *width) -{ - cairo_status_t status; - - status = _cairo_pdf_surface_emit_outline_glyph (surface, - scaled_font, - glyph_index, - glyph_ret); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_pdf_surface_emit_bitmap_glyph (surface, - scaled_font, - glyph_index, - glyph_ret, - bbox, - width); - - if (status) - status = _cairo_surface_set_error (&surface->base, status); -} - static cairo_status_t _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) { - cairo_status_t status; + cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream; cairo_pdf_font_t font; cairo_matrix_t matrix; @@ -3736,23 +3476,35 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, cairo_box_t font_bbox = {{0,0},{0,0}}; cairo_box_t bbox = {{0,0},{0,0}}; + if (font_subset->num_glyphs == 0) + return CAIRO_STATUS_SUCCESS; + + subset_resource = _cairo_pdf_surface_get_font_resource (surface, + font_subset->font_id, + font_subset->subset_id); + if (subset_resource.id == 0) + return CAIRO_STATUS_SUCCESS; + glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t)); if (glyphs == NULL) - return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double)); if (widths == NULL) { free (glyphs); - return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } for (i = 0; i < font_subset->num_glyphs; i++) { - _cairo_pdf_surface_emit_glyph (surface, - font_subset->scaled_font, - font_subset->glyphs[i], - &glyphs[i], - &bbox, - &widths[i]); + status = _cairo_pdf_surface_emit_bitmap_glyph (surface, + font_subset->scaled_font, + font_subset->glyphs[i], + &glyphs[i], + &bbox, + &widths[i]); + if (status) + break; + if (i == 0) { font_bbox.p1.x = bbox.p1.x; font_bbox.p1.y = bbox.p1.y; @@ -3769,6 +3521,11 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, font_bbox.p2.y = bbox.p2.y; } } + if (status) { + free (glyphs); + free (widths); + return status; + } encoding = _cairo_pdf_surface_new_object (surface); if (encoding.id == 0) { @@ -3817,14 +3574,8 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, return status; } - subset_resource = _cairo_pdf_surface_get_font_resource (surface, - font_subset->font_id, - font_subset->subset_id); _cairo_pdf_surface_update_object (surface, subset_resource); - matrix = font_subset->scaled_font->scale; - status = cairo_matrix_invert (&matrix); - /* _cairo_scaled_font_init ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); + matrix = font_subset->scaled_font->scale_inverse; _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" "<< /Type /Font\r\n" @@ -3902,6 +3653,7 @@ _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_s return status; } + ASSERT_NOT_REACHED; return CAIRO_STATUS_SUCCESS; } @@ -3916,6 +3668,7 @@ _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_sub if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; + ASSERT_NOT_REACHED; return CAIRO_STATUS_SUCCESS; } @@ -3991,53 +3744,245 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface) } static cairo_status_t -_cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule) +_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, + cairo_pdf_smask_group_t *group) { - const char *pdf_operator; + cairo_pdf_resource_t mask_group; + cairo_pdf_resource_t smask; + cairo_pdf_smask_group_t *smask_group; + cairo_pdf_resource_t pattern_res, gstate_res; + cairo_status_t status; - if (path == NULL) { - _cairo_output_stream_printf (surface->output, "Q q\r\n"); - return CAIRO_STATUS_SUCCESS; - } + /* Create mask group */ + status = _cairo_pdf_surface_open_group (surface, NULL); + if (status) + return status; - if (! path->has_current_point) { - /* construct an empty path */ - _cairo_output_stream_printf (surface->output, "0 0 m "); - } else { - pdf_path_info_t info; - cairo_status_t status; + pattern_res.id = 0; + gstate_res.id = 0; + status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, &pattern_res, &gstate_res); + if (status) + return status; - info.output = surface->output; - info.cairo_to_pdf = &surface->cairo_to_pdf; - info.ctm_inverse = NULL; + if (gstate_res.id != 0) { + smask_group = _cairo_pdf_surface_create_smask_group (surface); + if (smask_group == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_pdf_path_move_to, - _cairo_pdf_path_line_to, - _cairo_pdf_path_curve_to, - _cairo_pdf_path_close_path, - &info); + smask_group->operation = PDF_PAINT; + smask_group->source = cairo_pattern_reference (group->mask); + smask_group->source_res = pattern_res; + status = _cairo_pdf_surface_add_smask_group (surface, smask_group); + if (status) { + _cairo_pdf_smask_group_destroy (smask_group); + return status; + } + + status = _cairo_pdf_surface_add_smask (surface, gstate_res); if (status) return status; + + status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res); + if (status) + return status; + + _cairo_output_stream_printf (surface->output, + "q /s%d gs /x%d Do Q\r\n", + gstate_res.id, + smask_group->group_res.id); + } else { + status = _cairo_pdf_surface_select_pattern (surface, group->mask, pattern_res, FALSE); + if (status) + return status; + + _cairo_output_stream_printf (surface->output, + "0 0 %f %f re f\r\n", + surface->width, surface->height); + + _cairo_pdf_surface_unselect_pattern (surface); } - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - pdf_operator = "W"; - break; - case CAIRO_FILL_RULE_EVEN_ODD: - pdf_operator = "W*"; - break; - default: - ASSERT_NOT_REACHED; + status = _cairo_pdf_surface_close_group (surface, &mask_group); + if (status) + return status; + + /* Create source group */ + status = _cairo_pdf_surface_open_group (surface, &group->source_res); + if (status) + return status; + + pattern_res.id = 0; + gstate_res.id = 0; + status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, &pattern_res, &gstate_res); + if (status) + return status; + + if (gstate_res.id != 0) { + smask_group = _cairo_pdf_surface_create_smask_group (surface); + if (smask_group == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + smask_group->operation = PDF_PAINT; + smask_group->source = cairo_pattern_reference (group->source); + smask_group->source_res = pattern_res; + status = _cairo_pdf_surface_add_smask_group (surface, smask_group); + if (status) { + _cairo_pdf_smask_group_destroy (smask_group); + return status; + } + + status = _cairo_pdf_surface_add_smask (surface, gstate_res); + if (status) + return status; + + status = _cairo_pdf_surface_add_xobject (surface, smask_group->group_res); + if (status) + return status; + + _cairo_output_stream_printf (surface->output, + "q /s%d gs /x%d Do Q\r\n", + gstate_res.id, + smask_group->group_res.id); + } else { + status = _cairo_pdf_surface_select_pattern (surface, group->source, pattern_res, FALSE); + if (status) + return status; + + _cairo_output_stream_printf (surface->output, + "0 0 %f %f re f\r\n", + surface->width, surface->height); + + _cairo_pdf_surface_unselect_pattern (surface); } + status = _cairo_pdf_surface_close_group (surface, NULL); + if (status) + return status; + + /* Create an smask based on the alpha component of mask_group */ + smask = _cairo_pdf_surface_new_object (surface); + if (smask.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_output_stream_printf (surface->output, - "%s n\r\n", - pdf_operator); + "%d 0 obj\r\n" + "<< /Type /Mask\r\n" + " /S /Alpha\r\n" + " /G %d 0 R\r\n" + ">>\r\n" + "endobj\r\n", + smask.id, + mask_group.id); + + /* Create a GState that uses the smask */ + _cairo_pdf_surface_update_object (surface, group->group_res); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<< /Type /ExtGState\r\n" + " /SMask %d 0 R\r\n" + " /ca 1\r\n" + " /CA 1\r\n" + " /AIS false\r\n" + ">>\r\n" + "endobj\r\n", + group->group_res.id, + smask.id); + + return _cairo_output_stream_get_status (surface->output); +} + +static cairo_status_t +_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface, + cairo_pdf_smask_group_t *group) +{ + cairo_status_t status; + + /* _mask is a special case that requires two groups - source + * and mask as well as a smask and gstate dictionary */ + if (group->operation == PDF_MASK) + return _cairo_pdf_surface_write_mask_group (surface, group); + + status = _cairo_pdf_surface_open_group (surface, &group->group_res); + if (status) + return status; + + status = _cairo_pdf_surface_select_pattern (surface, + group->source, + group->source_res, + group->operation == PDF_STROKE); + if (status) + return status; + + switch (group->operation) { + case PDF_PAINT: + _cairo_output_stream_printf (surface->output, + "0 0 %f %f re f\r\n", + surface->width, surface->height); + break; + case PDF_MASK: + ASSERT_NOT_REACHED; + break; + case PDF_FILL: + status = _cairo_pdf_operators_fill (&surface->pdf_operators, + &group->path, + group->fill_rule); + break; + case PDF_STROKE: + status = _cairo_pdf_operator_stroke (&surface->pdf_operators, + &group->path, + group->style, + &group->ctm, + &group->ctm_inverse); + break; + case PDF_SHOW_GLYPHS: + status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators, + group->glyphs, + group->num_glyphs, + group->scaled_font); + break; + } + if (status) + return status; + + _cairo_pdf_surface_unselect_pattern (surface); + + return _cairo_pdf_surface_close_group (surface, NULL); +} + +static cairo_status_t +_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface) +{ + cairo_pdf_pattern_t pattern; + cairo_pdf_smask_group_t *group; + int pattern_index, group_index; + cairo_status_t status; + + /* Writing out PDF_MASK groups will cause additional smask groups + * to be appended to surface->smask_groups. Additional patterns + * may also be appended to surface->patterns. + * + * Writing meta surface patterns will cause additional patterns + * and groups to be appended. + */ + pattern_index = 0; + group_index = 0; + while ((pattern_index < _cairo_array_num_elements (&surface->patterns)) || + (group_index < _cairo_array_num_elements (&surface->smask_groups))) + { + for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) { + _cairo_array_copy_element (&surface->smask_groups, group_index, &group); + status = _cairo_pdf_surface_write_smask_group (surface, group); + if (status) + return status; + } + + for (; pattern_index < _cairo_array_num_elements (&surface->patterns); pattern_index++) { + _cairo_array_copy_element (&surface->patterns, pattern_index, &pattern); + status = _cairo_pdf_surface_emit_pattern (surface, &pattern); + if (status) + return status; + } + } return CAIRO_STATUS_SUCCESS; } @@ -4045,62 +3990,54 @@ _cairo_pdf_surface_emit_clip (cairo_pdf_surface_t *surface, static cairo_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) { + cairo_pdf_resource_t page, knockout, res; cairo_status_t status; - cairo_pdf_resource_t page; - cairo_pdf_resource_t content_group, knockout_group, page_content; - cairo_bool_t has_fallback_images = FALSE; + int i, len; - if (_cairo_array_num_elements (&surface->knockout_group) > 0) - has_fallback_images = TRUE; - - status = _cairo_pdf_surface_open_group (surface); - if (status) - return status; - - status = _cairo_pdf_surface_write_group_list (surface, &surface->content_group); - if (status) - return status; - - status = _cairo_pdf_surface_close_group (surface, &content_group); - if (status) - return status; - - if (has_fallback_images) { - status = _cairo_pdf_surface_open_knockout_group (surface, &content_group); + _cairo_pdf_group_resources_clear (&surface->resources); + if (surface->has_fallback_images) { + status = _cairo_pdf_surface_open_knockout_group (surface); if (status) return status; - status = _cairo_pdf_surface_write_group_list (surface, &surface->knockout_group); + len = _cairo_array_num_elements (&surface->knockout_group); + for (i = 0; i < len; i++) { + _cairo_array_copy_element (&surface->knockout_group, i, &res); + _cairo_output_stream_printf (surface->output, + "/x%d Do\r\n", + res.id); + status = _cairo_pdf_surface_add_xobject (surface, res); + if (status) + return status; + } + _cairo_output_stream_printf (surface->output, + "/x%d Do\r\n", + surface->content.id); + status = _cairo_pdf_surface_add_xobject (surface, surface->content); if (status) return status; - status = _cairo_pdf_surface_close_group (surface, &knockout_group); + status = _cairo_pdf_surface_close_group (surface, &knockout); + if (status) + return status; + + _cairo_pdf_group_resources_clear (&surface->resources); + status = _cairo_pdf_surface_open_content_stream (surface, FALSE); + if (status) + return status; + + _cairo_output_stream_printf (surface->output, + "/x%d Do\r\n", + knockout.id); + status = _cairo_pdf_surface_add_xobject (surface, knockout); + if (status) + return status; + + status = _cairo_pdf_surface_close_content_stream (surface); if (status) return status; } - page_content = _cairo_pdf_surface_open_stream (surface, - FALSE, - " /Type /XObject\r\n" - " /Subtype /Form\r\n" - " /BBox [ 0 0 %f %f ]\r\n" - " /Group <<\r\n" - " /Type /Group\r\n" - " /S /Transparency\r\n" - " /CS /DeviceRGB\r\n" - " >>\r\n", - surface->width, - surface->height); - if (page_content.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_output_stream_printf (surface->output, - "/x%d Do\r\n", - has_fallback_images ? knockout_group.id : content_group.id); - status = _cairo_pdf_surface_close_stream (surface); - if (status) - return status; - page = _cairo_pdf_surface_new_object (surface); if (page.id == 0) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4110,29 +4047,30 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) "<< /Type /Page\r\n" " /Parent %d 0 R\r\n" " /MediaBox [ 0 0 %f %f ]\r\n" - " /Contents [ %d 0 R ]\r\n" + " /Contents %d 0 R\r\n" " /Group <<\r\n" " /Type /Group\r\n" " /S /Transparency\r\n" " /CS /DeviceRGB\r\n" " >>\r\n" - " /Resources <<\r\n" - " /XObject << /x%d %d 0 R >>\r\n" - " >>\r\n" + " /Resources %d 0 R\r\n" ">>\r\n" "endobj\r\n", page.id, surface->pages_resource.id, surface->width, surface->height, - page_content.id, - has_fallback_images ? knockout_group.id : content_group.id, - has_fallback_images ? knockout_group.id : content_group.id); + surface->content.id, + surface->content_resources.id); status = _cairo_array_append (&surface->pages, &page); if (status) return status; + status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface); + if (status) + return status; + return CAIRO_STATUS_SUCCESS; } @@ -4233,20 +4171,22 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface, if (! _pattern_supported (pattern)) return CAIRO_INT_STATUS_UNSUPPORTED; - if (op == CAIRO_OPERATOR_OVER) { + if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) { if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; if ( _cairo_surface_is_meta (surface_pattern->surface)) - return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; + return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; } - return CAIRO_STATUS_SUCCESS; } - /* The SOURCE operator is only supported for the fallback images. */ - if (op == CAIRO_OPERATOR_SOURCE && - surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) + if (op == CAIRO_OPERATOR_OVER) return CAIRO_STATUS_SUCCESS; + /* The SOURCE operator is only if there is nothing painted + * underneath. */ + if (op == CAIRO_OPERATOR_SOURCE) + return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; + return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -4262,28 +4202,21 @@ _cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface, } static cairo_int_status_t -_cairo_pdf_surface_set_operator (cairo_pdf_surface_t *surface, - cairo_operator_t op) +_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface) { cairo_status_t status; - if (op == CAIRO_OPERATOR_OVER) - return CAIRO_STATUS_SUCCESS; + status = _cairo_pdf_surface_close_content_stream (surface); + if (status) + return status; - if (op == CAIRO_OPERATOR_SOURCE) { - surface->current_group = &surface->knockout_group; - status = _cairo_pdf_surface_stop_content_stream (surface); - if (status) - return status; + status = _cairo_array_append (&surface->knockout_group, &surface->content); + if (status) + return status; - status = _cairo_pdf_surface_start_content_stream (surface); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; + surface->has_fallback_images = TRUE; + _cairo_pdf_group_resources_clear (&surface->resources); + return _cairo_pdf_surface_open_content_stream (surface, TRUE); } static cairo_int_status_t @@ -4292,64 +4225,67 @@ _cairo_pdf_surface_paint (void *abstract_surface, cairo_pattern_t *source) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */ cairo_status_t status; + cairo_pdf_smask_group_t *group; + cairo_pdf_resource_t pattern_res, gstate_res; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { return _cairo_pdf_surface_analyze_operation (surface, op, source); + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { + status = _cairo_pdf_surface_start_fallback (surface); + if (status) + return status; + } assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_emit_pattern (surface, source); + pattern_res.id = 0; + gstate_res.id = 0; + status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; if (status) return status; - status = _cairo_pdf_surface_set_operator (surface, op); - if (status) - return status; + if (gstate_res.id != 0) { + group = _cairo_pdf_surface_create_smask_group (surface); + if (group == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (surface->emitted_pattern.smask.id != 0) { - _cairo_pdf_surface_pause_content_stream (surface); - status = _cairo_pdf_surface_open_group (surface); - if (status) + group->operation = PDF_PAINT; + group->source = cairo_pattern_reference (source); + group->source_res = pattern_res; + status = _cairo_pdf_surface_add_smask_group (surface, group); + if (status) { + _cairo_pdf_smask_group_destroy (group); return status; - } else { - _cairo_output_stream_printf (surface->output, "q "); - } + } - status = _cairo_pdf_surface_select_pattern (surface, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\r\n", - surface->width, surface->height); - - if (surface->emitted_pattern.smask.id != 0) { - status = _cairo_pdf_surface_close_group (surface, &smask_group); + status = _cairo_pdf_surface_add_smask (surface, gstate_res); + if (status) + return status; + + status = _cairo_pdf_surface_add_xobject (surface, group->group_res); if (status) return status; - _cairo_pdf_surface_resume_content_stream (surface); _cairo_output_stream_printf (surface->output, "q /s%d gs /x%d Do Q\r\n", - surface->emitted_pattern.smask, - smask_group.id); - status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, smask_group); - if (status) - return status; + gstate_res.id, + group->group_res.id); } else { - _cairo_output_stream_printf (surface->output, "Q\r\n"); + status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE); + if (status) + return status; + + _cairo_output_stream_printf (surface->output, + "0 0 %f %f re f\r\n", + surface->width, surface->height); + + _cairo_pdf_surface_unselect_pattern (surface); } - status = _cairo_output_stream_get_status (surface->output); - if (status) - return status; - - return _cairo_pdf_surface_check_content_stream_size (surface); + return _cairo_output_stream_get_status (surface->output); } static cairo_int_status_t @@ -4359,11 +4295,7 @@ _cairo_pdf_surface_mask (void *abstract_surface, cairo_pattern_t *mask) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_resource_t mask_group; - cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */ - cairo_pdf_resource_t source_group; - cairo_pdf_resource_t smask; - cairo_pdf_resource_t gstate; + cairo_pdf_smask_group_t *group; cairo_status_t status, status2; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { @@ -4377,213 +4309,46 @@ _cairo_pdf_surface_mask (void *abstract_surface, return status2; return status; + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { + status = _cairo_pdf_surface_start_fallback (surface); + if (status) + return status; } assert (_cairo_pdf_surface_operation_supported (surface, op, source)); assert (_cairo_pdf_surface_operation_supported (surface, op, mask)); - status = _cairo_pdf_surface_set_operator (surface, op); - if (status) - return status; - - /* Create mask group */ - status = _cairo_pdf_surface_emit_pattern (surface, mask); - if (status) - return status; - - _cairo_pdf_surface_pause_content_stream (surface); - - status = _cairo_pdf_surface_open_group (surface); - if (status) - return status; - - status = _cairo_pdf_surface_select_pattern (surface, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\r\n", - surface->width, surface->height); - status = _cairo_pdf_surface_close_group (surface, &mask_group); - if (status) - return status; - - if (surface->emitted_pattern.smask.id != 0) { - group = mask_group; - status = _cairo_pdf_surface_open_group (surface); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "/s%d gs /x%d Do\r\n", - surface->emitted_pattern.smask, - group.id); - status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, group); - if (status) - return status; - - status = _cairo_pdf_surface_close_group (surface, &mask_group); - if (status) - return status; - } - - /* Create source group */ - status = _cairo_pdf_surface_emit_pattern (surface, source); - if (status) - return status; - - _cairo_pdf_surface_pause_content_stream (surface); - - status = _cairo_pdf_surface_open_group (surface); - if (status) - return status; - - status = _cairo_pdf_surface_select_pattern (surface, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\r\n", - surface->width, surface->height); - status = _cairo_pdf_surface_close_group (surface, &source_group); - if (status) - return status; - - if (surface->emitted_pattern.smask.id != 0) { - group = source_group; - status = _cairo_pdf_surface_open_group (surface); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "/s%d gs /x%d Do\r\n", - surface->emitted_pattern.smask, - group.id); - status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, group); - if (status) - return status; - - status =_cairo_pdf_surface_close_group (surface, &source_group); - if (status) - return status; - } - - /* Create an smask based on the alpha component of mask_group */ - smask = _cairo_pdf_surface_new_object (surface); - if (smask.id == 0) + group = _cairo_pdf_surface_create_smask_group (surface); + if (group == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - _cairo_output_stream_printf (surface->output, - "%d 0 obj\r\n" - "<< /Type /Mask\r\n" - " /S /Alpha\r\n" - " /G %d 0 R\r\n" - ">>\r\n" - "endobj\r\n", - smask.id, - mask_group.id); - - /* Create a GState that uses the smask */ - gstate = _cairo_pdf_surface_new_object (surface); - if (gstate.id == 0) + group->operation = PDF_MASK; + group->source = cairo_pattern_reference (source); + group->mask = cairo_pattern_reference (mask); + group->source_res = _cairo_pdf_surface_new_object (surface); + if (group->source_res.id == 0) { + _cairo_pdf_smask_group_destroy (group); return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - _cairo_output_stream_printf (surface->output, - "%d 0 obj\r\n" - "<< /Type /ExtGState\r\n" - " /SMask %d 0 R\r\n" - " /ca 1\r\n" - " /CA 1\r\n" - " /AIS false\r\n" - ">>\r\n" - "endobj\r\n", - gstate.id, - smask.id); + status = _cairo_pdf_surface_add_smask_group (surface, group); + if (status) { + _cairo_pdf_smask_group_destroy (group); + return status; + } + + status = _cairo_pdf_surface_add_smask (surface, group->group_res); + if (status) + return status; + + status = _cairo_pdf_surface_add_xobject (surface, group->source_res); + if (status) + return status; - /* Select the GState then draw the source */ - _cairo_pdf_surface_resume_content_stream (surface); _cairo_output_stream_printf (surface->output, "q /s%d gs /x%d Do Q\r\n", - gstate.id, - source_group.id); - status = _cairo_pdf_surface_add_smask (surface, gstate); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, source_group); - if (status) - return status; - - return _cairo_output_stream_get_status (surface->output); -} - -static int -_cairo_pdf_line_cap (cairo_line_cap_t cap) -{ - switch (cap) { - case CAIRO_LINE_CAP_BUTT: - return 0; - case CAIRO_LINE_CAP_ROUND: - return 1; - case CAIRO_LINE_CAP_SQUARE: - return 2; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static int -_cairo_pdf_line_join (cairo_line_join_t join) -{ - switch (join) { - case CAIRO_LINE_JOIN_MITER: - return 0; - case CAIRO_LINE_JOIN_ROUND: - return 1; - case CAIRO_LINE_JOIN_BEVEL: - return 2; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static cairo_status_t -_cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t *surface, - cairo_stroke_style_t *style) -{ - _cairo_output_stream_printf (surface->output, - "%f w\r\n", - style->line_width); - - _cairo_output_stream_printf (surface->output, - "%d J\r\n", - _cairo_pdf_line_cap (style->line_cap)); - - _cairo_output_stream_printf (surface->output, - "%d j\r\n", - _cairo_pdf_line_join (style->line_join)); - - if (style->num_dashes) { - unsigned int d; - _cairo_output_stream_printf (surface->output, "["); - for (d = 0; d < style->num_dashes; d++) - _cairo_output_stream_printf (surface->output, " %f", style->dash[d]); - _cairo_output_stream_printf (surface->output, "] %f d\r\n", - style->dash_offset); - } else { - _cairo_output_stream_printf (surface->output, "[] 0.0 d\r\n"); - } - - _cairo_output_stream_printf (surface->output, - "%f M ", - style->miter_limit); + group->group_res.id, + group->source_res.id); return _cairo_output_stream_get_status (surface->output); } @@ -4600,85 +4365,75 @@ _cairo_pdf_surface_stroke (void *abstract_surface, cairo_antialias_t antialias) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */ - pdf_path_info_t info; cairo_status_t status; - cairo_matrix_t m; + cairo_pdf_smask_group_t *group; + cairo_pdf_resource_t pattern_res, gstate_res; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _cairo_pdf_surface_analyze_operation (surface, op, source); assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_emit_pattern (surface, source); + pattern_res.id = 0; + gstate_res.id = 0; + status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; if (status) return status; - if (surface->emitted_pattern.smask.id != 0) { - _cairo_pdf_surface_pause_content_stream (surface); - status = _cairo_pdf_surface_open_group (surface); - if (status) + if (gstate_res.id != 0) { + group = _cairo_pdf_surface_create_smask_group (surface); + if (group == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + group->operation = PDF_STROKE; + group->source = cairo_pattern_reference (source); + group->source_res = pattern_res; + status = _cairo_path_fixed_init_copy (&group->path, path); + if (status) { + _cairo_pdf_smask_group_destroy (group); return status; - } else { - _cairo_output_stream_printf (surface->output, "q "); - } + } - status = _cairo_pdf_surface_select_pattern (surface, TRUE); - if (status) - return status; + group->style = style; + group->ctm = *ctm; + group->ctm_inverse = *ctm_inverse; + status = _cairo_pdf_surface_add_smask_group (surface, group); + if (status) { + _cairo_pdf_smask_group_destroy (group); + return status; + } - status = _cairo_pdf_surface_emit_stroke_style (surface, - style); - if (status) - return status; - - info.output = surface->output; - info.cairo_to_pdf = NULL; - info.ctm_inverse = ctm_inverse; - - cairo_matrix_multiply (&m, ctm, &surface->cairo_to_pdf); - _cairo_output_stream_printf (surface->output, - "q %f %f %f %f %f %f cm\r\n", - m.xx, m.yx, m.xy, m.yy, - m.x0, m.y0); - - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_pdf_path_move_to, - _cairo_pdf_path_line_to, - _cairo_pdf_path_curve_to, - _cairo_pdf_path_close_path, - &info); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, "S Q\r\n"); - - if (surface->emitted_pattern.smask.id != 0) { - status = _cairo_pdf_surface_close_group (surface, &smask_group); + status = _cairo_pdf_surface_add_smask (surface, gstate_res); + if (status) + return status; + + status = _cairo_pdf_surface_add_xobject (surface, group->group_res); if (status) return status; - _cairo_pdf_surface_resume_content_stream (surface); _cairo_output_stream_printf (surface->output, "q /s%d gs /x%d Do Q\r\n", - surface->emitted_pattern.smask, - smask_group.id); - status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, smask_group); - if (status) - return status; + gstate_res.id, + group->group_res.id); } else { - _cairo_output_stream_printf (surface->output, "Q\r\n"); + status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, TRUE); + if (status) + return status; + + status = _cairo_pdf_operator_stroke (&surface->pdf_operators, + path, + style, + ctm, + ctm_inverse); + if (status) + return status; + + _cairo_pdf_surface_unselect_pattern (surface); } - status = _cairo_output_stream_get_status (surface->output); - if (status) - return status; - - return _cairo_pdf_surface_check_content_stream_size (surface); + return _cairo_output_stream_get_status (surface->output); } static cairo_int_status_t @@ -4691,94 +4446,78 @@ _cairo_pdf_surface_fill (void *abstract_surface, cairo_antialias_t antialias) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */ - const char *pdf_operator; cairo_status_t status; - pdf_path_info_t info; + cairo_pdf_smask_group_t *group; + cairo_pdf_resource_t pattern_res, gstate_res; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { return _cairo_pdf_surface_analyze_operation (surface, op, source); + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { + status = _cairo_pdf_surface_start_fallback (surface); + if (status) + return status; + } assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_set_operator (surface, op); + pattern_res.id = 0; + gstate_res.id = 0; + status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; if (status) return status; - status = _cairo_pdf_surface_emit_pattern (surface, source); - if (status) - return status; + if (gstate_res.id != 0) { + group = _cairo_pdf_surface_create_smask_group (surface); + if (group == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (surface->emitted_pattern.smask.id != 0) { - _cairo_pdf_surface_pause_content_stream (surface); - status = _cairo_pdf_surface_open_group (surface); - if (status) + group->operation = PDF_FILL; + group->source = cairo_pattern_reference (source); + group->source_res = pattern_res; + status = _cairo_path_fixed_init_copy (&group->path, path); + if (status) { + _cairo_pdf_smask_group_destroy (group); return status; - } else { - _cairo_output_stream_printf (surface->output, "q "); - } + } - status = _cairo_pdf_surface_select_pattern (surface, FALSE); - if (status) - return status; + group->fill_rule = fill_rule; + status = _cairo_pdf_surface_add_smask_group (surface, group); + if (status) { + _cairo_pdf_smask_group_destroy (group); + return status; + } - info.output = surface->output; - info.cairo_to_pdf = &surface->cairo_to_pdf; - info.ctm_inverse = NULL; - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_pdf_path_move_to, - _cairo_pdf_path_line_to, - _cairo_pdf_path_curve_to, - _cairo_pdf_path_close_path, - &info); - if (status) - return status; - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - pdf_operator = "f"; - break; - case CAIRO_FILL_RULE_EVEN_ODD: - pdf_operator = "f*"; - break; - default: - ASSERT_NOT_REACHED; - } - - _cairo_output_stream_printf (surface->output, - "%s\r\n", - pdf_operator); - - if (surface->emitted_pattern.smask.id != 0) { - status = _cairo_pdf_surface_close_group (surface, &smask_group); + status = _cairo_pdf_surface_add_smask (surface, gstate_res); + if (status) + return status; + + status = _cairo_pdf_surface_add_xobject (surface, group->group_res); if (status) return status; - _cairo_pdf_surface_resume_content_stream (surface); _cairo_output_stream_printf (surface->output, "q /s%d gs /x%d Do Q\r\n", - surface->emitted_pattern.smask, - smask_group.id); - status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, smask_group); - if (status) - return status; + gstate_res.id, + group->group_res.id); } else { - _cairo_output_stream_printf (surface->output, "Q\r\n"); + status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE); + if (status) + return status; + + status = _cairo_pdf_operators_fill (&surface->pdf_operators, + path, + fill_rule); + if (status) + return status; + + _cairo_pdf_surface_unselect_pattern (surface); } - status = _cairo_output_stream_get_status (surface->output); - if (status) - return status; - - return _cairo_pdf_surface_check_content_stream_size (surface); + return _cairo_output_stream_get_status (surface->output); } -#define GLYPH_POSITION_TOLERANCE 0.001 - static cairo_int_status_t _cairo_pdf_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, @@ -4788,206 +4527,68 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_resource_t smask_group = {0}; /* squelch bogus compiler warning */ - unsigned int current_subset_id = (unsigned int)-1; - cairo_scaled_font_subsets_glyph_t subset_glyph; - cairo_bool_t diagonal, in_TJ; cairo_status_t status; - double Tlm_x = 0, Tlm_y = 0; - double Tm_x = 0, y; - int i, hex_width; + cairo_pdf_smask_group_t *group; + cairo_pdf_resource_t pattern_res, gstate_res; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _cairo_pdf_surface_analyze_operation (surface, op, source); assert (_cairo_pdf_surface_operation_supported (surface, op, source)); - status = _cairo_pdf_surface_emit_pattern (surface, source); + pattern_res.id = 0; + gstate_res.id = 0; + status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &pattern_res, &gstate_res); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; if (status) return status; - if (surface->emitted_pattern.smask.id != 0) { - _cairo_pdf_surface_pause_content_stream (surface); - status = _cairo_pdf_surface_open_group (surface); - if (status) + if (gstate_res.id != 0) { + group = _cairo_pdf_surface_create_smask_group (surface); + if (group == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + group->operation = PDF_SHOW_GLYPHS; + group->source = cairo_pattern_reference (source); + group->source_res = pattern_res; + group->glyphs = glyphs; + group->num_glyphs = num_glyphs; + group->scaled_font = cairo_scaled_font_reference (scaled_font); + status = _cairo_pdf_surface_add_smask_group (surface, group); + if (status) { + _cairo_pdf_smask_group_destroy (group); return status; - } else { - _cairo_output_stream_printf (surface->output, "q "); - } + } - status = _cairo_pdf_surface_select_pattern (surface, FALSE); - if (status) - return status; - - _cairo_output_stream_printf (surface->output, - "BT\r\n"); - - if (scaled_font->scale.xy == 0.0 && - scaled_font->scale.yx == 0.0) - diagonal = TRUE; - else - diagonal = FALSE; - - in_TJ = FALSE; - for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, - scaled_font, glyphs[i].index, - &subset_glyph); - if (status) - return status; - - if (subset_glyph.is_composite) - hex_width = 4; - else - hex_width = 2; - - if (subset_glyph.is_scaled == FALSE) { - y = 0.0; - cairo_matrix_transform_distance (&scaled_font->scale, - &subset_glyph.x_advance, - &y); - } - - if (subset_glyph.subset_id != current_subset_id) { - if (in_TJ) { - _cairo_output_stream_printf (surface->output, ">] TJ\r\n"); - in_TJ = FALSE; - } - _cairo_output_stream_printf (surface->output, - "/f-%d-%d 1 Tf\r\n", - subset_glyph.font_id, - subset_glyph.subset_id); - status = _cairo_pdf_surface_add_font (surface, - subset_glyph.font_id, - subset_glyph.subset_id); - if (status) - return status; - } - - if (subset_glyph.subset_id != current_subset_id || !diagonal) { - _cairo_output_stream_printf (surface->output, - "%f %f %f %f %f %f Tm\r\n", - scaled_font->scale.xx, - -scaled_font->scale.yx, - -scaled_font->scale.xy, - scaled_font->scale.yy, - glyphs[i].x, - surface->height - glyphs[i].y); - current_subset_id = subset_glyph.subset_id; - Tlm_x = glyphs[i].x; - Tlm_y = glyphs[i].y; - Tm_x = Tlm_x; - } - - if (diagonal) { - if (i < num_glyphs - 1 && - fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE && - fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10) - { - if (!in_TJ) { - if (i != 0) { - _cairo_output_stream_printf (surface->output, - "%f %f Td\r\n", - (glyphs[i].x - Tlm_x)/scaled_font->scale.xx, - -(glyphs[i].y - Tlm_y)/scaled_font->scale.yy); - - Tlm_x = glyphs[i].x; - Tlm_y = glyphs[i].y; - Tm_x = Tlm_x; - } - _cairo_output_stream_printf (surface->output, - "[<%0*x", - hex_width, - subset_glyph.subset_glyph_index); - Tm_x += subset_glyph.x_advance; - in_TJ = TRUE; - } else { - if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) { - double delta = glyphs[i].x - Tm_x; - - _cairo_output_stream_printf (surface->output, - "> %f <", - -1000.0*delta/scaled_font->scale.xx); - Tm_x += delta; - } - _cairo_output_stream_printf (surface->output, - "%0*x", - hex_width, - subset_glyph.subset_glyph_index); - Tm_x += subset_glyph.x_advance; - } - } - else - { - if (in_TJ) { - if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) { - double delta = glyphs[i].x - Tm_x; - - _cairo_output_stream_printf (surface->output, - "> %f <", - -1000.0*delta/scaled_font->scale.xx); - Tm_x += delta; - } - _cairo_output_stream_printf (surface->output, - "%0*x>] TJ\r\n", - hex_width, - subset_glyph.subset_glyph_index); - Tm_x += subset_glyph.x_advance; - in_TJ = FALSE; - } else { - if (i != 0) { - _cairo_output_stream_printf (surface->output, - "%f %f Td ", - (glyphs[i].x - Tlm_x)/scaled_font->scale.xx, - (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy); - Tlm_x = glyphs[i].x; - Tlm_y = glyphs[i].y; - Tm_x = Tlm_x; - } - _cairo_output_stream_printf (surface->output, - "<%0*x> Tj ", - hex_width, - subset_glyph.subset_glyph_index); - Tm_x += subset_glyph.x_advance; - } - } - } else { - _cairo_output_stream_printf (surface->output, - "<%0*x> Tj\r\n", - hex_width, - subset_glyph.subset_glyph_index); - } - } - - _cairo_output_stream_printf (surface->output, - "ET\r\n"); - - if (surface->emitted_pattern.smask.id != 0) { - status = _cairo_pdf_surface_close_group (surface, &smask_group); + status = _cairo_pdf_surface_add_smask (surface, gstate_res); if (status) return status; - _cairo_pdf_surface_resume_content_stream (surface); + status = _cairo_pdf_surface_add_xobject (surface, group->group_res); + if (status) + return status; _cairo_output_stream_printf (surface->output, "q /s%d gs /x%d Do Q\r\n", - surface->emitted_pattern.smask, - smask_group.id); - status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask); - if (status) - return status; - status = _cairo_pdf_surface_add_xobject (surface, smask_group); - if (status) - return status; + gstate_res.id, + group->group_res.id); } else { - _cairo_output_stream_printf (surface->output, "Q\r\n"); + status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE); + if (status) + return status; + + status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators, + glyphs, + num_glyphs, + scaled_font); + if (status) + return status; + + _cairo_pdf_surface_unselect_pattern (surface); } - status = _cairo_output_stream_get_status (surface->output); - if (status) - return status; - - return _cairo_pdf_surface_check_content_stream_size (surface); + return _cairo_output_stream_get_status (surface->output); } static void @@ -5011,7 +4612,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { NULL, /* composite */ NULL, /* fill_rectangles */ NULL, /* composite_trapezoids */ - _cairo_pdf_surface_copy_page, + NULL, /* _cairo_pdf_surface_copy_page */ _cairo_pdf_surface_show_page, NULL, /* set_clip_region */ _cairo_pdf_surface_intersect_clip_path, diff --git a/gfx/cairo/cairo/src/cairo-png.c b/gfx/cairo/cairo/src/cairo-png.c index 67c87fd5018d..a78da3f82a7e 100644 --- a/gfx/cairo/cairo/src/cairo-png.c +++ b/gfx/cairo/cairo/src/cairo-png.c @@ -275,8 +275,14 @@ cairo_surface_write_to_png (cairo_surface_t *surface, cairo_status_t status; fp = fopen (filename, "wb"); - if (fp == NULL) - return _cairo_error (CAIRO_STATUS_WRITE_ERROR); + if (fp == NULL) { + switch (errno) { + case ENOMEM: + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + default: + return _cairo_error (CAIRO_STATUS_WRITE_ERROR); + } + } status = write_png (surface, stdio_write_func, fp); @@ -376,7 +382,7 @@ static cairo_surface_t * read_png (png_rw_ptr read_func, void *closure) { - cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil; + cairo_surface_t *surface; png_struct *png = NULL; png_info *info; png_byte *data = NULL; @@ -392,20 +398,23 @@ read_png (png_rw_ptr read_func, &status, png_simple_error_callback, png_simple_warning_callback); - if (png == NULL) + if (png == NULL) { + surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto BAIL; + } info = png_create_info_struct (png); - if (info == NULL) + if (info == NULL) { + surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto BAIL; + } png_set_read_fn (png, closure, read_func); status = CAIRO_STATUS_SUCCESS; #ifdef PNG_SETJMP_SUPPORTED if (setjmp (png_jmpbuf (png))) { - if (status != CAIRO_STATUS_NO_MEMORY) - surface = (cairo_surface_t*) &_cairo_surface_nil_read_error; + surface = _cairo_surface_create_in_error (status); goto BAIL; } #endif @@ -454,12 +463,16 @@ read_png (png_rw_ptr read_func, pixel_size = 4; data = _cairo_malloc_abc (png_height, png_width, pixel_size); - if (data == NULL) + if (data == NULL) { + surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto BAIL; + } row_pointers = _cairo_malloc_ab (png_height, sizeof (char *)); - if (row_pointers == NULL) + if (row_pointers == NULL) { + surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto BAIL; + } for (i = 0; i < png_height; i++) row_pointers[i] = &data[i * png_width * pixel_size]; @@ -484,9 +497,6 @@ read_png (png_rw_ptr read_func, if (png) png_destroy_read_struct (&png, &info, NULL); - if (surface->status) - _cairo_error_throw (surface->status); - return surface; } @@ -532,17 +542,19 @@ cairo_image_surface_create_from_png (const char *filename) fp = fopen (filename, "rb"); if (fp == NULL) { + cairo_status_t status; switch (errno) { case ENOMEM: - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + break; case ENOENT: - _cairo_error_throw (CAIRO_STATUS_FILE_NOT_FOUND); - return (cairo_surface_t*) &_cairo_surface_nil_file_not_found; + status = _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND); + break; default: - _cairo_error_throw (CAIRO_STATUS_READ_ERROR); - return (cairo_surface_t*) &_cairo_surface_nil_read_error; + status = _cairo_error (CAIRO_STATUS_READ_ERROR); + break; } + return _cairo_surface_create_in_error (status); } surface = read_png (stdio_read_func, fp); diff --git a/gfx/cairo/cairo/src/cairo-ps-surface-private.h b/gfx/cairo/cairo/src/cairo-ps-surface-private.h index d75f6c705cd0..c42863a13dfc 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h @@ -78,6 +78,7 @@ typedef struct cairo_ps_surface { cairo_array_t *dsc_comment_target; cairo_ps_level_t ps_level; + cairo_ps_level_t ps_level_used; cairo_surface_t *paginated_surface; } cairo_ps_surface_t; diff --git a/gfx/cairo/cairo/src/cairo-ps-surface.c b/gfx/cairo/cairo/src/cairo-ps-surface.c index 71fa6bdfcbcc..d54b22bc2483 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface.c +++ b/gfx/cairo/cairo/src/cairo-ps-surface.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2003 University of Southern California @@ -47,12 +48,18 @@ #include "cairo-meta-surface-private.h" #include "cairo-output-stream-private.h" +#include #include #include #include +#include #define DEBUG_PS 0 +#ifndef HAVE_CTIME_R +#define ctime_r(T, BUF) ctime (T) +#endif + typedef enum _cairo_image_transparency { CAIRO_IMAGE_IS_OPAQUE, CAIRO_IMAGE_HAS_BILEVEL_ALPHA, @@ -170,6 +177,9 @@ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column) { word_wrap_stream_t *stream; + if (output->status) + return _cairo_output_stream_create_in_error (output->status); + stream = malloc (sizeof (word_wrap_stream_t)); if (stream == NULL) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); @@ -295,7 +305,7 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface, word_wrap = _word_wrap_stream_create (stream, 79); status = _cairo_output_stream_get_status (word_wrap); if (status) - return status; + return _cairo_output_stream_destroy (word_wrap); path_info.surface = surface; path_info.stream = word_wrap; @@ -318,18 +328,19 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface, static void _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) { + char ctime_buf[26]; time_t now; char **comments; int i, num_comments; - const char *level; + int level; const char *eps_header = ""; now = time (NULL); - if (surface->ps_level == CAIRO_PS_LEVEL_2) - level = "2"; + if (surface->ps_level_used == CAIRO_PS_LEVEL_2) + level = 2; else - level = "3"; + level = 3; if (surface->eps) eps_header = " EPSF-3.0"; @@ -342,7 +353,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "%%%%BoundingBox: %d %d %d %d\n", eps_header, cairo_version_string (), - ctime (&now), + ctime_r (&now, ctime_buf), surface->num_pages, surface->bbox_x1, surface->bbox_y1, @@ -351,7 +362,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) _cairo_output_stream_printf (surface->final_stream, "%%%%DocumentData: Clean7Bit\n" - "%%%%LanguageLevel: %s\n", + "%%%%LanguageLevel: %d\n", level); num_comments = _cairo_array_num_elements (&surface->dsc_header_comments); @@ -375,6 +386,14 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "/dict_count countdictstack def\n" "/op_count count 1 sub def\n" "userdict begin\n"); + } else { + _cairo_output_stream_printf (surface->final_stream, + "/languagelevel where{pop languagelevel}{1}ifelse %d lt{/Helvetica\n" + "findfont 12 scalefont setfont 50 500 moveto\n" + "(This print job requires a PostScript Language Level %d printer.)show\n" + "showpage quit}if\n", + level, + level); } _cairo_output_stream_printf (surface->final_stream, @@ -569,7 +588,8 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, static cairo_int_status_t _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, - unsigned long glyph_index) + unsigned long glyph_index, + cairo_box_t *bbox) { cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; @@ -582,6 +602,7 @@ _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface, if (status) return status; + *bbox = scaled_glyph->bbox; _cairo_output_stream_printf (surface->final_stream, "0 0 %f %f %f %f setcachedevice\n", _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), @@ -594,6 +615,8 @@ _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface, surface->final_stream, scaled_glyph->path, CAIRO_LINE_CAP_ROUND); + if (status) + return status; _cairo_output_stream_printf (surface->final_stream, "F\n"); @@ -604,13 +627,15 @@ _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface, static cairo_int_status_t _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, - unsigned long glyph_index) + unsigned long glyph_index, + cairo_box_t *bbox) { cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; cairo_image_surface_t *image; unsigned char *row, *byte; int rows, cols; + double x_advance, y_advance; status = _cairo_scaled_glyph_lookup (scaled_font, glyph_index, @@ -620,6 +645,11 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, if (status) return status; + *bbox = scaled_glyph->bbox; + x_advance = scaled_glyph->metrics.x_advance; + y_advance = scaled_glyph->metrics.y_advance; + cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance); + image = scaled_glyph->surface; if (image->format != CAIRO_FORMAT_A1) { image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1); @@ -628,11 +658,12 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->final_stream, - "0 0 %f %f %f %f setcachedevice\n", + "%f 0 %f %f %f %f setcachedevice\n", + x_advance, _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), - - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y), + _cairo_fixed_to_double (scaled_glyph->bbox.p2.y), _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), - - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); + _cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); _cairo_output_stream_printf (surface->final_stream, "<<\n" @@ -678,20 +709,25 @@ static cairo_status_t _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, - unsigned int subset_glyph_index) + unsigned int subset_glyph_index, + cairo_box_t *bbox) { - cairo_status_t status; + cairo_status_t status = CAIRO_STATUS_SUCCESS; _cairo_output_stream_printf (surface->final_stream, "\t\t{ %% %d\n", subset_glyph_index); - status = _cairo_ps_surface_emit_outline_glyph_data (surface, - scaled_font, - scaled_font_glyph_index); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_ps_surface_emit_bitmap_glyph_data (surface, - scaled_font, - scaled_font_glyph_index); + if (subset_glyph_index != 0) { + status = _cairo_ps_surface_emit_outline_glyph_data (surface, + scaled_font, + scaled_font_glyph_index, + bbox); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) + status = _cairo_ps_surface_emit_bitmap_glyph_data (surface, + scaled_font, + scaled_font_glyph_index, + bbox); + } _cairo_output_stream_printf (surface->final_stream, "\t\t}\n"); @@ -711,47 +747,81 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, cairo_status_t status; cairo_matrix_t matrix; unsigned int i; + cairo_box_t font_bbox = {{0,0},{0,0}}; + cairo_box_t bbox = {{0,0},{0,0}}; #if DEBUG_PS _cairo_output_stream_printf (surface->final_stream, "%% _cairo_ps_surface_emit_type3_font_subset\n"); #endif + matrix = font_subset->scaled_font->scale_inverse; _cairo_output_stream_printf (surface->final_stream, - "/CairoFont-%d-%d <<\n", - font_subset->font_id, - font_subset->subset_id); - - matrix = font_subset->scaled_font->scale; - status = cairo_matrix_invert (&matrix); - /* _cairo_scaled_font_init ensures the matrix is invertible */ - assert (status == CAIRO_STATUS_SUCCESS); - _cairo_output_stream_printf (surface->final_stream, - "\t/FontType\t3\n" - "\t/FontMatrix\t[%f %f %f %f 0 0]\n" - "\t/Encoding\t[0]\n" - "\t/FontBBox\t[0 0 10 10]\n" - "\t/Glyphs [\n", + "8 dict begin\n" + "/FontType 3 def\n" + "/FontMatrix [%f %f %f %f 0 0] def\n" + "/Encoding 256 array def\n" + "0 1 255 { Encoding exch /.notdef put } for\n", matrix.xx, matrix.yx, -matrix.xy, -matrix.yy); - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_ps_surface_emit_glyph (surface, - font_subset->scaled_font, - font_subset->glyphs[i], i); - if (status) - return status; + for (i = 1; i < font_subset->num_glyphs; i++) { + if (font_subset->glyph_names != NULL) { + _cairo_output_stream_printf (surface->final_stream, + "Encoding %d /%s put\n", + i, font_subset->glyph_names[i]); + } else { + _cairo_output_stream_printf (surface->final_stream, + "Encoding %d /g%d put\n", i, i); + } } _cairo_output_stream_printf (surface->final_stream, - "\t]\n" - "\t/BuildChar {\n" - "\t\texch /Glyphs get\n" - "\t\texch get exec\n" - "\t}\n" - ">> definefont pop\n"); + "/Glyphs [\n"); + + for (i = 0; i < font_subset->num_glyphs; i++) { + status = _cairo_ps_surface_emit_glyph (surface, + font_subset->scaled_font, + font_subset->glyphs[i], i, + &bbox); + if (status) + return status; + + if (i == 0) { + font_bbox.p1.x = bbox.p1.x; + font_bbox.p1.y = bbox.p1.y; + font_bbox.p2.x = bbox.p2.x; + font_bbox.p2.y = bbox.p2.y; + } else { + if (bbox.p1.x < font_bbox.p1.x) + font_bbox.p1.x = bbox.p1.x; + if (bbox.p1.y < font_bbox.p1.y) + font_bbox.p1.y = bbox.p1.y; + if (bbox.p2.x > font_bbox.p2.x) + font_bbox.p2.x = bbox.p2.x; + if (bbox.p2.y > font_bbox.p2.y) + font_bbox.p2.y = bbox.p2.y; + } + } + + _cairo_output_stream_printf (surface->final_stream, + "] def\n" + "/FontBBox [%f %f %f %f] def\n" + "/BuildChar {\n" + " exch /Glyphs get\n" + " exch get exec\n" + "} bind def\n" + "currentdict\n" + "end\n" + "/CairoFont-%d-%d exch definefont pop\n", + _cairo_fixed_to_double (font_bbox.p1.x), + _cairo_fixed_to_double (font_bbox.p1.y), + _cairo_fixed_to_double (font_bbox.p2.x), + _cairo_fixed_to_double (font_bbox.p2.y), + font_subset->font_id, + font_subset->subset_id); return CAIRO_STATUS_SUCCESS; } @@ -782,6 +852,7 @@ _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_su if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; + ASSERT_NOT_REACHED; return CAIRO_STATUS_SUCCESS; } @@ -800,6 +871,7 @@ _cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subs if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; + ASSERT_NOT_REACHED; return CAIRO_STATUS_SUCCESS; } @@ -830,15 +902,20 @@ BAIL: return status; } -static void +static cairo_status_t _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface) { char buf[4096]; int n; + if (ferror (surface->tmpfile) != 0) + return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR); + rewind (surface->tmpfile); while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0) _cairo_output_stream_write (surface->final_stream, buf, n); + + return CAIRO_STATUS_SUCCESS; } static void @@ -863,7 +940,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, double width, double height) { - cairo_status_t status; + cairo_status_t status, status_ignored; cairo_ps_surface_t *surface; surface = malloc (sizeof (cairo_ps_surface_t)); @@ -878,20 +955,32 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->final_stream = stream; surface->tmpfile = tmpfile (); - if (surface->tmpfile == NULL) + if (surface->tmpfile == NULL) { + switch (errno) { + case ENOMEM: + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + break; + default: + status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR); + break; + } goto CLEANUP_SURFACE; + } surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile); status = _cairo_output_stream_get_status (surface->stream); if (status) - goto CLEANUP_TMPFILE; + goto CLEANUP_OUTPUT_STREAM; surface->font_subsets = _cairo_scaled_font_subsets_create_simple (); - if (! surface->font_subsets) + if (surface->font_subsets == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_OUTPUT_STREAM; + } surface->eps = FALSE; surface->ps_level = CAIRO_PS_LEVEL_3; + surface->ps_level_used = CAIRO_PS_LEVEL_2; surface->width = width; surface->height = height; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; @@ -911,22 +1000,21 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, CAIRO_CONTENT_COLOR_ALPHA, width, height, &cairo_ps_surface_paginated_backend); - if (surface->paginated_surface->status == CAIRO_STATUS_SUCCESS) + status = surface->paginated_surface->status; + if (status == CAIRO_STATUS_SUCCESS) return surface->paginated_surface; _cairo_scaled_font_subsets_destroy (surface->font_subsets); CLEANUP_OUTPUT_STREAM: - status = _cairo_output_stream_destroy (surface->stream); - /* Ignore status---we're already on a failure path. */ - CLEANUP_TMPFILE: + status_ignored = _cairo_output_stream_destroy (surface->stream); fclose (surface->tmpfile); CLEANUP_SURFACE: free (surface); CLEANUP: /* destroy stream on behalf of caller */ - status = _cairo_output_stream_destroy (stream); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + status_ignored = _cairo_output_stream_destroy (stream); + + return _cairo_surface_create_in_error (status); } /** @@ -958,15 +1046,11 @@ cairo_ps_surface_create (const char *filename, double width_in_points, double height_in_points) { - cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create_for_filename (filename); - status = _cairo_output_stream_get_status (stream); - if (status) - return (status == CAIRO_STATUS_WRITE_ERROR) ? - (cairo_surface_t*) &_cairo_surface_nil_write_error : - (cairo_surface_t*) &_cairo_surface_nil; + if (_cairo_output_stream_get_status (stream)) + return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); return _cairo_ps_surface_create_for_stream_internal (stream, width_in_points, @@ -1004,13 +1088,11 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, double width_in_points, double height_in_points) { - cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create (write_func, NULL, closure); - status = _cairo_output_stream_get_status (stream); - if (status) - return (cairo_surface_t*) &_cairo_surface_nil; + if (_cairo_output_stream_get_status (stream)) + return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); return _cairo_ps_surface_create_for_stream_internal (stream, width_in_points, @@ -1436,11 +1518,16 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_ps_surface_emit_header (surface); status = _cairo_ps_surface_emit_font_subsets (surface); + if (status) + goto CLEANUP; - _cairo_ps_surface_emit_body (surface); + status = _cairo_ps_surface_emit_body (surface); + if (status) + goto CLEANUP; _cairo_ps_surface_emit_footer (surface); +CLEANUP: status2 = _cairo_output_stream_destroy (surface->stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; @@ -1515,7 +1602,6 @@ static cairo_status_t _analyze_image_transparency (cairo_image_surface_t *image, cairo_image_transparency_t *transparency) { - cairo_status_t status; int x, y; if (image->format == CAIRO_FORMAT_RGB24) { @@ -1547,9 +1633,8 @@ _analyze_image_transparency (cairo_image_surface_t *image, } } } - status = CAIRO_STATUS_SUCCESS; - return status; + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -1580,10 +1665,12 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t break; case CAIRO_IMAGE_HAS_BILEVEL_ALPHA: - if (surface->ps_level == CAIRO_PS_LEVEL_2) + if (surface->ps_level == CAIRO_PS_LEVEL_2) { status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - else + } else { + surface->ps_level_used = CAIRO_PS_LEVEL_3; status = CAIRO_STATUS_SUCCESS; + } break; case CAIRO_IMAGE_HAS_ALPHA: @@ -1646,6 +1733,7 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface, if (surface->ps_level == CAIRO_PS_LEVEL_2) return FALSE; + surface->ps_level_used = CAIRO_PS_LEVEL_3; extend = cairo_pattern_get_extend (pattern); if (extend == CAIRO_EXTEND_REPEAT || @@ -1706,19 +1794,16 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface, op == CAIRO_OPERATOR_OVER)) return CAIRO_INT_STATUS_UNSUPPORTED; - if (op == CAIRO_OPERATOR_SOURCE) - return CAIRO_STATUS_SUCCESS; - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; if ( _cairo_surface_is_meta (surface_pattern->surface)) return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN; - else - return _cairo_ps_surface_analyze_surface_pattern_transparency (surface, - surface_pattern); } + if (op == CAIRO_OPERATOR_SOURCE) + return CAIRO_STATUS_SUCCESS; + /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If * the pattern contains transparency, we return * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis @@ -1729,6 +1814,13 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface, * background to convert the pattern to opaque. */ + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; + + return _cairo_ps_surface_analyze_surface_pattern_transparency (surface, + surface_pattern); + } + if (_cairo_pattern_is_opaque (pattern)) return CAIRO_STATUS_SUCCESS; else @@ -1889,10 +1981,8 @@ _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t *surface, opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24, image->width, image->height); - if (opaque->status) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return status; - } + if (opaque->status) + return opaque->status; _cairo_pattern_init_for_surface (&pattern.surface, &image->base); @@ -1930,8 +2020,8 @@ fail: static cairo_status_t _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, - unsigned char *data, - unsigned long length) + unsigned char *data, + unsigned long length) { cairo_output_stream_t *base85_stream, *string_array_stream; cairo_status_t status, status2; @@ -1939,13 +2029,13 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, string_array_stream = _string_array_stream_create (surface->stream); status = _cairo_output_stream_get_status (string_array_stream); if (status) - return status; + return _cairo_output_stream_destroy (string_array_stream); base85_stream = _cairo_base85_stream_create (string_array_stream); status = _cairo_output_stream_get_status (base85_stream); if (status) { status2 = _cairo_output_stream_destroy (string_array_stream); - return status; + return _cairo_output_stream_destroy (base85_stream); } _cairo_output_stream_write (base85_stream, data, length); @@ -1962,7 +2052,7 @@ static cairo_status_t _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, const char *name, - cairo_operator_t op) + cairo_operator_t op) { cairo_status_t status; unsigned char *rgb, *rgb_compressed; @@ -1988,10 +2078,14 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, if (op == CAIRO_OPERATOR_SOURCE || transparency == CAIRO_IMAGE_HAS_ALPHA || (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA && - surface->ps_level == CAIRO_PS_LEVEL_2)) { - _cairo_ps_surface_flatten_image_transparency (surface, - image, - &opaque_image); + surface->ps_level == CAIRO_PS_LEVEL_2)) + { + status = _cairo_ps_surface_flatten_image_transparency (surface, + image, + &opaque_image); + if (status) + return status; + use_mask = FALSE; } else if (transparency == CAIRO_IMAGE_IS_OPAQUE) { opaque_image = image; @@ -2008,7 +2102,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, } if (use_mask) { - mask_size = (image->width * image->height + 7)/8; + mask_size = ((image->width+7) / 8) * image->height; mask = malloc (mask_size); if (mask == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2036,6 +2130,11 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, rgb[i++] = (*pixel & 0x0000ff00) >> 8; rgb[i++] = (*pixel & 0x000000ff) >> 0; } + + if (bit != 7) { + bit = 7; + byte++; + } } } else { i = 0; @@ -2193,7 +2292,7 @@ _cairo_ps_surface_emit_image_surface (cairo_ps_surface_t *surface, cairo_surface_pattern_t *pattern, int *width, int *height, - cairo_operator_t op) + cairo_operator_t op) { cairo_image_surface_t *image; void *image_extra; @@ -2205,7 +2304,7 @@ _cairo_ps_surface_emit_image_surface (cairo_ps_surface_t *surface, if (status) return status; - _cairo_ps_surface_emit_image (surface, image, "CairoPattern", op); + status = _cairo_ps_surface_emit_image (surface, image, "CairoPattern", op); if (status) goto fail; @@ -2248,7 +2347,9 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface, surface->height); } - status = _cairo_meta_surface_replay (meta_surface, &surface->base); + status = _cairo_meta_surface_replay_region (meta_surface, &surface->base, + CAIRO_META_REGION_NATIVE); + assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (status) return status; @@ -2263,11 +2364,11 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface, } static void -_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface, - const cairo_color_t *color, - double *red, - double *green, - double *blue) +_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface, + const cairo_color_t *color, + double *red, + double *green, + double *blue) { *red = color->red; *green = color->green; @@ -2309,7 +2410,7 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface, static cairo_status_t _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, cairo_surface_pattern_t *pattern, - cairo_operator_t op) + cairo_operator_t op) { cairo_status_t status; int pattern_width = 0; /* squelch bogus compiler warning */ @@ -2327,9 +2428,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, status = _cairo_ps_surface_emit_meta_surface (surface, meta_surface); + if (status) + return status; + status = _cairo_surface_get_extents (meta_surface, &pattern_extents); if (status) return status; + pattern_width = pattern_extents.width; pattern_height = pattern_extents.height; } else { @@ -2475,7 +2580,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface, allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t)); if (allstops == NULL) - return CAIRO_STATUS_NO_MEMORY; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); stops = &allstops[1]; n_stops = pattern->n_stops; @@ -2531,6 +2636,9 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface, cairo_status_t status; cairo_matrix_t inverse = pattern->base.base.matrix; + if (pattern->base.n_stops == 0) + return CAIRO_INT_STATUS_NOTHING_TO_DO; + extend = cairo_pattern_get_extend (&pattern->base.base); status = cairo_matrix_invert (&inverse); @@ -2586,6 +2694,9 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface, cairo_status_t status; cairo_matrix_t inverse = pattern->base.base.matrix; + if (pattern->base.n_stops == 0) + return CAIRO_INT_STATUS_NOTHING_TO_DO; + extend = cairo_pattern_get_extend (&pattern->base.base); status = cairo_matrix_invert (&inverse); @@ -2658,11 +2769,17 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, break; case CAIRO_PATTERN_TYPE_LINEAR: - _cairo_ps_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); + status = _cairo_ps_surface_emit_linear_pattern (surface, + (cairo_linear_pattern_t *) pattern); + if (status) + return status; break; case CAIRO_PATTERN_TYPE_RADIAL: - _cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); + status = _cairo_ps_surface_emit_radial_pattern (surface, + (cairo_radial_pattern_t *) pattern); + if (status) + return status; break; } @@ -2777,6 +2894,9 @@ _cairo_ps_surface_paint (void *abstract_surface, _cairo_rectangle_intersect (&extents, &pattern_extents); status = _cairo_ps_surface_emit_pattern (surface, source, op); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; + if (status) return status; @@ -2920,13 +3040,24 @@ _cairo_ps_surface_stroke (void *abstract_surface, } status = _cairo_ps_surface_emit_pattern (surface, source, op); - if (status) + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; + + if (status) { + if (dash != style->dash) + free (dash); return status; + } _cairo_output_stream_printf (stream, "gsave\n"); status = _cairo_ps_surface_emit_path (surface, stream, path, style->line_cap); + if (status) { + if (dash != style->dash) + free (dash); + return status; + } /* * Switch to user space to set line parameters @@ -2963,7 +3094,8 @@ _cairo_ps_surface_stroke (void *abstract_surface, "stroke\n"); _cairo_output_stream_printf (stream, "grestore\n"); - return status; + + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t @@ -2991,6 +3123,9 @@ _cairo_ps_surface_fill (void *abstract_surface, #endif status = _cairo_ps_surface_emit_pattern (surface, source, op); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; + if (status) return status; @@ -3060,6 +3195,9 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, num_glyphs_unsigned = num_glyphs; status = _cairo_ps_surface_emit_pattern (surface, source, op); + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) + return CAIRO_STATUS_SUCCESS; + if (status) return status; @@ -3073,6 +3211,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, &subset_glyph); if (status) goto fail; + glyph_ids[i].subset_id = subset_glyph.subset_id; glyph_ids[i].glyph_id = subset_glyph.subset_glyph_index; } @@ -3119,9 +3258,10 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, _cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id); } else { word_wrap = _word_wrap_stream_create (surface->stream, 79); - status = _cairo_output_stream_get_status (word_wrap); - if (status) + if (_cairo_output_stream_get_status (word_wrap)) { + status = _cairo_output_stream_destroy (word_wrap); goto fail; + } _cairo_output_stream_printf (word_wrap, "<"); for (j = i; j < last+1; j++) @@ -3149,7 +3289,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, } else { for (j = i; j < last+1; j++) { if (j == num_glyphs_unsigned - 1) - _cairo_output_stream_printf (word_wrap, "0 "); + _cairo_output_stream_printf (word_wrap, "0 0 "); else _cairo_output_stream_printf (word_wrap, "%f %f ", diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index 7f1f7d2c1f3f..e085ca9cf7ae 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -1,7 +1,7 @@ /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ /* cairo - a vector graphics library with display and print output * - * Copyright © 2006, 2007 Mozilla Corporation + * Copyright � 2006, 2007 Mozilla Corporation * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -34,6 +34,8 @@ * Vladimir Vukicevic */ +#include + #include "cairoint.h" #include "cairo-quartz-private.h" @@ -57,6 +59,8 @@ #define ND(_x) do {} while(0) #endif +#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0) + /* This method is private, but it exists. Its params are are exposed * as args to the NS* method, but not as CG. */ @@ -84,7 +88,7 @@ CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef); /* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9 * has all the stuff we care about, just some of it isn't exported in the SDK. - */ + */ #ifndef kCGBitmapByteOrder32Host #define USE_10_3_WORKAROUNDS #define kCGBitmapAlphaInfoMask 0x1F @@ -98,8 +102,12 @@ CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef); CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); #endif -/* missing in 10.3.9 */ -extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__((weak_import)); +/* Only present in 10.4+ */ +static void (*CGContextClipToMaskPtr) (CGContextRef, CGRect, CGImageRef) = NULL; +/* Only present in 10.5+ */ +static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL; + +static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE; /* * Utility functions @@ -108,6 +116,24 @@ extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__ static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest); static void quartz_image_to_png (CGImageRef, char *dest); +static cairo_quartz_surface_t * +_cairo_quartz_surface_create_internal (CGContextRef cgContext, + cairo_content_t content, + unsigned int width, + unsigned int height); + +/* Load all extra symbols */ +static void quartz_ensure_symbols(void) +{ + if (_cairo_quartz_symbol_lookup_done) + return; + + CGContextClipToMaskPtr = dlsym(RTLD_DEFAULT, "CGContextClipToMask"); + CGContextDrawTiledImagePtr = dlsym(RTLD_DEFAULT, "CGContextDrawTiledImage"); + + _cairo_quartz_symbol_lookup_done = TRUE; +} + /* CoreGraphics limitation with flipped CTM surfaces: height must be less than signed 16-bit max */ #define CG_MAX_HEIGHT SHRT_MAX @@ -160,7 +186,7 @@ _cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point) quartz_stroke_t *stroke = (quartz_stroke_t *)closure; double x = _cairo_fixed_to_double (point->x); double y = _cairo_fixed_to_double (point->y); - + if (stroke->ctm_inverse) cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y); @@ -367,94 +393,6 @@ CreateGradientFunction (cairo_gradient_pattern_t *gpat) &callbacks); } -static cairo_int_status_t -_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat, - CGShadingRef *shading) -{ - cairo_matrix_t mat; - double x0, y0; - - if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR && - abspat->type != CAIRO_PATTERN_TYPE_RADIAL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* bandaid for mozilla bug 379321, also visible in the - * linear-gradient-reflect test. - */ - if (abspat->extend == CAIRO_EXTEND_REFLECT || - abspat->extend == CAIRO_EXTEND_REPEAT) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* We can only do this if we have an identity pattern matrix; - * otherwise fall back through to the generic pattern case. - * XXXperf we could optimize this by creating a pattern with the shading; - * but we'd need to know the extents to do that. - * ... but we don't care; we can use the surface extents for it - * XXXtodo - implement gradients with non-identity pattern matrices - */ - cairo_pattern_get_matrix (abspat, &mat); - if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - x0 = mat.x0; - y0 = mat.y0; - - if (abspat->type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t*) abspat; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - bool extend = abspat->extend == CAIRO_EXTEND_PAD; - - start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x) - x0, - _cairo_fixed_to_double (lpat->p1.y) - y0); - end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x) - x0, - _cairo_fixed_to_double (lpat->p2.y) - y0); - - cairo_pattern_reference (abspat); - gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat); - *shading = CGShadingCreateAxial (rgb, - start, end, - gradFunc, - extend, extend); - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return CAIRO_STATUS_SUCCESS; - } - - if (abspat->type == CAIRO_PATTERN_TYPE_RADIAL) { - cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t*) abspat; - CGPoint start, end; - CGFunctionRef gradFunc; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - bool extend = abspat->extend == CAIRO_EXTEND_PAD; - - start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x) - x0, - _cairo_fixed_to_double (rpat->c1.y) - y0); - end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x) - x0, - _cairo_fixed_to_double (rpat->c2.y) - y0); - - cairo_pattern_reference (abspat); - gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat); - *shading = CGShadingCreateRadial (rgb, - start, - _cairo_fixed_to_double (rpat->r1), - end, - _cairo_fixed_to_double (rpat->r2), - gradFunc, - extend, extend); - CGColorSpaceRelease(rgb); - CGFunctionRelease(gradFunc); - - return CAIRO_STATUS_SUCCESS; - } - - /* Shouldn't be reached */ - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; -} - /* generic cairo surface -> cairo_quartz_surface_t function */ static cairo_int_status_t _cairo_quartz_surface_to_quartz (cairo_surface_t *target, @@ -690,9 +628,123 @@ typedef enum { DO_SHADING, DO_PATTERN, DO_IMAGE, - DO_UNSUPPORTED + DO_UNSUPPORTED, + DO_NOTHING, + DO_TILED_IMAGE } cairo_quartz_action_t; +static cairo_quartz_action_t +_cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface, + cairo_linear_pattern_t *lpat) +{ + cairo_pattern_t *abspat = (cairo_pattern_t *) lpat; + cairo_matrix_t mat; + double x0, y0; + CGPoint start, end; + CGFunctionRef gradFunc; + CGColorSpaceRef rgb; + bool extend = abspat->extend == CAIRO_EXTEND_PAD; + + /* bandaid for mozilla bug 379321, also visible in the + * linear-gradient-reflect test. + */ + if (abspat->extend == CAIRO_EXTEND_REFLECT || + abspat->extend == CAIRO_EXTEND_REPEAT) + return DO_UNSUPPORTED; + + /* We can only do this if we have an identity pattern matrix; + * otherwise fall back through to the generic pattern case. + * XXXperf we could optimize this by creating a pattern with the shading; + * but we'd need to know the extents to do that. + * ... but we don't care; we can use the surface extents for it + * XXXtodo - implement gradients with non-identity pattern matrices + */ + cairo_pattern_get_matrix (abspat, &mat); + if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0) + return DO_UNSUPPORTED; + + if (!lpat->base.n_stops) { + CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.); + CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.); + return DO_SOLID; + } + + x0 = mat.x0; + y0 = mat.y0; + rgb = CGColorSpaceCreateDeviceRGB(); + + start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x) - x0, + _cairo_fixed_to_double (lpat->p1.y) - y0); + end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x) - x0, + _cairo_fixed_to_double (lpat->p2.y) - y0); + + cairo_pattern_reference (abspat); + gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat); + surface->sourceShading = CGShadingCreateAxial (rgb, + start, end, + gradFunc, + extend, extend); + CGColorSpaceRelease(rgb); + CGFunctionRelease(gradFunc); + + return DO_SHADING; +} + +static cairo_quartz_action_t +_cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface, + cairo_radial_pattern_t *rpat) +{ + cairo_pattern_t *abspat = (cairo_pattern_t *)rpat; + cairo_matrix_t mat; + double x0, y0; + CGPoint start, end; + CGFunctionRef gradFunc; + CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); + bool extend = abspat->extend == CAIRO_EXTEND_PAD; + + /* bandaid for mozilla bug 379321, also visible in the + * linear-gradient-reflect test. + */ + if (abspat->extend == CAIRO_EXTEND_REFLECT || + abspat->extend == CAIRO_EXTEND_REPEAT) + return DO_UNSUPPORTED; + + /* XXXtodo - implement gradients with non-identity pattern matrices + */ + cairo_pattern_get_matrix (abspat, &mat); + if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0) + return DO_UNSUPPORTED; + + if (!rpat->base.n_stops) { + CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.); + CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.); + return DO_SOLID; + } + + x0 = mat.x0; + y0 = mat.y0; + rgb = CGColorSpaceCreateDeviceRGB(); + + start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x) - x0, + _cairo_fixed_to_double (rpat->c1.y) - y0); + end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x) - x0, + _cairo_fixed_to_double (rpat->c2.y) - y0); + + cairo_pattern_reference (abspat); + gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat); + surface->sourceShading = CGShadingCreateRadial (rgb, + start, + _cairo_fixed_to_double (rpat->r1), + end, + _cairo_fixed_to_double (rpat->r2), + gradFunc, + extend, extend); + CGColorSpaceRelease(rgb); + CGFunctionRelease(gradFunc); + + return DO_SHADING; +} + static cairo_quartz_action_t _cairo_quartz_setup_source (cairo_quartz_surface_t *surface, cairo_pattern_t *source) @@ -714,53 +766,99 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface, solid->color.alpha); return DO_SOLID; - } else if (source->type == CAIRO_PATTERN_TYPE_LINEAR || - source->type == CAIRO_PATTERN_TYPE_RADIAL) - { - CGShadingRef shading = NULL; - cairo_int_status_t status; + } - status = _cairo_quartz_cairo_gradient_pattern_to_quartz (source, &shading); + if (source->type == CAIRO_PATTERN_TYPE_LINEAR) { + cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *)source; + return _cairo_quartz_setup_linear_source (surface, lpat); + + } + + if (source->type == CAIRO_PATTERN_TYPE_RADIAL) { + cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *)source; + return _cairo_quartz_setup_radial_source (surface, rpat); + + } + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE && + (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))) + { + cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source; + cairo_surface_t *pat_surf = spat->surface; + cairo_quartz_surface_t *quartz_surf; + CGImageRef img; + cairo_matrix_t m = spat->base.matrix; + cairo_rectangle_int_t extents; + cairo_status_t status; + CGAffineTransform xform; + CGRect srcRect; + cairo_fixed_t fw, fh; + + status = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf, &quartz_surf); if (status) return DO_UNSUPPORTED; - surface->sourceShading = shading; + surface->sourceImageSurface = (cairo_surface_t *)quartz_surf; - return DO_SHADING; - } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - source->extend == CAIRO_EXTEND_NONE) - { - cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source; - cairo_surface_t *pat_surf = spat->surface; - cairo_quartz_surface_t *quartz_surf; - CGImageRef img; - cairo_matrix_t m = spat->base.matrix; - cairo_rectangle_int_t extents; - cairo_status_t status; + if (IS_EMPTY(quartz_surf)) + return DO_NOTHING; - status = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf, &quartz_surf); - if (status) - return DO_UNSUPPORTED; + img = CGBitmapContextCreateImage (quartz_surf->cgContext); + if (!img) + return DO_UNSUPPORTED; - img = CGBitmapContextCreateImage (quartz_surf->cgContext); - if (!img) - return DO_UNSUPPORTED; + surface->sourceImage = img; - surface->sourceImage = img; + cairo_matrix_invert(&m); + _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform); - cairo_matrix_invert(&m); - _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform); - - status = _cairo_surface_get_extents (pat_surf, &extents); - if (status) - return DO_UNSUPPORTED; + status = _cairo_surface_get_extents (pat_surf, &extents); + if (status) + return DO_UNSUPPORTED; + if (source->extend == CAIRO_EXTEND_NONE) { surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height); - - surface->sourceImageSurface = (cairo_surface_t *)quartz_surf; - return DO_IMAGE; - } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + } + + /* Quartz seems to tile images at pixel-aligned regions only -- this + * leads to seams if the image doesn't end up scaling to fill the + * space exactly. The CGPattern tiling approach doesn't have this + * problem. Check if we're going to fill up the space (within some + * epsilon), and if not, fall back to the CGPattern type. + */ + + xform = CGAffineTransformConcat (CGContextGetCTM (surface->cgContext), + surface->sourceImageTransform); + + srcRect = CGRectMake (0, 0, extents.width, extents.height); + srcRect = CGRectApplyAffineTransform (srcRect, xform); + + fw = _cairo_fixed_from_double (srcRect.size.width); + fh = _cairo_fixed_from_double (srcRect.size.height); + + if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON && + (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON) + { + /* We're good to use DrawTiledImage, but ensure that + * the math works out */ + + srcRect.size.width = round(srcRect.size.width); + srcRect.size.height = round(srcRect.size.height); + + xform = CGAffineTransformInvert (xform); + + srcRect = CGRectApplyAffineTransform (srcRect, xform); + + surface->sourceImageRect = srcRect; + + return DO_TILED_IMAGE; + } + + /* Fall through to generic SURFACE case */ + } + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { float patternAlpha = 1.0f; CGColorSpaceRef patternSpace; CGPatternRef pattern; @@ -791,11 +889,9 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface, surface->sourcePattern = pattern; return DO_PATTERN; - } else { - return DO_UNSUPPORTED; } - ASSERT_NOT_REACHED; + return DO_UNSUPPORTED; } static void @@ -828,23 +924,19 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface, * get source/dest image implementation */ -static void -ImageDataReleaseFunc(void *info, const void *data, size_t size) -{ - if (data != NULL) { - free((void *) data); - } -} - /* Read the image from the surface's front buffer */ static cairo_int_status_t _cairo_quartz_get_image (cairo_quartz_surface_t *surface, - cairo_image_surface_t **image_out, - unsigned char **data_out) + cairo_image_surface_t **image_out) { unsigned char *imageData; cairo_image_surface_t *isurf; + if (IS_EMPTY(surface)) { + *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); + return CAIRO_STATUS_SUCCESS; + } + if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) { unsigned int stride; unsigned int bitinfo; @@ -927,6 +1019,9 @@ _cairo_quartz_surface_finish (void *abstract_surface) ND((stderr, "_cairo_quartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext)); + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; + /* Restore our saved gstate that we use to reset clipping */ CGContextRestoreGState (surface->cgContext); @@ -952,12 +1047,12 @@ _cairo_quartz_surface_acquire_source_image (void *abstract_surface, //ND((stderr, "%p _cairo_quartz_surface_acquire_source_image\n", surface)); - *image_extra = NULL; - - status = _cairo_quartz_get_image (surface, image_out, NULL); + status = _cairo_quartz_get_image (surface, image_out); if (status) return _cairo_error (CAIRO_STATUS_NO_MEMORY); + *image_extra = NULL; + return CAIRO_STATUS_SUCCESS; } @@ -979,17 +1074,15 @@ _cairo_quartz_surface_acquire_dest_image (void *abstract_surface, { cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; cairo_int_status_t status; - unsigned char *data; ND((stderr, "%p _cairo_quartz_surface_acquire_dest_image\n", surface)); - *image_rect = surface->extents; - - status = _cairo_quartz_get_image (surface, image_out, &data); + status = _cairo_quartz_get_image (surface, image_out); if (status) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - *image_extra = data; + *image_rect = surface->extents; + *image_extra = NULL; return CAIRO_STATUS_SUCCESS; } @@ -1001,43 +1094,10 @@ _cairo_quartz_surface_release_dest_image (void *abstract_surface, cairo_rectangle_int_t *image_rect, void *image_extra) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - unsigned char *imageData = (unsigned char *) image_extra; + //cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; //ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface)); - if (!CGBitmapContextGetData (surface->cgContext)) { - CGDataProviderRef dataProvider; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGImageRef img; - - dataProvider = CGDataProviderCreateWithData (NULL, imageData, - surface->extents.width * surface->extents.height * 4, - ImageDataReleaseFunc); - - img = CGImageCreate (surface->extents.width, surface->extents.height, - 8, 32, - surface->extents.width * 4, - rgb, - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, - dataProvider, - NULL, - false, - kCGRenderingIntentDefault); - CGColorSpaceRelease (rgb); - - CGContextSetCompositeOperation (surface->cgContext, kPrivateCGCompositeCopy); - - CGContextDrawImage (surface->cgContext, - CGRectMake (0, 0, surface->extents.width, surface->extents.height), - img); - - CGImageRelease (img); - CGDataProviderRelease (dataProvider); - - ND((stderr, "Image for surface %p was recovered from a bitmap\n", surface)); - } - cairo_surface_destroy ((cairo_surface_t *) image); } @@ -1059,7 +1119,7 @@ _cairo_quartz_surface_create_similar (void *abstract_surface, format = CAIRO_FORMAT_A8; else return NULL; - + // verify width and height of surface if (!verify_surface_size(width, height)) { _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1080,7 +1140,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, { cairo_quartz_surface_t *new_surface = NULL; cairo_format_t new_format; - + CGImageRef quartz_image = NULL; + *clone_out = NULL; // verify width and height of surface @@ -1088,10 +1149,14 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, return CAIRO_INT_STATUS_UNSUPPORTED; } - CGImageRef quartz_image = NULL; - if (cairo_surface_get_type(src) == CAIRO_SURFACE_TYPE_QUARTZ) { cairo_quartz_surface_t *qsurf = (cairo_quartz_surface_t *) src; + + if (IS_EMPTY(qsurf)) { + *clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, qsurf->extents.width, qsurf->extents.height); + return CAIRO_STATUS_SUCCESS; + } + quartz_image = CGBitmapContextCreateImage (qsurf->cgContext); new_format = CAIRO_FORMAT_ARGB32; /* XXX bogus; recover a real format from the image */ } else if (_cairo_surface_is_image (src)) { @@ -1101,6 +1166,11 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface, CGBitmapInfo bitinfo; int bitsPerComponent, bitsPerPixel; + if (isurf->width == 0 || isurf->height == 0) { + *clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, isurf->width, isurf->height); + return CAIRO_STATUS_SUCCESS; + } + if (isurf->format == CAIRO_FORMAT_ARGB32) { cgColorspace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; @@ -1193,6 +1263,9 @@ _cairo_quartz_surface_paint (void *abstract_surface, ND((stderr, "%p _cairo_quartz_surface_paint op %d source->type %d\n", surface, op, source->type)); + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_DEST) return CAIRO_STATUS_SUCCESS; @@ -1207,20 +1280,25 @@ _cairo_quartz_surface_paint (void *abstract_surface, surface->extents.height)); } else if (action == DO_SHADING) { CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else if (action == DO_IMAGE) { + } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; cairo_surface_t *pat_surf = surface_pattern->surface; + CGContextSaveGState (surface->cgContext); + CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform); if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) { CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage)); CGContextScaleCTM (surface->cgContext, 1, -1); } - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + if (action == DO_IMAGE) + CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + else + CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); CGContextRestoreGState (surface->cgContext); - } else { + } else if (action != DO_NOTHING) { rv = CAIRO_INT_STATUS_UNSUPPORTED; } @@ -1246,6 +1324,9 @@ _cairo_quartz_surface_fill (void *abstract_surface, ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type)); + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_DEST) return CAIRO_STATUS_SUCCESS; @@ -1255,10 +1336,6 @@ _cairo_quartz_surface_fill (void *abstract_surface, CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); action = _cairo_quartz_setup_source (surface, source); - if (action == DO_UNSUPPORTED) { - CGContextRestoreGState (surface->cgContext); - return CAIRO_INT_STATUS_UNSUPPORTED; - } CGContextBeginPath (surface->cgContext); @@ -1283,7 +1360,7 @@ _cairo_quartz_surface_fill (void *abstract_surface, CGContextEOClip (surface->cgContext); CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else if (action == DO_IMAGE) { + } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; cairo_surface_t *pat_surf = surface_pattern->surface; @@ -1291,14 +1368,18 @@ _cairo_quartz_surface_fill (void *abstract_surface, CGContextClip (surface->cgContext); else CGContextEOClip (surface->cgContext); + CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform); if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) { CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage)); CGContextScaleCTM (surface->cgContext, 1, -1); } - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); - } else { + if (action == DO_IMAGE) + CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + else + CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + } else if (action != DO_NOTHING) { rv = CAIRO_INT_STATUS_UNSUPPORTED; } @@ -1330,6 +1411,9 @@ _cairo_quartz_surface_stroke (void *abstract_surface, ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type)); + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; + if (op == CAIRO_OPERATOR_DEST) return CAIRO_STATUS_SUCCESS; @@ -1361,7 +1445,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface, for (k = 0; k < max_dashes; k++) fdash[k] = (float) style->dash[k % style->num_dashes]; - + CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, max_dashes); if (fdash != sdash) free (fdash); @@ -1370,10 +1454,6 @@ _cairo_quartz_surface_stroke (void *abstract_surface, CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); action = _cairo_quartz_setup_source (surface, source); - if (action == DO_UNSUPPORTED) { - CGContextRestoreGState (surface->cgContext); - return CAIRO_INT_STATUS_UNSUPPORTED; - } CGContextBeginPath (surface->cgContext); @@ -1385,7 +1465,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface, if (action == DO_SOLID || action == DO_PATTERN) { CGContextStrokePath (surface->cgContext); - } else if (action == DO_IMAGE) { + } else if (action == DO_IMAGE || action == DO_TILED_IMAGE) { CGContextReplacePathWithStrokedPath (surface->cgContext); CGContextClip (surface->cgContext); @@ -1395,13 +1475,16 @@ _cairo_quartz_surface_stroke (void *abstract_surface, CGContextScaleCTM (surface->cgContext, 1, -1); } - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + if (action == DO_IMAGE) + CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + else + CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); } else if (action == DO_SHADING) { CGContextReplacePathWithStrokedPath (surface->cgContext); CGContextClip (surface->cgContext); CGContextDrawShading (surface->cgContext, surface->sourceShading); - } else { + } else if (action != DO_NOTHING) { rv = CAIRO_INT_STATUS_UNSUPPORTED; } @@ -1436,6 +1519,10 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface, cairo_quartz_action_t action; float xprev, yprev; int i; + CGFontRef cgfref; + + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; if (num_glyphs <= 0) return CAIRO_STATUS_SUCCESS; @@ -1451,17 +1538,18 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface, action = _cairo_quartz_setup_source (surface, source); if (action == DO_SOLID || action == DO_PATTERN) { CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill); - } else if (action == DO_IMAGE || action == DO_SHADING) { + } else if (action == DO_IMAGE || action == DO_TILED_IMAGE || action == DO_SHADING) { CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip); } else { - /* Unsupported */ - rv = CAIRO_INT_STATUS_UNSUPPORTED; + if (action != DO_NOTHING) + rv = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; } CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op)); - CGFontRef cgfref = _cairo_atsui_scaled_font_get_cg_font_ref (scaled_font); + /* this doesn't addref */ + cgfref = _cairo_atsui_scaled_font_get_cg_font_ref (scaled_font); CGContextSetFont (surface->cgContext, cgfref); /* So this should include the size; I don't know if I need to extract the @@ -1470,9 +1558,9 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface, * text matrix? */ //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y)); - cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx, + cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx, scaled_font->font_matrix.yx, - scaled_font->font_matrix.xy, + scaled_font->font_matrix.xy, scaled_font->font_matrix.yy, 0., 0.); @@ -1532,14 +1620,17 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface, cg_advances, num_glyphs); - if (action == DO_IMAGE) { + if (action == DO_IMAGE || action == DO_TILED_IMAGE) { CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform); if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) { CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage)); CGContextScaleCTM (surface->cgContext, 1, -1); } - CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + if (action == DO_IMAGE) + CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage); + else + CGContextDrawTiledImagePtr (surface->cgContext, surface->sourceImageRect, surface->sourceImage); } else if (action == DO_SHADING) { CGContextDrawShading (surface->cgContext, surface->sourceShading); } @@ -1554,7 +1645,7 @@ BAIL: } _cairo_quartz_teardown_source (surface, source); - + CGContextRestoreGState (surface->cgContext); return rv; @@ -1582,6 +1673,10 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface, if (status) return status; + // everything would be masked out, so do nothing + if (IS_EMPTY(quartz_surf)) + goto BAIL; + img = CGBitmapContextCreateImage (quartz_surf->cgContext); if (!img) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1590,7 +1685,7 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface, rect = CGRectMake (-mask->base.matrix.x0, -mask->base.matrix.y0, extents.width, extents.height); CGContextSaveGState (surface->cgContext); - CGContextClipToMask (surface->cgContext, rect, img); + CGContextClipToMaskPtr (surface->cgContext, rect, img); status = _cairo_quartz_surface_paint (surface, op, source); CGContextRestoreGState (surface->cgContext); @@ -1611,12 +1706,15 @@ _cairo_quartz_surface_mask (void *abstract_surface, ND((stderr, "%p _cairo_quartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type)); + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; + if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { /* This is easy; we just need to paint with the alpha. */ cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha); - } else if (CGContextClipToMask && + } else if (CGContextClipToMaskPtr && mask->type == CAIRO_PATTERN_TYPE_SURFACE && mask->extend == CAIRO_EXTEND_NONE) { return _cairo_quartz_surface_mask_with_surface (surface, op, source, (cairo_surface_pattern_t *) mask); @@ -1655,6 +1753,9 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface, ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path)); + if (IS_EMPTY(surface)) + return CAIRO_STATUS_SUCCESS; + if (path == NULL) { /* If we're being asked to reset the clip, we can only do it * by restoring the gstate to our previous saved one, and @@ -1671,7 +1772,7 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface, stroke.ctm_inverse = NULL; /* path must not be empty. */ - CGContextMoveToPoint (surface->cgContext, 0, 0); + CGContextMoveToPoint (surface->cgContext, 0, 0); status = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke); if (status) return status; @@ -1719,7 +1820,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { _cairo_quartz_surface_fill, #if CAIRO_HAS_ATSUI_FONT _cairo_quartz_surface_show_glyphs, -#else +#else NULL, /* surface_show_glyphs */ #endif /* CAIRO_HAS_ATSUI_FONT */ @@ -1729,7 +1830,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { NULL /* fill_stroke */ }; -static cairo_quartz_surface_t * +cairo_quartz_surface_t * _cairo_quartz_surface_create_internal (CGContextRef cgContext, cairo_content_t content, unsigned int width, @@ -1737,12 +1838,12 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, { cairo_quartz_surface_t *surface; + quartz_ensure_symbols(); + /* Init the base surface */ surface = malloc(sizeof(cairo_quartz_surface_t)); - if (surface == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return NULL; - } + if (surface == NULL) + return (cairo_quartz_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); memset(surface, 0, sizeof(cairo_quartz_surface_t)); @@ -1754,6 +1855,13 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, surface->extents.width = width; surface->extents.height = height; + if (IS_EMPTY(surface)) { + surface->cgContext = NULL; + surface->cgContextBaseCTM = CGAffineTransformIdentity; + surface->imageData = NULL; + return surface; + } + /* Save so we can always get back to a known-good CGContext -- this is * required for proper behaviour of intersect_clip_path(NULL) */ @@ -1766,7 +1874,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, return surface; } - + /** * cairo_quartz_surface_create_for_cg_context * @cgContext: the existing CGContext for which to create the surface @@ -1781,7 +1889,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, * this function is called: * * - * GContextTranslateCTM (cgContext, 0.0, height); + * CGContextTranslateCTM (cgContext, 0.0, height); * CGContextScaleCTM (cgContext, 1.0, -1.0); * * @@ -1806,11 +1914,11 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, CGContextRetain (cgContext); surf = _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA, - width, height); - if (!surf) { + width, height); + if (surf->base.status) { CGContextRelease (cgContext); // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) surf; } return (cairo_surface_t *) surf; @@ -1845,9 +1953,12 @@ cairo_quartz_surface_create (cairo_format_t format, int bitsPerComponent; // verify width and height of surface - if (!verify_surface_size(width, height)) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + if (!verify_surface_size(width, height)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + + if (width == 0 || height == 0) { + return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format), + width, height); } if (format == CAIRO_FORMAT_ARGB32) { @@ -1873,19 +1984,18 @@ cairo_quartz_surface_create (cairo_format_t format, * cairo_format_t -- these are 1-bit pixels stored in 32-bit * quantities. */ - _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); } else { - _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); } imageData = _cairo_malloc_ab (height, stride); if (!imageData) { CGColorSpaceRelease (cgColorspace); - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } + /* zero the memory to match the image surface behaviour */ + memset (imageData, 0, height * stride); cgc = CGBitmapContextCreate (imageData, width, @@ -1897,9 +2007,8 @@ cairo_quartz_surface_create (cairo_format_t format, CGColorSpaceRelease (cgColorspace); if (!cgc) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); free (imageData); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } /* flip the Y axis */ @@ -1907,12 +2016,12 @@ cairo_quartz_surface_create (cairo_format_t format, CGContextScaleCTM (cgc, 1.0, -1.0); surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format), - width, height); - if (!surf) { + width, height); + if (surf->base.status) { CGContextRelease (cgc); free (imageData); // create_internal will have set an error - return (cairo_surface_t*) &_cairo_surface_nil; + return (cairo_surface_t*) surf; } surf->imageData = imageData; diff --git a/gfx/cairo/cairo/src/cairo-region.c b/gfx/cairo/cairo/src/cairo-region.c index b4b9117717b6..7bf4982a204f 100644 --- a/gfx/cairo/cairo/src/cairo-region.c +++ b/gfx/cairo/cairo/src/cairo-region.c @@ -52,14 +52,12 @@ _cairo_region_init_rect (cairo_region_t *region, rect->width, rect->height); } -#define STACK_BOXES_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_box16_t))) - cairo_int_status_t _cairo_region_init_boxes (cairo_region_t *region, cairo_box_int_t *boxes, int count) { - pixman_box16_t stack_pboxes[STACK_BOXES_LEN]; + pixman_box16_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box16_t)]; pixman_box16_t *pboxes = stack_pboxes; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; int i; diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h index eb2f7f4ef48b..6bb552e499ec 100644 --- a/gfx/cairo/cairo/src/cairo-rename.h +++ b/gfx/cairo/cairo/src/cairo-rename.h @@ -121,6 +121,7 @@ #define cairo_paint _moz_cairo_paint #define cairo_paint_with_alpha _moz_cairo_paint_with_alpha #define cairo_path_destroy _moz_cairo_path_destroy +#define cairo_path_extents _moz_cairo_path_extents #define cairo_pattern_add_color_stop_rgb _moz_cairo_pattern_add_color_stop_rgb #define cairo_pattern_add_color_stop_rgba _moz_cairo_pattern_add_color_stop_rgba #define cairo_pattern_create_for_surface _moz_cairo_pattern_create_for_surface @@ -152,11 +153,16 @@ #define cairo_pdf_surface_set_size _moz_cairo_pdf_surface_set_size #define cairo_pop_group _moz_cairo_pop_group #define cairo_pop_group_to_source _moz_cairo_pop_group_to_source +#define cairo_ps_get_levels _moz_cairo_ps_get_levels +#define cairo_ps_level_to_string _moz_cairo_ps_level_to_string #define cairo_ps_surface_create _moz_cairo_ps_surface_create #define cairo_ps_surface_create_for_stream _moz_cairo_ps_surface_create_for_stream #define cairo_ps_surface_dsc_begin_page_setup _moz_cairo_ps_surface_dsc_begin_page_setup #define cairo_ps_surface_dsc_begin_setup _moz_cairo_ps_surface_dsc_begin_setup #define cairo_ps_surface_dsc_comment _moz_cairo_ps_surface_dsc_comment +#define cairo_ps_surface_get_eps _moz_cairo_ps_surface_get_eps +#define cairo_ps_surface_restrict_to_level _moz_cairo_ps_surface_restrict_to_level +#define cairo_ps_surface_set_eps _moz_cairo_ps_surface_set_eps #define cairo_ps_surface_set_size _moz_cairo_ps_surface_set_size #define cairo_push_group _moz_cairo_push_group #define cairo_push_group_with_content _moz_cairo_push_group_with_content @@ -256,6 +262,7 @@ #define cairo_win32_font_face_create_for_hfont _moz_cairo_win32_font_face_create_for_hfont #define cairo_win32_font_face_create_for_logfontw _moz_cairo_win32_font_face_create_for_logfontw #define cairo_win32_font_face_create_for_logfontw_hfont _moz_cairo_win32_font_face_create_for_logfontw_hfont +#define cairo_win32_printing_surface_create _moz_cairo_win32_printing_surface_create #define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font #define cairo_win32_scaled_font_get_device_to_logical _moz_cairo_win32_scaled_font_get_device_to_logical #define cairo_win32_scaled_font_get_logical_to_device _moz_cairo_win32_scaled_font_get_logical_to_device @@ -282,3 +289,64 @@ #define cairo_xlib_surface_get_width _moz_cairo_xlib_surface_get_width #define cairo_xlib_surface_set_drawable _moz_cairo_xlib_surface_set_drawable #define cairo_xlib_surface_set_size _moz_cairo_xlib_surface_set_size +#define pixman_transform_point_3d _moz_pixman_transform_point_3d +#define pixman_region_set_static_pointers _moz_pixman_region_set_static_pointers +#define pixman_region_init _moz_pixman_region_init +#define pixman_region_init_rect _moz_pixman_region_init_rect +#define pixman_region_init_with_extents _moz_pixman_region_init_with_extents +#define pixman_region_fini _moz_pixman_region_fini +#define pixman_region_translate _moz_pixman_region_translate +#define pixman_region_copy _moz_pixman_region_copy +#define pixman_region_intersect _moz_pixman_region_intersect +#define pixman_region_union _moz_pixman_region_union +#define pixman_region_union_rect _moz_pixman_region_union_rect +#define pixman_region_subtract _moz_pixman_region_subtract +#define pixman_region_inverse _moz_pixman_region_inverse +#define pixman_region_contains_point _moz_pixman_region_contains_point +#define pixman_region_contains_rectangle _moz_pixman_region_contains_rectangle +#define pixman_region_not_empty _moz_pixman_region_not_empty +#define pixman_region_extents _moz_pixman_region_extents +#define pixman_region_n_rects _moz_pixman_region_n_rects +#define pixman_region_rectangles _moz_pixman_region_rectangles +#define pixman_region_equal _moz_pixman_region_equal +#define pixman_region_selfcheck _moz_pixman_region_selfcheck +#define pixman_region_reset _moz_pixman_region_reset +#define pixman_region_init_rects _moz_pixman_region_init_rects +#define pixman_blt _moz_pixman_blt +#define pixman_fill _moz_pixman_fill +#define pixman_image_create_solid_fill _moz_pixman_image_create_solid_fill +#define pixman_image_create_linear_gradient _moz_pixman_image_create_linear_gradient +#define pixman_image_create_radial_gradient _moz_pixman_image_create_radial_gradient +#define pixman_image_create_conical_gradient _moz_pixman_image_create_conical_gradient +#define pixman_image_create_bits _moz_pixman_image_create_bits +#define pixman_image_ref _moz_pixman_image_ref +#define pixman_image_unref _moz_pixman_image_unref +#define pixman_image_set_clip_region _moz_pixman_image_set_clip_region +#define pixman_image_set_has_client_clip _moz_pixman_image_set_has_client_clip +#define pixman_image_set_transform _moz_pixman_image_set_transform +#define pixman_image_set_repeat _moz_pixman_image_set_repeat +#define pixman_image_set_filter _moz_pixman_image_set_filter +#define pixman_image_set_filter_params _moz_pixman_image_set_filter_params +#define pixman_image_set_alpha_map _moz_pixman_image_set_alpha_map +#define pixman_image_set_component_alpha _moz_pixman_image_set_component_alpha +#define pixman_image_set_accessors _moz_pixman_image_set_accessors +#define pixman_image_set_indexed _moz_pixman_image_set_indexed +#define pixman_image_get_data _moz_pixman_image_get_data +#define pixman_image_get_width _moz_pixman_image_get_width +#define pixman_image_get_height _moz_pixman_image_get_height +#define pixman_image_get_stride _moz_pixman_image_get_stride +#define pixman_image_get_depth _moz_pixman_image_get_depth +#define pixman_image_fill_rectangles _moz_pixman_image_fill_rectangles +#define pixman_compute_composite_region _moz_pixman_compute_composite_region +#define pixman_image_composite _moz_pixman_image_composite +#define pixman_sample_ceil_y _moz_pixman_sample_ceil_y +#define pixman_sample_floor_y _moz_pixman_sample_floor_y +#define pixman_edge_step _moz_pixman_edge_step +#define pixman_edge_init _moz_pixman_edge_init +#define pixman_line_fixed_edge_init _moz_pixman_line_fixed_edge_init +#define pixman_rasterize_edges _moz_pixman_rasterize_edges +#define pixman_add_traps _moz_pixman_add_traps +#define pixman_add_trapezoids _moz_pixman_add_trapezoids +#define pixman_rasterize_trapezoid _moz_pixman_rasterize_trapezoid +#define pixman_transform_point_3d _moz_pixman_transform_point_3d + diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-private.h b/gfx/cairo/cairo/src/cairo-scaled-font-private.h index f16487c5c8e4..87a46166c5d3 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-private.h +++ b/gfx/cairo/cairo/src/cairo-scaled-font-private.h @@ -91,6 +91,7 @@ struct _cairo_scaled_font { /* "live" scaled_font members */ cairo_matrix_t scale; /* font space => device space */ + cairo_matrix_t scale_inverse; /* device space => font space */ cairo_font_extents_t extents; /* user space */ /* The mutex protects modification to all subsequent fields. */ diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c index 35ba53cb3924..9121aab1bf1d 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c @@ -106,6 +106,11 @@ typedef struct _cairo_string_entry { char *string; } cairo_string_entry_t; +static cairo_status_t +_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, + unsigned long scaled_font_glyph_index, + cairo_scaled_font_subsets_glyph_t *subset_glyph); + static void _cairo_sub_font_glyph_init_key (cairo_sub_font_glyph_t *sub_font_glyph, unsigned long scaled_font_glyph_index) @@ -221,6 +226,8 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_bool_t is_composite) { cairo_sub_font_t *sub_font; + cairo_status_t status; + cairo_scaled_font_subsets_glyph_t subset_glyph; sub_font = malloc (sizeof (cairo_sub_font_t)); if (sub_font == NULL) { @@ -246,9 +253,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, return NULL; } - if (parent->type != CAIRO_SUBSETS_SCALED) { - /* Reserve first glyph in subset for the .notdef glyph */ - sub_font->num_glyphs_in_current_subset++; + /* Reserve first glyph in subset for the .notdef glyph */ + status = _cairo_sub_font_map_glyph (sub_font, 0, &subset_glyph); + if (status) { + _cairo_error_throw (status); + return NULL; } return sub_font; @@ -307,6 +316,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, cairo_sub_font_glyph_t key, *sub_font_glyph; cairo_status_t status; cairo_scaled_glyph_t *scaled_glyph; + cairo_scaled_font_subsets_glyph_t tmp_subset_glyph; _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index); if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base, @@ -317,10 +327,10 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, sub_font->current_subset++; sub_font->num_glyphs_in_current_subset = 0; - if (sub_font->parent->type != CAIRO_SUBSETS_SCALED) { - /* Reserve first glyph in subset for the .notdef glyph */ - sub_font->num_glyphs_in_current_subset++; - } + /* Reserve first glyph in subset for the .notdef glyph */ + status = _cairo_sub_font_map_glyph (sub_font, 0, &tmp_subset_glyph); + if (status) + return status; } status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, @@ -381,16 +391,8 @@ _cairo_sub_font_collect (void *entry, void *closure) for (i = 0; i <= sub_font->current_subset; i++) { collection->subset_id = i; - - if (sub_font->parent->type == CAIRO_SUBSETS_SCALED) { - collection->num_glyphs = 0; - collection->max_glyph = 0; - } else { - /* Assign .notdef glyph to the first glyph in the subset */ - collection->glyphs[0] = 0; - collection->num_glyphs = 1; - collection->max_glyph = 0; - } + collection->num_glyphs = 0; + collection->max_glyph = 0; _cairo_hash_table_foreach (sub_font->sub_font_glyphs, _cairo_sub_font_glyph_collect, collection); @@ -493,10 +495,11 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets) _cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts); _cairo_hash_table_destroy (subsets->unscaled_sub_fonts); + free (subsets); } -cairo_private cairo_status_t +cairo_status_t _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, @@ -547,7 +550,9 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) return status; - if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) { + if (status == CAIRO_STATUS_SUCCESS && + subsets->type != CAIRO_SUBSETS_SCALED) + { /* Path available. Add to unscaled subset. */ key.is_scaled = FALSE; _cairo_sub_font_init_key (&key, scaled_font); @@ -722,20 +727,16 @@ _cairo_string_init_key (cairo_string_entry_t *key, char *s) key->string = s; } -static cairo_string_entry_t * -create_string_entry (char *s) +static cairo_status_t +create_string_entry (char *s, cairo_string_entry_t **entry) { - cairo_string_entry_t *entry; + *entry = malloc (sizeof (cairo_string_entry_t)); + if (*entry == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - entry = malloc (sizeof (cairo_string_entry_t)); - if (entry == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } + _cairo_string_init_key (*entry, s); - _cairo_string_init_key (entry, s); - - return entry; + return CAIRO_STATUS_SUCCESS; } cairo_int_status_t @@ -748,37 +749,42 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset cairo_string_entry_t key, *entry; char buf[30]; - if (subset->to_unicode == NULL) { + if (subset->to_unicode == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; - } - if (_cairo_truetype_create_glyph_to_unicode_map (subset) != CAIRO_STATUS_SUCCESS) { + status = _cairo_truetype_create_glyph_to_unicode_map (subset); + if (status) { + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + backend = subset->scaled_font->backend; - if (backend->map_glyphs_to_unicode == NULL) { + if (backend->map_glyphs_to_unicode == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; - } - backend->map_glyphs_to_unicode (subset->scaled_font, subset); - } - subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *)); + status = backend->map_glyphs_to_unicode (subset->scaled_font, subset); + if (status) + return status; + } names = _cairo_hash_table_create (_cairo_string_equal); - if (names == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL1; + if (names == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *)); + if (subset->glyph_names == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP_HASH; } subset->glyph_names[0] = strdup (".notdef"); if (subset->glyph_names[0] == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL1; + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP_HASH; } - entry = create_string_entry (subset->glyph_names[0]); - if (entry == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL2; - } + status = create_string_entry (subset->glyph_names[0], &entry); + if (status) + goto CLEANUP_HASH; status = _cairo_hash_table_insert (names, &entry->base); if (status) { @@ -786,7 +792,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset goto CLEANUP_HASH; } - for (i = 0; i < subset->num_glyphs; i++) { + for (i = 1; i < subset->num_glyphs; i++) { if (subset->to_unicode[i] <= 0xffff) { snprintf (buf, sizeof(buf), "uni%04X", (unsigned int)(subset->to_unicode[i])); _cairo_string_init_key (&key, buf); @@ -800,15 +806,13 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset subset->glyph_names[i] = strdup (buf); if (subset->glyph_names[i] == NULL) { - status = CAIRO_STATUS_NO_MEMORY; + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_HASH; } - entry = create_string_entry (subset->glyph_names[i]); - if (entry == NULL) { - status = CAIRO_STATUS_NO_MEMORY; + status = create_string_entry (subset->glyph_names[i], &entry); + if (status) goto CLEANUP_HASH; - } status = _cairo_hash_table_insert (names, &entry->base); if (status) { @@ -816,30 +820,30 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset goto CLEANUP_HASH; } } - return 0; CLEANUP_HASH: while (1) { entry = _cairo_hash_table_random_entry (names, NULL); if (entry == NULL) break; + _cairo_hash_table_remove (names, (cairo_hash_entry_t *) entry); free (entry); } _cairo_hash_table_destroy (names); if (status == CAIRO_STATUS_SUCCESS) - return status; + return CAIRO_STATUS_SUCCESS; -FAIL2: - for (i = 0; i < subset->num_glyphs; i++) { - if (subset->glyph_names[i] != NULL) - free (subset->glyph_names[i]); + if (subset->glyph_names != NULL) { + for (i = 0; i < subset->num_glyphs; i++) { + if (subset->glyph_names[i] != NULL) + free (subset->glyph_names[i]); + } + + free (subset->glyph_names); + subset->glyph_names = NULL; } -FAIL1: - free (subset->glyph_names); - subset->glyph_names = NULL; - return status; } diff --git a/gfx/cairo/cairo/src/cairo-scaled-font.c b/gfx/cairo/cairo/src/cairo-scaled-font.c index 2fd1fff61058..e21cd61c0c0f 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font.c @@ -191,6 +191,7 @@ const cairo_scaled_font_t _cairo_scaled_font_nil = { CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_METRICS_DEFAULT} , { 1., 0., 0., 1., 0, 0}, /* scale */ + { 1., 0., 0., 1., 0, 0}, /* scale_inverse */ { 0., 0., 0., 0., 0. }, /* extents */ CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */ NULL, /* glyphs */ @@ -412,7 +413,7 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, /* ignore translation values in the ctm */ scaled_font->ctm.x0 = 0.; scaled_font->ctm.y0 = 0.; - scaled_font->options = *options; + _cairo_font_options_init_copy (&scaled_font->options, options); /* We do a bytewise hash on the font matrices */ hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx), @@ -463,15 +464,14 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, const cairo_font_options_t *options, const cairo_scaled_font_backend_t *backend) { - cairo_matrix_t inverse; cairo_status_t status; - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) - return status; + if (options != NULL) { + status = cairo_font_options_status ((cairo_font_options_t *) options); + if (status) + return status; + } - /* Initialize scaled_font->scale early for easier bail out on an - * invalid matrix. */ _cairo_scaled_font_init_key (scaled_font, font_face, font_matrix, ctm, options); @@ -479,10 +479,27 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, &scaled_font->font_matrix, &scaled_font->ctm); - inverse = scaled_font->scale; - status = cairo_matrix_invert (&inverse); - if (status) - return status; + scaled_font->scale_inverse = scaled_font->scale; + status = cairo_matrix_invert (&scaled_font->scale_inverse); + if (status) { + /* If the font scale matrix is rank 0, just using an all-zero inverse matrix + * makes everything work correctly. This make font size 0 work without + * producing an error. + * + * FIXME: If the scale is rank 1, we still go into error mode. But then + * again, that's what we doo everywhere in cairo. + * + * Also, the check for == 0. below may bee too harsh... + */ + if (scaled_font->scale.xx == 0. && scaled_font->scale.xy == 0. && + scaled_font->scale.yx == 0. && scaled_font->scale.yy == 0.) + cairo_matrix_init (&scaled_font->scale_inverse, + 0, 0, 0, 0, + -scaled_font->scale.x0, + -scaled_font->scale.y0); + else + return status; + } scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, _cairo_scaled_glyph_destroy, @@ -580,7 +597,8 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) * @ctm: user to device transformation matrix with which the font will * be used. * @options: options to use when getting metrics for the font and - * rendering with it. + * rendering with it. A %NULL pointer will be interpreted as + * meaning the default options. * * Creates a #cairo_scaled_font_t object from a font face and matrices that * describe the size of the font and the environment in which it will @@ -602,11 +620,14 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, if (font_face->status) return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; - if (cairo_font_options_status ((cairo_font_options_t *) options)) + if (options != NULL && + cairo_font_options_status ((cairo_font_options_t *) options)) + { return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; + } - if (! _cairo_matrix_is_invertible (font_matrix)) - return (cairo_scaled_font_t *)&_cairo_scaled_font_nil; + /* Note that degenerate ctm or font_matrix *are* allowed. + * We want to support a font size of 0. */ font_map = _cairo_scaled_font_map_lock (); if (font_map == NULL) @@ -898,15 +919,27 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font, int num_glyphs; if (scaled_font->status) - return; + goto ZERO_EXTENTS; + + if (utf8 == NULL) + goto ZERO_EXTENTS; status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs); - if (status) { - status = _cairo_scaled_font_set_error (scaled_font, status); - return; - } + if (status) + goto ZERO_EXTENTS; + cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents); free (glyphs); + + return; + +ZERO_EXTENTS: + extents->x_bearing = 0.0; + extents->y_bearing = 0.0; + extents->width = 0.0; + extents->height = 0.0; + extents->x_advance = 0.0; + extents->y_advance = 0.0; } /** @@ -942,7 +975,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, if (scaled_font->status) { extents->x_bearing = 0.0; extents->y_bearing = 0.0; - extents->width = 0.0; + extents->width = 0.0; extents->height = 0.0; extents->x_advance = 0.0; extents->y_advance = 0.0; @@ -1095,7 +1128,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, if (ucs4) free (ucs4); - return status; + return _cairo_scaled_font_set_error (scaled_font, status); } /* @@ -1105,12 +1138,12 @@ cairo_status_t _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, - cairo_rectangle_int16_t *extents) + cairo_rectangle_int_t *extents) { cairo_status_t status = CAIRO_STATUS_SUCCESS; int i; - short min_x = INT16_MAX, max_x = INT16_MIN; - short min_y = INT16_MAX, max_y = INT16_MIN; + cairo_point_int_t min = { CAIRO_RECT_INT_MAX, CAIRO_RECT_INT_MAX }; + cairo_point_int_t max = { CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN }; if (scaled_font->status) return scaled_font->status; @@ -1137,16 +1170,16 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, right = x + _cairo_fixed_integer_ceil(scaled_glyph->bbox.p2.x); bottom = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); - if (left < min_x) min_x = left; - if (right > max_x) max_x = right; - if (top < min_y) min_y = top; - if (bottom > max_y) max_y = bottom; + if (left < min.x) min.x = left; + if (right > max.x) max.x = right; + if (top < min.y) min.y = top; + if (bottom > max.y) max.y = bottom; } - if (min_x < max_x && min_y < max_y) { - extents->x = min_x; - extents->width = max_x - min_x; - extents->y = min_y; - extents->height = max_y - min_y; + if (min.x < max.x && min.y < max.y) { + extents->x = min.x; + extents->width = max.x - min.x; + extents->y = min.y; + extents->height = max.y - min.y; } else { extents->x = extents->y = 0; extents->width = extents->height = 0; @@ -1170,7 +1203,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, { cairo_status_t status; cairo_surface_t *mask = NULL; + cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */ cairo_surface_pattern_t mask_pattern; + cairo_solid_pattern_t white_pattern; int i; /* These operators aren't interpreted the same way by the backends; @@ -1200,6 +1235,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, status = CAIRO_STATUS_SUCCESS; + _cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); + _cairo_cache_freeze (scaled_font->glyphs); for (i = 0; i < num_glyphs; i++) { @@ -1218,26 +1255,67 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, glyph_surface = scaled_glyph->surface; - /* Create the mask using the format from the first glyph */ + /* To start, create the mask using the format from the first + * glyph. Later we'll deal with different formats. */ if (mask == NULL) { - mask = cairo_image_surface_create (glyph_surface->format, + mask_format = glyph_surface->format; + mask = cairo_image_surface_create (mask_format, width, height); if (mask->status) { status = mask->status; goto CLEANUP_MASK; } + } - status = _cairo_surface_fill_rectangle (mask, - CAIRO_OPERATOR_CLEAR, - CAIRO_COLOR_TRANSPARENT, - 0, 0, - width, height); - if (status) + /* If we have glyphs of different formats, we "upgrade" the mask + * to the wider of the formats. */ + if (glyph_surface->format != mask_format && + _cairo_format_width (mask_format) < _cairo_format_width (glyph_surface->format) ) + { + cairo_surface_t *new_mask; + cairo_surface_pattern_t mask_pattern; + + switch (glyph_surface->format) { + case CAIRO_FORMAT_ARGB32: + case CAIRO_FORMAT_A8: + case CAIRO_FORMAT_A1: + mask_format = glyph_surface->format; + break; + case CAIRO_FORMAT_RGB24: + default: + ASSERT_NOT_REACHED; + mask_format = CAIRO_FORMAT_ARGB32; + break; + } + + new_mask = cairo_image_surface_create (mask_format, + width, height); + if (new_mask->status) { + status = new_mask->status; + cairo_surface_destroy (new_mask); goto CLEANUP_MASK; - if (glyph_surface->format == CAIRO_FORMAT_ARGB32) - pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)-> - pixman_image, TRUE); + } + _cairo_pattern_init_for_surface (&mask_pattern, mask); + + status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, + &white_pattern.base, + &mask_pattern.base, + new_mask, + 0, 0, + 0, 0, + 0, 0, + width, height); + + _cairo_pattern_fini (&mask_pattern.base); + + if (status) { + cairo_surface_destroy (new_mask); + goto CLEANUP_MASK; + } + + cairo_surface_destroy (mask); + mask = new_mask; } /* round glyph locations to the nearest pixel */ @@ -1248,21 +1326,24 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, + &white_pattern.base, &glyph_pattern.base, - NULL, mask, 0, 0, 0, 0, - x - dest_x, - y - dest_y, + x - dest_x, y - dest_y, glyph_surface->width, glyph_surface->height); _cairo_pattern_fini (&glyph_pattern.base); + if (status) goto CLEANUP_MASK; } + if (mask_format == CAIRO_FORMAT_ARGB32) + pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)-> + pixman_image, TRUE); _cairo_pattern_init_for_surface (&mask_pattern, mask); status = _cairo_surface_composite (op, pattern, &mask_pattern.base, @@ -1277,6 +1358,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, CLEANUP_MASK: _cairo_cache_thaw (scaled_font->glyphs); + _cairo_pattern_fini (&white_pattern.base); + if (mask != NULL) cairo_surface_destroy (mask); return _cairo_scaled_font_set_error (scaled_font, status); diff --git a/gfx/cairo/cairo/src/cairo-surface-fallback.c b/gfx/cairo/cairo/src/cairo-surface-fallback.c index 4abeaf91f4d6..2eb4eae1f186 100644 --- a/gfx/cairo/cairo/src/cairo-surface-fallback.c +++ b/gfx/cairo/cairo/src/cairo-surface-fallback.c @@ -997,8 +997,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, return status; if (_cairo_operator_bounded_by_mask (op)) { - cairo_rectangle_int16_t glyph_extents; - cairo_rectangle_int_t glyph_extents_full; + cairo_rectangle_int_t glyph_extents; status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, @@ -1006,11 +1005,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, if (status) return status; - glyph_extents_full.x = glyph_extents.x; - glyph_extents_full.y = glyph_extents.y; - glyph_extents_full.width = glyph_extents.width; - glyph_extents_full.height = glyph_extents.height; - _cairo_rectangle_intersect (&extents, &glyph_extents_full); + _cairo_rectangle_intersect (&extents, &glyph_extents); } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); @@ -1043,15 +1038,15 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface) status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); - if (status != CAIRO_STATUS_SUCCESS) - return (cairo_surface_t *) &_cairo_surface_nil; + if (status) + return _cairo_surface_create_in_error (status); snapshot = cairo_image_surface_create (image->format, image->width, image->height); if (cairo_surface_status (snapshot)) { _cairo_surface_release_source_image (surface, - image, &image_extra); + image, image_extra); return snapshot; } @@ -1069,11 +1064,11 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface) _cairo_pattern_fini (&pattern.base); _cairo_surface_release_source_image (surface, - image, &image_extra); + image, image_extra); if (status) { cairo_surface_destroy (snapshot); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); } snapshot->device_transform = surface->device_transform; diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index ed332f503539..010195f7e10e 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -78,15 +78,19 @@ const cairo_surface_t name = { \ } /* font_options */ \ } -DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil); -DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found); -DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error); -DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_file_error); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error); +static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error); static cairo_status_t _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, cairo_surface_t *destination, - cairo_pattern_t *pattern_out); + cairo_pattern_t **pattern_out); /** * _cairo_surface_set_error: @@ -228,7 +232,7 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, cairo_format_t format = _cairo_format_from_content (content); if (other->status) - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (other->status); if (other->backend->create_similar) { surface = other->backend->create_similar (other, content, width, height); @@ -289,12 +293,10 @@ cairo_surface_create_similar (cairo_surface_t *other, int height) { if (other->status) - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (other->status); - if (! CAIRO_CONTENT_VALID (content)) { - _cairo_error_throw (CAIRO_STATUS_INVALID_CONTENT); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (! CAIRO_CONTENT_VALID (content)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); return _cairo_surface_create_similar_solid (other, content, width, height, @@ -317,17 +319,14 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other, surface = _cairo_surface_create_similar_scratch (other, content, width, height); - if (surface->status) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (surface->status) + return surface; if (pattern == NULL) { source = _cairo_pattern_create_solid (color, content); if (source->status) { cairo_surface_destroy (surface); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (source->status); } } else source = pattern; @@ -342,8 +341,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other, if (status) { cairo_surface_destroy (surface); - _cairo_error_throw (status); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); } return surface; @@ -931,7 +929,7 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface) * @surface as a source. _cairo_surface_release_source_image() must be called * when finished. * - * Return value: %CAIRO_STATUS_SUCCESS if a an image was stored in @image_out. + * Return value: %CAIRO_STATUS_SUCCESS if an image was stored in @image_out. * %CAIRO_INT_STATUS_UNSUPPORTED if an image cannot be retrieved for the specified * surface. Or %CAIRO_STATUS_NO_MEMORY. **/ @@ -942,6 +940,9 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface, { assert (!surface->finished); + if (surface->backend->acquire_source_image == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + return _cairo_surface_set_error (surface, surface->backend->acquire_source_image (surface, image_out, image_extra)); @@ -1005,6 +1006,9 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface, { assert (!surface->finished); + if (surface->backend->acquire_dest_image == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + return _cairo_surface_set_error (surface, surface->backend->acquire_dest_image (surface, interest_rect, @@ -1135,7 +1139,7 @@ cairo_surface_t * _cairo_surface_snapshot (cairo_surface_t *surface) { if (surface->finished) - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); if (surface->backend->snapshot) return surface->backend->snapshot (surface); @@ -1286,7 +1290,7 @@ _cairo_surface_fill_region (cairo_surface_t *surface, { int num_boxes; cairo_box_int_t *boxes = NULL; - cairo_rectangle_int_t stack_rects[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_rectangle_int_t)]; + cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; cairo_rectangle_int_t *rects = stack_rects; cairo_status_t status; int i; @@ -1389,24 +1393,24 @@ _cairo_surface_paint (cairo_surface_t *surface, cairo_pattern_t *source) { cairo_status_t status; - cairo_pattern_union_t dev_source; + cairo_pattern_t *dev_source; assert (! surface->is_snapshot); - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) return _cairo_surface_set_error (surface, status); if (surface->backend->paint) { - status = surface->backend->paint (surface, op, &dev_source.base); + status = surface->backend->paint (surface, op, dev_source); if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto FINISH; } - status = _cairo_surface_fallback_paint (surface, op, &dev_source.base); + status = _cairo_surface_fallback_paint (surface, op, dev_source); FINISH: - _cairo_pattern_fini (&dev_source.base); + cairo_pattern_destroy (dev_source); return _cairo_surface_set_error (surface, status); } @@ -1418,31 +1422,31 @@ _cairo_surface_mask (cairo_surface_t *surface, cairo_pattern_t *mask) { cairo_status_t status; - cairo_pattern_union_t dev_source; - cairo_pattern_union_t dev_mask; + cairo_pattern_t *dev_source; + cairo_pattern_t *dev_mask; assert (! surface->is_snapshot); - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) goto FINISH; - status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base); + status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask); if (status) goto CLEANUP_SOURCE; if (surface->backend->mask) { - status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base); + status = surface->backend->mask (surface, op, dev_source, dev_mask); if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto CLEANUP_MASK; } - status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base); + status = _cairo_surface_fallback_mask (surface, op, dev_source, dev_mask); CLEANUP_MASK: - _cairo_pattern_fini (&dev_mask.base); + cairo_pattern_destroy (dev_mask); CLEANUP_SOURCE: - _cairo_pattern_fini (&dev_source.base); + cairo_pattern_destroy (dev_source); FINISH: return _cairo_surface_set_error (surface, status); @@ -1467,29 +1471,29 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface, cairo_status_t status; if (surface->backend->fill_stroke) { - cairo_pattern_union_t dev_stroke_source; - cairo_pattern_union_t dev_fill_source; + cairo_pattern_t *dev_stroke_source; + cairo_pattern_t *dev_fill_source; cairo_matrix_t dev_ctm = *stroke_ctm; cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse; - status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source.base); + status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source); if (status) return _cairo_surface_set_error (surface, status); - status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source.base); + status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source); if (status) { - _cairo_pattern_fini (&dev_stroke_source.base); + cairo_pattern_destroy (dev_stroke_source); return _cairo_surface_set_error (surface, status); } - status = surface->backend->fill_stroke (surface, fill_op, &dev_fill_source.base, + status = surface->backend->fill_stroke (surface, fill_op, dev_fill_source, fill_rule, fill_tolerance, fill_antialias, - path, stroke_op, &dev_stroke_source.base, stroke_style, + path, stroke_op, dev_stroke_source, stroke_style, &dev_ctm, &dev_ctm_inverse, stroke_tolerance, stroke_antialias); - _cairo_pattern_fini (&dev_stroke_source.base); - _cairo_pattern_fini (&dev_fill_source.base); + cairo_pattern_destroy (dev_stroke_source); + cairo_pattern_destroy (dev_fill_source); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return _cairo_surface_set_error (surface, status); @@ -1521,7 +1525,7 @@ _cairo_surface_stroke (cairo_surface_t *surface, cairo_antialias_t antialias) { cairo_status_t status; - cairo_pattern_union_t dev_source; + cairo_pattern_t *dev_source; cairo_path_fixed_t *dev_path = path; cairo_path_fixed_t real_dev_path; cairo_matrix_t dev_ctm = *ctm; @@ -1529,12 +1533,12 @@ _cairo_surface_stroke (cairo_surface_t *surface, assert (! surface->is_snapshot); - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) return _cairo_surface_set_error (surface, status); if (surface->backend->stroke) { - status = surface->backend->stroke (surface, op, &dev_source.base, + status = surface->backend->stroke (surface, op, dev_source, path, stroke_style, &dev_ctm, &dev_ctm_inverse, tolerance, antialias); @@ -1543,7 +1547,7 @@ _cairo_surface_stroke (cairo_surface_t *surface, goto FINISH; } - status = _cairo_surface_fallback_stroke (surface, op, &dev_source.base, + status = _cairo_surface_fallback_stroke (surface, op, dev_source, path, stroke_style, &dev_ctm, &dev_ctm_inverse, tolerance, antialias); @@ -1551,7 +1555,7 @@ _cairo_surface_stroke (cairo_surface_t *surface, FINISH: if (dev_path == &real_dev_path) _cairo_path_fixed_fini (&real_dev_path); - _cairo_pattern_fini (&dev_source.base); + cairo_pattern_destroy (dev_source); return _cairo_surface_set_error (surface, status); } @@ -1566,16 +1570,16 @@ _cairo_surface_fill (cairo_surface_t *surface, cairo_antialias_t antialias) { cairo_status_t status; - cairo_pattern_union_t dev_source; + cairo_pattern_t *dev_source; assert (! surface->is_snapshot); - status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base); + status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source); if (status) return _cairo_surface_set_error (surface, status); if (surface->backend->fill) { - status = surface->backend->fill (surface, op, &dev_source.base, + status = surface->backend->fill (surface, op, dev_source, path, fill_rule, tolerance, antialias); @@ -1583,12 +1587,12 @@ _cairo_surface_fill (cairo_surface_t *surface, goto FINISH; } - status = _cairo_surface_fallback_fill (surface, op, &dev_source.base, + status = _cairo_surface_fallback_fill (surface, op, dev_source, path, fill_rule, tolerance, antialias); FINISH: - _cairo_pattern_fini (&dev_source.base); + cairo_pattern_destroy (dev_source); return _cairo_surface_set_error (surface, status); } @@ -2039,7 +2043,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, { cairo_status_t status; cairo_scaled_font_t *dev_scaled_font = scaled_font; - cairo_pattern_union_t dev_source; + cairo_pattern_t *dev_source; cairo_matrix_t font_matrix; assert (! surface->is_snapshot); @@ -2049,7 +2053,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, status = _cairo_surface_copy_pattern_for_destination (source, surface, - &dev_source.base); + &dev_source); if (status) return _cairo_surface_set_error (surface, status); @@ -2074,7 +2078,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, } status = cairo_scaled_font_status (dev_scaled_font); if (status) { - _cairo_pattern_fini (&dev_source.base); + cairo_pattern_destroy (dev_source); return _cairo_surface_set_error (surface, status); } @@ -2083,12 +2087,12 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, status = CAIRO_INT_STATUS_UNSUPPORTED; if (surface->backend->show_glyphs) - status = surface->backend->show_glyphs (surface, op, &dev_source.base, + status = surface->backend->show_glyphs (surface, op, dev_source, glyphs, num_glyphs, dev_scaled_font); if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base, + status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source, glyphs, num_glyphs, dev_scaled_font); @@ -2097,7 +2101,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface, if (dev_scaled_font != scaled_font) cairo_scaled_font_destroy (dev_scaled_font); - _cairo_pattern_fini (&dev_source.base); + cairo_pattern_destroy (dev_source); return _cairo_surface_set_error (surface, status); } @@ -2185,12 +2189,9 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst, has_drawn_region = TRUE; has_clear_region = TRUE; - if (_cairo_region_subtract (&clear_region, &clear_region, &drawn_region) - != CAIRO_STATUS_SUCCESS) - { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_region_subtract (&clear_region, &clear_region, &drawn_region); + if (status) goto CLEANUP_REGIONS; - } status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE, CAIRO_COLOR_TRANSPARENT, @@ -2364,11 +2365,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, static cairo_status_t _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, cairo_surface_t *destination, - cairo_pattern_t *pattern_out) + cairo_pattern_t **pattern_out) { cairo_status_t status; - status = _cairo_pattern_init_copy (pattern_out, pattern); + status = _cairo_pattern_create_copy (pattern_out, pattern); if (status) return status; @@ -2381,7 +2382,7 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern, * matrix should always be invertible. */ assert (status == CAIRO_STATUS_SUCCESS); - _cairo_pattern_transform (pattern_out, &device_to_surface); + _cairo_pattern_transform (*pattern_out, &device_to_surface); } return CAIRO_STATUS_SUCCESS; @@ -2406,5 +2407,31 @@ _cairo_surface_set_resolution (cairo_surface_t *surface, surface->y_resolution = y_res; } +cairo_surface_t * +_cairo_surface_create_in_error (cairo_status_t status) +{ + switch (status) { + case CAIRO_STATUS_NO_MEMORY: + return (cairo_surface_t *) &_cairo_surface_nil; + case CAIRO_STATUS_INVALID_CONTENT: + return (cairo_surface_t *) &_cairo_surface_nil_invalid_content; + case CAIRO_STATUS_INVALID_FORMAT: + return (cairo_surface_t *) &_cairo_surface_nil_invalid_format; + case CAIRO_STATUS_INVALID_VISUAL: + return (cairo_surface_t *) &_cairo_surface_nil_invalid_visual; + case CAIRO_STATUS_READ_ERROR: + return (cairo_surface_t *) &_cairo_surface_nil_read_error; + case CAIRO_STATUS_WRITE_ERROR: + return (cairo_surface_t *) &_cairo_surface_nil_write_error; + case CAIRO_STATUS_FILE_NOT_FOUND: + return (cairo_surface_t *) &_cairo_surface_nil_file_not_found; + case CAIRO_STATUS_TEMP_FILE_ERROR: + return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error; + default: + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return (cairo_surface_t *) &_cairo_surface_nil; + } +} + /* LocalWords: rasterized */ diff --git a/gfx/cairo/cairo/src/cairo-svg-surface.c b/gfx/cairo/cairo/src/cairo-svg-surface.c index a3d2b7e95f46..2c3cb5893f1a 100644 --- a/gfx/cairo/cairo/src/cairo-svg-surface.c +++ b/gfx/cairo/cairo/src/cairo-svg-surface.c @@ -118,11 +118,12 @@ typedef struct { cairo_meta_surface_t *meta; } cairo_meta_snapshot_t; -static cairo_svg_document_t * -_cairo_svg_document_create (cairo_output_stream_t *stream, - double width, - double height, - cairo_svg_version_t version); +static cairo_status_t +_cairo_svg_document_create (cairo_output_stream_t *stream, + double width, + double height, + cairo_svg_version_t version, + cairo_svg_document_t **document_out); static cairo_status_t _cairo_svg_document_destroy (cairo_svg_document_t *document); @@ -173,13 +174,11 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write_func, double width, double height) { - cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create (write_func, NULL, closure); - status = _cairo_output_stream_get_status (stream); - if (status) - return (cairo_surface_t *) &_cairo_surface_nil; + if (_cairo_output_stream_get_status (stream)) + return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1); } @@ -208,15 +207,11 @@ cairo_svg_surface_create (const char *filename, double width, double height) { - cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create_for_filename (filename); - status = _cairo_output_stream_get_status (stream); - if (status) - return (status == CAIRO_STATUS_WRITE_ERROR) ? - (cairo_surface_t *) &_cairo_surface_nil_write_error : - (cairo_surface_t *) &_cairo_surface_nil; + if (_cairo_output_stream_get_status (stream)) + return _cairo_surface_create_in_error (_cairo_output_stream_destroy (stream)); return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1); } @@ -332,13 +327,11 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, { cairo_svg_surface_t *surface; cairo_surface_t *paginated; - cairo_status_t status; + cairo_status_t status, status_ignored; surface = malloc (sizeof (cairo_svg_surface_t)); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_svg_surface_backend, content); @@ -355,8 +348,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, surface->is_base_clip_emitted = FALSE; surface->xml_node = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (surface->xml_node)) - goto CLEANUP_DOCUMENT; + status = _cairo_output_stream_get_status (surface->xml_node); + if (status) + goto CLEANUP; _cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t)); @@ -366,8 +360,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, "style=\"opacity: 1; stroke: none; " "fill: rgb(0,0,0);\"/>\n", width, height); - if (_cairo_output_stream_get_status (surface->xml_node)) - goto CLEANUP_STREAM; + status = _cairo_output_stream_get_status (surface->xml_node); + if (status) + goto CLEANUP; } surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; @@ -379,18 +374,18 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, surface->width, surface->height, &cairo_svg_surface_paginated_backend); - if (! paginated->status) + status = paginated->status; + if (status == CAIRO_STATUS_SUCCESS) return paginated; /* ignore status as we are on the error path */ -CLEANUP_STREAM: - status = _cairo_output_stream_destroy (surface->xml_node); -CLEANUP_DOCUMENT: - status = _cairo_svg_document_destroy (document); +CLEANUP: + status_ignored = _cairo_output_stream_destroy (surface->xml_node); + status_ignored = _cairo_svg_document_destroy (document); free (surface); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + + return _cairo_surface_create_in_error (status); } static cairo_surface_t * @@ -399,23 +394,25 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, double height, cairo_svg_version_t version) { - cairo_svg_document_t *document; + cairo_svg_document_t *document = NULL; /* silence compiler */ cairo_surface_t *surface; cairo_status_t status; - document = _cairo_svg_document_create (stream, width, height, version); - if (document == NULL) { + status = _cairo_svg_document_create (stream, + width, height, version, + &document); + if (status) { + surface = _cairo_surface_create_in_error (status); /* consume the output stream on behalf of caller */ status = _cairo_output_stream_destroy (stream); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return surface; } surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA, width, height); if (surface->status) { status = _cairo_svg_document_destroy (document); - return (cairo_surface_t *) &_cairo_surface_nil; + return surface; } document->owner = surface; @@ -432,20 +429,21 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface) unsigned int i; cairo_svg_page_t page; cairo_output_stream_t *stream; + cairo_status_t status; stream = _cairo_memory_stream_create (); - if (stream->status) + if (_cairo_output_stream_get_status (stream)) { + status = _cairo_output_stream_destroy (stream); return NULL; + } page.surface_id = surface->id; page.clip_level = surface->clip_level; page.xml_node = surface->xml_node; - if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS) - { - cairo_status_t status = _cairo_output_stream_destroy (stream); + if (_cairo_array_append (&surface->page_set, &page)) { + status = _cairo_output_stream_destroy (stream); return NULL; - (void) status; } surface->xml_node = stream; @@ -1032,7 +1030,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document, meta->height_pixels); if (paginated_surface->status) { cairo_surface_destroy (&meta->base); - return CAIRO_STATUS_NO_MEMORY; + return paginated_surface->status; } svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface); @@ -1096,7 +1094,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document, if (_cairo_memory_stream_length (contents) > 0) { if (_cairo_svg_surface_store_page (svg_surface) == NULL) { cairo_surface_destroy (paginated_surface); - return CAIRO_STATUS_NO_MEMORY; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } } @@ -1538,6 +1536,8 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, assert (status == CAIRO_STATUS_SUCCESS); if (pattern->r1 == pattern->r2) { + unsigned int n_stops = pattern->base.n_stops; + _cairo_output_stream_printf (document->xml_node_defs, "xml_node_defs, "gradientTransform", &p2u); _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - if (extend == CAIRO_EXTEND_NONE || - pattern->base.n_stops < 1) + if (extend == CAIRO_EXTEND_NONE || n_stops < 1) _cairo_output_stream_printf (document->xml_node_defs, "base.stops[0].color.green * 100.0, pattern->base.stops[0].color.blue * 100.0, pattern->base.stops[0].color.alpha); - if (pattern->base.n_stops > 1) + if (n_stops > 1) _cairo_output_stream_printf (document->xml_node_defs, "\n", - pattern->base.stops[1].color.red * 100.0, - pattern->base.stops[1].color.green * 100.0, - pattern->base.stops[1].color.blue * 100.0, - pattern->base.stops[1].color.alpha); + pattern->base.stops[n_stops - 1].color.red * 100.0, + pattern->base.stops[n_stops - 1].color.green * 100.0, + pattern->base.stops[n_stops - 1].color.blue * 100.0, + pattern->base.stops[n_stops - 1].color.alpha); } } else { @@ -1959,8 +1958,8 @@ _cairo_svg_surface_paint (void *abstract_surface, } surface->xml_node = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (surface->xml_node); - if (status) { + if (_cairo_output_stream_get_status (surface->xml_node)) { + status = _cairo_output_stream_destroy (surface->xml_node); surface->xml_node = NULL; return status; } @@ -2005,9 +2004,8 @@ _cairo_svg_surface_mask (void *abstract_surface, * document->xml_node_defs so we need to write the mask element to * a temporary stream and then copy that to xml_node_defs. */ mask_stream = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (mask_stream); - if (status) - return status; + if (_cairo_output_stream_get_status (mask_stream)) + return _cairo_output_stream_destroy (mask_stream); _cairo_output_stream_printf (mask_stream, "\n" @@ -2245,28 +2243,29 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = { _cairo_svg_surface_fill_stroke }; -static cairo_svg_document_t * -_cairo_svg_document_create (cairo_output_stream_t *output_stream, - double width, - double height, - cairo_svg_version_t version) +static cairo_status_t +_cairo_svg_document_create (cairo_output_stream_t *output_stream, + double width, + double height, + cairo_svg_version_t version, + cairo_svg_document_t **document_out) { cairo_svg_document_t *document; - cairo_status_t status; + cairo_status_t status, status_ignored; if (output_stream->status) - return NULL; + return output_stream->status; document = malloc (sizeof (cairo_svg_document_t)); - if (document == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } + if (document == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); /* The use of defs for font glyphs imposes no per-subset limit. */ document->font_subsets = _cairo_scaled_font_subsets_create_scaled (); - if (document->font_subsets == NULL) + if (document->font_subsets == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_DOCUMENT; + } document->output_stream = output_stream; document->refcount = 1; @@ -2284,12 +2283,14 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, document->mask_id = 0; document->xml_node_defs = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (document->xml_node_defs)) - goto CLEANUP_FONT_SUBSETS; + status = _cairo_output_stream_get_status (document->xml_node_defs); + if (status) + goto CLEANUP_NODE_DEFS; document->xml_node_glyphs = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (document->xml_node_glyphs)) - goto CLEANUP_NODE_DEFS; + status = _cairo_output_stream_get_status (document->xml_node_glyphs); + if (status) + goto CLEANUP_NODE_GLYPHS; document->alpha_filter = FALSE; @@ -2298,15 +2299,17 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, document->svg_version = version; - return document; + *document_out = document; + return CAIRO_STATUS_SUCCESS; + CLEANUP_NODE_GLYPHS: + status_ignored = _cairo_output_stream_destroy (document->xml_node_glyphs); CLEANUP_NODE_DEFS: - status = _cairo_output_stream_destroy (document->xml_node_defs); - CLEANUP_FONT_SUBSETS: + status_ignored = _cairo_output_stream_destroy (document->xml_node_defs); _cairo_scaled_font_subsets_destroy (document->font_subsets); CLEANUP_DOCUMENT: free (document); - return NULL; + return status; } static cairo_svg_document_t * @@ -2377,7 +2380,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) _cairo_memory_stream_length (surface->xml_node) > 0) { if (_cairo_svg_surface_store_page (surface) == NULL) { if (status == CAIRO_STATUS_SUCCESS) - status = CAIRO_STATUS_NO_MEMORY; + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); } } diff --git a/gfx/cairo/cairo/src/cairo-traps.c b/gfx/cairo/cairo/src/cairo-traps.c index 099b09ef6184..c3d4329f9e63 100644 --- a/gfx/cairo/cairo/src/cairo-traps.c +++ b/gfx/cairo/cairo/src/cairo-traps.c @@ -568,11 +568,13 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y) void _cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents) { - *extents = traps->extents; + if (traps->num_traps == 0) { + extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0); + extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0); + } else + *extents = traps->extents; } -#define STACK_BOXES_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(cairo_box_int_t))) - /** * _cairo_traps_extract_region: * @traps: a #cairo_traps_t @@ -591,7 +593,7 @@ cairo_int_status_t _cairo_traps_extract_region (cairo_traps_t *traps, cairo_region_t *region) { - cairo_box_int_t stack_boxes[STACK_BOXES_LEN]; + cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)]; cairo_box_int_t *boxes = stack_boxes; int i, box_count; cairo_int_status_t status; diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset.c b/gfx/cairo/cairo/src/cairo-truetype-subset.c index 5e392d42fdd0..557ab1d677eb 100644 --- a/gfx/cairo/cairo/src/cairo-truetype-subset.c +++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c @@ -323,7 +323,7 @@ cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font, return CAIRO_STATUS_SUCCESS; } -static cairo_status_t +static void cairo_truetype_font_write (cairo_truetype_font_t *font, const void *data, size_t length) @@ -331,13 +331,11 @@ cairo_truetype_font_write (cairo_truetype_font_t *font, cairo_status_t status; if (font->status) - return font->status; + return; status = _cairo_array_append_multiple (&font->output, data, length); if (status) - return _cairo_truetype_font_set_error (font, status); - - return CAIRO_STATUS_SUCCESS; + status = _cairo_truetype_font_set_error (font, status); } static void @@ -366,22 +364,29 @@ cairo_truetype_font_write_be32 (cairo_truetype_font_t *font, cairo_truetype_font_write (font, &be32_value, sizeof be32_value); } -static unsigned long -cairo_truetype_font_align_output (cairo_truetype_font_t *font) +static cairo_status_t +cairo_truetype_font_align_output (cairo_truetype_font_t *font, + unsigned long *aligned) { - int length, aligned, pad; + int length, pad; unsigned char *padding; length = _cairo_array_num_elements (&font->output); - aligned = (length + 3) & ~3; - pad = aligned - length; + *aligned = (length + 3) & ~3; + pad = *aligned - length; if (pad) { - cairo_truetype_font_allocate_write_buffer (font, pad, &padding); + cairo_status_t status; + + status = cairo_truetype_font_allocate_write_buffer (font, pad, + &padding); + if (status) + return status; + memset (padding, 0, pad); } - return aligned; + return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -575,8 +580,9 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, } size = end - begin; - - next = cairo_truetype_font_align_output (font); + status = cairo_truetype_font_align_output (font, &next); + if (status) + goto FAIL; status = cairo_truetype_font_check_boundary (font, next); if (status) @@ -598,8 +604,11 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, } } - font->glyphs[i].location = - cairo_truetype_font_align_output (font) - start_offset; + status = cairo_truetype_font_align_output (font, &next); + if (status) + goto FAIL; + + font->glyphs[i].location = next - start_offset; status = font->status; FAIL: @@ -881,8 +890,9 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font, if (status) goto FAIL; - start = cairo_truetype_font_align_output (font); - end = start; + status = cairo_truetype_font_align_output (font, &start); + if (status) + goto FAIL; end = 0; for (i = 0; i < font->num_tables; i++) { @@ -891,7 +901,10 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font, goto FAIL; end = _cairo_array_num_elements (&font->output); - next = cairo_truetype_font_align_output (font); + status = cairo_truetype_font_align_output (font, &next); + if (status) + goto FAIL; + cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos, font->truetype_tables[i].tag, start, end); status = cairo_truetype_font_check_boundary (font, next); diff --git a/gfx/cairo/cairo/src/cairo-type1-fallback.c b/gfx/cairo/cairo/src/cairo-type1-fallback.c index 626c7b5d3678..0ca49986938b 100644 --- a/gfx/cairo/cairo/src/cairo-type1-fallback.c +++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c @@ -110,6 +110,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset, goto fail; _cairo_array_init (&font->contents, sizeof (unsigned char)); + font->output = NULL; *subset_return = font; @@ -600,10 +601,8 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font, cairo_type1_write_stream_encrypted, NULL, font); - if (encrypted_output == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail; - } + if (_cairo_output_stream_get_status (encrypted_output)) + return _cairo_output_stream_destroy (encrypted_output); /* Note: the first four spaces at the start of this private dict * are the four "random" bytes of plaintext required by the @@ -696,6 +695,8 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name) return status; font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font); + if (_cairo_output_stream_get_status (font->output)) + return _cairo_output_stream_destroy (font->output); status = cairo_type1_font_write (font, name); if (status) @@ -709,12 +710,13 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name) static cairo_status_t cairo_type1_font_destroy (cairo_type1_font_t *font) { - cairo_status_t status; + cairo_status_t status = CAIRO_STATUS_SUCCESS; free (font->widths); cairo_scaled_font_destroy (font->type1_scaled_font); _cairo_array_fini (&font->contents); - status = _cairo_output_stream_destroy (font->output); + if (font->output) + status = _cairo_output_stream_destroy (font->output); free (font); return status; diff --git a/gfx/cairo/cairo/src/cairo-type1-subset.c b/gfx/cairo/cairo/src/cairo-type1-subset.c index 031b19fc4340..8b96aa706539 100644 --- a/gfx/cairo/cairo/src/cairo-type1-subset.c +++ b/gfx/cairo/cairo/src/cairo-type1-subset.c @@ -147,18 +147,20 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, font->base.y_max = face->bbox.yMax; font->base.ascent = face->ascender; font->base.descent = face->descender; - font->base.base_font = strdup (face->family_name); - if (font->base.base_font == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail2; - } - for (i = 0, j = 0; font->base.base_font[j]; j++) { - if (font->base.base_font[j] == ' ') - continue; - font->base.base_font[i++] = font->base.base_font[j]; + if (face->family_name) { + font->base.base_font = strdup (face->family_name); + if (font->base.base_font == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail2; + } + for (i = 0, j = 0; font->base.base_font[j]; j++) { + if (font->base.base_font[j] == ' ') + continue; + font->base.base_font[i++] = font->base.base_font[j]; + } + font->base.base_font[i] = '\0'; } - font->base.base_font[i] = '\0'; font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]); if (font->glyphs == NULL) { @@ -180,7 +182,8 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, return CAIRO_STATUS_SUCCESS; fail3: - free (font->base.base_font); + if (font->base.base_font) + free (font->base.base_font); fail2: _cairo_unscaled_font_destroy (unscaled_font); free (font); @@ -190,16 +193,13 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font, return status; } -static int +static void cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph) { if (font->glyphs[glyph].subset_index >= 0) - return font->glyphs[glyph].subset_index; + return; - font->glyphs[glyph].subset_index = font->num_glyphs; - font->num_glyphs++; - - return font->glyphs[glyph].subset_index; + font->glyphs[glyph].subset_index = font->num_glyphs++; } static cairo_bool_t @@ -1028,6 +1028,9 @@ cairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font) _cairo_output_stream_write (font->output, cleartomark_token, font->type1_end - cleartomark_token); + /* some fonts do not have a newline at the end of the last line */ + _cairo_output_stream_printf (font->output, "\n"); + return CAIRO_STATUS_SUCCESS; } @@ -1126,9 +1129,10 @@ cairo_type1_font_subset_generate (void *abstract_font, goto fail; font->output = _cairo_output_stream_create (type1_font_write, NULL, font); - status = _cairo_output_stream_get_status (font->output); - if (status) + if (_cairo_output_stream_get_status (font->output)) { + status = _cairo_output_stream_destroy (font->output); goto fail; + } status = cairo_type1_font_subset_write (font, name); if (status) @@ -1161,7 +1165,8 @@ cairo_type1_font_subset_destroy (void *abstract_font) _cairo_unscaled_font_destroy (font->base.unscaled_font); - free (font->base.base_font); + if (font->base.base_font) + free (font->base.base_font); free (font->glyphs); free (font); } @@ -1178,6 +1183,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, unsigned long parent_glyph, length; unsigned int i; cairo_unscaled_font_t *unscaled_font; + char buf[30]; /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */ if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font)) @@ -1201,7 +1207,13 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, if (status) goto fail1; - type1_subset->base_font = strdup (font->base.base_font); + if (font->base.base_font) { + type1_subset->base_font = strdup (font->base.base_font); + } else { + snprintf(buf, sizeof (buf), "CairoFont-%u-%u", + scaled_font_subset->font_id, scaled_font_subset->subset_id); + type1_subset->base_font = strdup (buf); + } if (type1_subset->base_font == NULL) goto fail1; diff --git a/gfx/cairo/cairo/src/cairo-types-private.h b/gfx/cairo/cairo/src/cairo-types-private.h index a7af7126e663..ac7d837223e0 100644 --- a/gfx/cairo/cairo/src/cairo-types-private.h +++ b/gfx/cairo/cairo/src/cairo-types-private.h @@ -41,6 +41,7 @@ /* This is the only header file not including cairoint.h. It only contains * typedefs.*/ #include "cairo.h" +#include "cairo-fixed-type-private.h" typedef struct _cairo_array cairo_array_t; typedef struct _cairo_hash_table cairo_hash_table_t; @@ -123,7 +124,8 @@ struct _cairo_cache { typedef enum _cairo_paginated_mode { CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */ - CAIRO_PAGINATED_MODE_RENDER /* render page contents */ + CAIRO_PAGINATED_MODE_RENDER, /* render page contents */ + CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */ } cairo_paginated_mode_t; /* Sure wish C had a real enum type so that this would be distinct @@ -148,4 +150,172 @@ typedef enum _cairo_internal_surface_type { CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED } cairo_internal_surface_type_t; +typedef struct _cairo_region cairo_region_t; + +typedef struct _cairo_point { + cairo_fixed_t x; + cairo_fixed_t y; +} cairo_point_t; + +typedef struct _cairo_slope +{ + cairo_fixed_t dx; + cairo_fixed_t dy; +} cairo_slope_t, cairo_distance_t; + +typedef struct _cairo_point_double { + double x; + double y; +} cairo_point_double_t; + +typedef struct _cairo_distance_double { + double dx; + double dy; +} cairo_distance_double_t; + +typedef struct _cairo_line { + cairo_point_t p1; + cairo_point_t p2; +} cairo_line_t, cairo_box_t; + +typedef struct _cairo_trapezoid { + cairo_fixed_t top, bottom; + cairo_line_t left, right; +} cairo_trapezoid_t; + +typedef struct _cairo_rectangle_int16 { + int16_t x, y; + uint16_t width, height; +} cairo_rectangle_int16_t, cairo_glyph_size_t; + +typedef struct _cairo_rectangle_int32 { + int32_t x, y; + uint32_t width, height; +} cairo_rectangle_int32_t; + +typedef struct _cairo_point_int16 { + int16_t x, y; +} cairo_point_int16_t; + +typedef struct _cairo_point_int32 { + int32_t x, y; +} cairo_point_int32_t; + +typedef struct _cairo_box_int16 { + cairo_point_int16_t p1; + cairo_point_int16_t p2; +} cairo_box_int16_t; + +typedef struct _cairo_box_int32 { + cairo_point_int32_t p1; + cairo_point_int32_t p2; +} cairo_box_int32_t; + + +#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16 +typedef cairo_rectangle_int16_t cairo_rectangle_int_t; +typedef cairo_point_int16_t cairo_point_int_t; +typedef cairo_box_int16_t cairo_box_int_t; +#define CAIRO_RECT_INT_MIN INT16_MIN +#define CAIRO_RECT_INT_MAX INT16_MAX +#elif CAIRO_FIXED_BITS == 32 +typedef cairo_rectangle_int32_t cairo_rectangle_int_t; +typedef cairo_point_int32_t cairo_point_int_t; +typedef cairo_box_int32_t cairo_box_int_t; +#define CAIRO_RECT_INT_MIN INT32_MIN +#define CAIRO_RECT_INT_MAX INT32_MAX +#else +#error Not sure how to pick a cairo_rectangle_int_t for your CAIRO_FIXED_BITS! +#endif + +typedef enum _cairo_direction { + CAIRO_DIRECTION_FORWARD, + CAIRO_DIRECTION_REVERSE +} cairo_direction_t; + +typedef struct _cairo_path_fixed cairo_path_fixed_t; +typedef enum _cairo_clip_mode { + CAIRO_CLIP_MODE_PATH, + CAIRO_CLIP_MODE_REGION, + CAIRO_CLIP_MODE_MASK +} cairo_clip_mode_t; +typedef struct _cairo_clip_path cairo_clip_path_t; + +typedef struct _cairo_edge { + cairo_line_t edge; + int clockWise; + + cairo_fixed_t current_x; +} cairo_edge_t; + +typedef struct _cairo_polygon { + cairo_status_t status; + + cairo_point_t first_point; + cairo_point_t current_point; + cairo_bool_t has_current_point; + + int num_edges; + int edges_size; + cairo_edge_t *edges; + cairo_edge_t edges_embedded[8]; +} cairo_polygon_t; + +typedef struct _cairo_spline_knots { + cairo_point_t a, b, c, d; +} cairo_spline_knots_t; +typedef struct _cairo_spline { + cairo_spline_knots_t knots; + + cairo_slope_t initial_slope; + cairo_slope_t final_slope; + + int num_points; + int points_size; + cairo_point_t *points; + cairo_point_t points_embedded[8]; +} cairo_spline_t; + +typedef struct _cairo_pen_vertex { + cairo_point_t point; + + cairo_slope_t slope_ccw; + cairo_slope_t slope_cw; +} cairo_pen_vertex_t; + +typedef struct _cairo_pen { + double radius; + double tolerance; + + cairo_pen_vertex_t *vertices; + int num_vertices; +} cairo_pen_t; + +typedef struct _cairo_color cairo_color_t; +typedef struct _cairo_image_surface cairo_image_surface_t; + +typedef struct _cairo_stroke_style { + double line_width; + cairo_line_cap_t line_cap; + cairo_line_join_t line_join; + double miter_limit; + double *dash; + unsigned int num_dashes; + double dash_offset; +} cairo_stroke_style_t; + +typedef struct _cairo_format_masks { + int bpp; + unsigned long alpha_mask; + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; +} cairo_format_masks_t; + +typedef enum { + CAIRO_STOCK_WHITE, + CAIRO_STOCK_BLACK, + CAIRO_STOCK_TRANSPARENT +} cairo_stock_t; + #endif /* CAIRO_TYPES_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-unicode.c b/gfx/cairo/cairo/src/cairo-unicode.c index 2b224a3ab88c..18b9143d9a53 100644 --- a/gfx/cairo/cairo/src/cairo-unicode.c +++ b/gfx/cairo/cairo/src/cairo-unicode.c @@ -258,6 +258,7 @@ _cairo_utf8_to_ucs4 (const unsigned char *str, return CAIRO_STATUS_SUCCESS; } +#if CAIRO_HAS_UTF8_TO_UTF16 /** * _cairo_utf8_to_utf16: * @str: an UTF-8 string @@ -333,3 +334,4 @@ _cairo_utf8_to_utf16 (const unsigned char *str, return CAIRO_STATUS_SUCCESS; } +#endif diff --git a/gfx/cairo/cairo/src/cairo-wideint-private.h b/gfx/cairo/cairo/src/cairo-wideint-private.h index 69fa1561e236..412fc00365f9 100644 --- a/gfx/cairo/cairo/src/cairo-wideint-private.h +++ b/gfx/cairo/cairo/src/cairo-wideint-private.h @@ -37,42 +37,7 @@ #ifndef CAIRO_WIDEINT_H #define CAIRO_WIDEINT_H -#if HAVE_STDINT_H -# include -#elif HAVE_INTTYPES_H -# include -#elif HAVE_SYS_INT_TYPES_H -# include -#elif defined(_MSC_VER) - typedef __int8 int8_t; - typedef unsigned __int8 uint8_t; - typedef __int16 int16_t; - typedef unsigned __int16 uint16_t; - typedef __int32 int32_t; - typedef unsigned __int32 uint32_t; - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# ifndef HAVE_UINT64_T -# define HAVE_UINT64_T 1 -# endif -# ifndef INT16_MIN -# define INT16_MIN (-32767-1) -# endif -# ifndef INT16_MAX -# define INT16_MAX (32767) -# endif -# ifndef UINT16_MAX -# define UINT16_MAX (65535) -# endif -# ifndef INT32_MIN -# define INT32_MIN (-2147483647-1) -# endif -# ifndef INT32_MAX -# define INT32_MAX (2147483647) -# endif -#else -#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.) -#endif +#include "cairo-wideint-type-private.h" #include "cairo-compiler-private.h" @@ -86,10 +51,6 @@ #if !HAVE_UINT64_T -typedef struct _cairo_uint64 { - uint32_t lo, hi; -} cairo_uint64_t, cairo_int64_t; - cairo_uint64_t I _cairo_uint32_to_uint64 (uint32_t i); #define _cairo_uint64_to_uint32(a) ((a).lo) cairo_uint64_t I _cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b); @@ -125,9 +86,6 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b); #else -typedef uint64_t cairo_uint64_t; -typedef int64_t cairo_int64_t; - #define _cairo_uint32_to_uint64(i) ((uint64_t) (i)) #define _cairo_uint64_to_uint32(i) ((uint32_t) (i)) #define _cairo_uint64_add(a,b) ((a) + (b)) @@ -181,16 +139,6 @@ typedef int64_t cairo_int64_t; * a function which returns both for the 'native' type as well */ -typedef struct _cairo_uquorem64 { - cairo_uint64_t quo; - cairo_uint64_t rem; -} cairo_uquorem64_t; - -typedef struct _cairo_quorem64 { - cairo_int64_t quo; - cairo_int64_t rem; -} cairo_quorem64_t; - cairo_uquorem64_t I _cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den); @@ -205,10 +153,6 @@ _cairo_int64_divrem (cairo_int64_t num, cairo_int64_t den); #if !HAVE_UINT128_T -typedef struct cairo_uint128 { - cairo_uint64_t lo, hi; -} cairo_uint128_t, cairo_int128_t; - cairo_uint128_t I _cairo_uint32_to_uint128 (uint32_t i); cairo_uint128_t I _cairo_uint64_to_uint128 (cairo_uint64_t i); #define _cairo_uint128_to_uint64(a) ((a).lo) @@ -248,9 +192,6 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b); #else /* !HAVE_UINT128_T */ -typedef uint128_t cairo_uint128_t; -typedef int128_t cairo_int128_t; - #define _cairo_uint32_to_uint128(i) ((uint128_t) (i)) #define _cairo_uint64_to_uint128(i) ((uint128_t) (i)) #define _cairo_uint128_to_uint64(i) ((uint64_t) (i)) @@ -290,16 +231,6 @@ typedef int128_t cairo_int128_t; #endif /* HAVE_UINT128_T */ -typedef struct _cairo_uquorem128 { - cairo_uint128_t quo; - cairo_uint128_t rem; -} cairo_uquorem128_t; - -typedef struct _cairo_quorem128 { - cairo_int128_t quo; - cairo_int128_t rem; -} cairo_quorem128_t; - cairo_uquorem128_t I _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den); diff --git a/gfx/cairo/cairo/src/cairo-wideint-type-private.h b/gfx/cairo/cairo/src/cairo-wideint-type-private.h new file mode 100644 index 000000000000..23e50dfadd65 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-wideint-type-private.h @@ -0,0 +1,130 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2004 Keith Packard + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.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/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Keith Packard + * + * Contributor(s): + * Keith R. Packard + * + */ + +#ifndef CAIRO_WIDEINT_TYPE_H +#define CAIRO_WIDEINT_TYPE_H + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_STDINT_H +# include +#elif HAVE_INTTYPES_H +# include +#elif HAVE_SYS_INT_TYPES_H +# include +#elif defined(_MSC_VER) + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +# ifndef HAVE_UINT64_T +# define HAVE_UINT64_T 1 +# endif +# ifndef INT16_MIN +# define INT16_MIN (-32767-1) +# endif +# ifndef INT16_MAX +# define INT16_MAX (32767) +# endif +# ifndef UINT16_MAX +# define UINT16_MAX (65535) +# endif +# ifndef INT32_MIN +# define INT32_MIN (-2147483647-1) +# endif +# ifndef INT32_MAX +# define INT32_MAX (2147483647) +# endif +#else +#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.) +#endif + + +#if !HAVE_UINT64_T + +typedef struct _cairo_uint64 { + uint32_t lo, hi; +} cairo_uint64_t, cairo_int64_t; + +#else + +typedef uint64_t cairo_uint64_t; +typedef int64_t cairo_int64_t; + +#endif + +typedef struct _cairo_uquorem64 { + cairo_uint64_t quo; + cairo_uint64_t rem; +} cairo_uquorem64_t; + +typedef struct _cairo_quorem64 { + cairo_int64_t quo; + cairo_int64_t rem; +} cairo_quorem64_t; + + +#if !HAVE_UINT128_T + +typedef struct cairo_uint128 { + cairo_uint64_t lo, hi; +} cairo_uint128_t, cairo_int128_t; + +#else + +typedef uint128_t cairo_uint128_t; +typedef int128_t cairo_int128_t; + +#endif + +typedef struct _cairo_uquorem128 { + cairo_uint128_t quo; + cairo_uint128_t rem; +} cairo_uquorem128_t; + +typedef struct _cairo_quorem128 { + cairo_int128_t quo; + cairo_int128_t rem; +} cairo_quorem128_t; + + +#endif /* CAIRO_WIDEINT_H */ diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c index 358d61cd2c21..f7ae1f0a7d0f 100644 --- a/gfx/cairo/cairo/src/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/cairo-win32-font.c @@ -33,6 +33,15 @@ * Contributor(s): */ +#define WIN32_LEAN_AND_MEAN +/* We require Windows 2000 features such as GetGlyphIndices */ +#if !defined(WINVER) || (WINVER < 0x0500) +# define WINVER 0x0500 +#endif +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) +# define _WIN32_WINNT 0x0500 +#endif + #include "cairoint.h" #include "cairo-win32-private.h" @@ -50,7 +59,7 @@ #define TT_PRIM_CSPLINE 3 #endif -#define OPENTYPE_CFF_TAG 0x20464643 +#define CMAP_TAG 0x70616d63 const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend; @@ -99,9 +108,8 @@ typedef struct { HFONT scaled_hfont; HFONT unscaled_hfont; - cairo_bool_t is_truetype; - cairo_bool_t glyph_indexing; - + cairo_bool_t is_bitmap; + cairo_bool_t is_type1; cairo_bool_t delete_scaled_hfont; } cairo_win32_scaled_font_t; @@ -112,6 +120,10 @@ static cairo_status_t _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); +static cairo_status_t +_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph); + static cairo_status_t _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); @@ -261,7 +273,7 @@ _win32_scaled_font_create (LOGFONTW *logfont, * XXX: The other option we could pay attention to, but don't * here is the hint_metrics options. */ - if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) + if (options == NULL || options->antialias == CAIRO_ANTIALIAS_DEFAULT) f->quality = _get_system_quality (); else { switch (options->antialias) { @@ -288,7 +300,7 @@ _win32_scaled_font_create (LOGFONTW *logfont, if (f->quality == logfont->lfQuality || (logfont->lfQuality == DEFAULT_QUALITY && - options->antialias == CAIRO_ANTIALIAS_DEFAULT)) { + (options == NULL || options->antialias == CAIRO_ANTIALIAS_DEFAULT))) { /* If face_hfont is non-NULL, then we can use it to avoid creating our * own --- because the constraints on face_hfont mentioned above * guarantee it was created in exactly the same way that @@ -565,6 +577,92 @@ _cairo_win32_scaled_font_fini (void *abstract_font) DeleteObject (scaled_font->unscaled_hfont); } +static cairo_int_status_t +_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font, + double x, + double y, + const char *utf8, + cairo_glyph_t **glyphs, + int *num_glyphs) +{ + uint16_t *utf16; + int n16; + int i; + WORD *glyph_indices = NULL; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + double x_pos, y_pos; + HDC hdc = NULL; + cairo_matrix_t mat; + + status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); + if (status) + return status; + + glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD)); + if (!glyph_indices) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto FAIL1; + } + + hdc = _get_global_font_dc (); + if (!hdc) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto FAIL2; + } + + status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + if (status) + goto FAIL2; + + if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW"); + goto FAIL2; + } + + *num_glyphs = n16; + *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t)); + if (!*glyphs) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto FAIL2; + } + + x_pos = x; + y_pos = y; + mat = scaled_font->base.ctm; + cairo_matrix_invert (&mat); + for (i = 0; i < n16; i++) { + cairo_scaled_glyph_t *scaled_glyph; + + (*glyphs)[i].index = glyph_indices[i]; + (*glyphs)[i].x = x_pos; + (*glyphs)[i].y = y_pos; + + status = _cairo_scaled_glyph_lookup (&scaled_font->base, + glyph_indices[i], + CAIRO_SCALED_GLYPH_INFO_METRICS, + &scaled_glyph); + if (status) { + free (*glyphs); + goto FAIL2; + } + + x = scaled_glyph->x_advance; + y = scaled_glyph->y_advance; + cairo_matrix_transform_distance (&mat, &x, &y); + x_pos += x; + y_pos += y; + } + + cairo_win32_scaled_font_done_font (&scaled_font->base); + +FAIL2: + free (glyph_indices); +FAIL1: + free (utf16); + + return status; +} + static cairo_int_status_t _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, double x, @@ -585,6 +683,16 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, double x_incr, y_incr; HDC hdc = NULL; + /* GetCharacterPlacement() returns utf16 instead of glyph indices + * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */ + if (scaled_font->is_type1) + return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font, + x, + y, + utf8, + glyphs, + num_glyphs); + /* Compute a vector in user space along the baseline of length one logical space unit */ x_incr = 1; y_incr = 0; @@ -742,11 +850,27 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) } - scaled_font->is_truetype = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) != 0; - scaled_font->glyph_indexing = scaled_font->is_truetype || - (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR); - // XXX in what situations does this OPENTYPE_CFF thing not have the - // TMPF_TRUETYPE flag? GetFontData says it only works on Truetype fonts... + scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR); + + /* Need to determine if this is a Type 1 font for the special + * handling in _text_to_glyphs. Unlike TrueType or OpenType, + * Type1 fonts do not have a "cmap" table (or any other table). + * However GetFontData() will retrieve a Type1 font when + * requesting that GetFontData() retrieve data from the start of + * the file. This is to distinguish Type1 from stroke fonts such + * as "Script" and "Modern". The TMPF_TRUETYPE test is redundant + * but improves performance for the most common fonts. + */ + scaled_font->is_type1 = FALSE; + if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) && + (metrics.tmPitchAndFamily & TMPF_VECTOR)) + { + if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) && + (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR)) + { + scaled_font->is_type1 = TRUE; + } + } _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); @@ -767,7 +891,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f if (!hdc) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (!scaled_font->is_truetype) { + if (scaled_font->is_bitmap) { /* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */ cairo_font_extents_t font_extents; INT width = 0; @@ -880,7 +1004,6 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, GLYPHMETRICS metrics; cairo_status_t status; int i; - UINT glyph_index_option; if (!hdc) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -889,16 +1012,11 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, if (status) return status; - if (scaled_font->glyph_indexing) - glyph_index_option = GGO_GLYPH_INDEX; - else - glyph_index_option = 0; - for (i = 0; i < num_glyphs; i++) { int x = _cairo_lround (glyphs[i].x); int y = _cairo_lround (glyphs[i].y); - GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option, + GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX, &metrics, 0, NULL, &matrix); if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x) @@ -954,22 +1072,16 @@ _flush_glyphs (cairo_glyph_state_t *state) int dx = 0; WCHAR * elements; int * dx_elements; - UINT glyph_index_option; status = _cairo_array_append (&state->dx, &dx); if (status) return status; - if (state->scaled_font->glyph_indexing) - glyph_index_option = ETO_GLYPH_INDEX; - else - glyph_index_option = 0; - elements = _cairo_array_index (&state->glyphs, 0); dx_elements = _cairo_array_index (&state->dx, 0); if (!ExtTextOutW (state->hdc, state->start_x, state->last_y, - glyph_index_option, + ETO_GLYPH_INDEX, NULL, elements, state->glyphs.num_elements, @@ -1157,8 +1269,10 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font, return status; } - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { - ASSERT_NOT_REACHED; + if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { + status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph); + if (status) + return status; } if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) { @@ -1316,18 +1430,143 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, return status; } -static void +static cairo_int_status_t _cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font, - cairo_scaled_font_subset_t *font_subset) + cairo_scaled_font_subset_t *font_subset) { cairo_win32_scaled_font_t *scaled_font = abstract_font; - unsigned int i; + GLYPHSET *glyph_set; + uint16_t *utf16 = NULL; + WORD *glyph_indices = NULL; + HDC hdc = NULL; + int res; + unsigned int i, j, k, count, num_glyphs; + cairo_status_t status = CAIRO_STATUS_SUCCESS; - if (scaled_font->glyph_indexing) - return; + hdc = _get_global_font_dc (); + if (!hdc) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - for (i = 0; i < font_subset->num_glyphs; i++) - font_subset->to_unicode[i] = font_subset->glyphs[i]; + status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + if (status) + return status; + + res = GetFontUnicodeRanges(hdc, NULL); + if (res == 0) { + status = _cairo_win32_print_gdi_error ( + "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges"); + goto fail1; + } + + glyph_set = malloc (res); + if (glyph_set == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail1; + } + + res = GetFontUnicodeRanges(hdc, glyph_set); + if (res == 0) { + status = _cairo_win32_print_gdi_error ( + "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges"); + goto fail2; + } + + count = font_subset->num_glyphs; + for (i = 0; i < glyph_set->cRanges && count > 0; i++) { + num_glyphs = glyph_set->ranges[i].cGlyphs; + + utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t)); + if (utf16 == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail2; + } + + glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD)); + if (glyph_indices == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail2; + } + + for (j = 0; j < num_glyphs; j++) + utf16[j] = glyph_set->ranges[i].wcLow + j; + utf16[j] = 0; + + if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ( + "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetGlyphIndicesW"); + goto fail2; + } + + for (j = 0; j < num_glyphs; j++) { + for (k = 0; k < font_subset->num_glyphs; k++) { + if (font_subset->glyphs[k] == glyph_indices[j]) { + font_subset->to_unicode[k] = utf16[j]; + count--; + break; + } + } + } + + free (glyph_indices); + glyph_indices = NULL; + free (utf16); + utf16= NULL; + } + +fail2: + if (glyph_indices) + free (glyph_indices); + if (utf16) + free (utf16); + free (glyph_set); +fail1: + cairo_win32_scaled_font_done_font (&scaled_font->base); + + return status; +} + +static cairo_status_t +_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_glyph_t glyph; + cairo_win32_surface_t *surface; + cairo_t *cr; + cairo_surface_t *image; + int width, height; + int x1, y1, x2, y2; + + x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); + y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); + x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); + y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); + width = x2 - x1; + height = y2 - y1; + + surface = (cairo_win32_surface_t *) + cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height); + + cr = cairo_create((cairo_surface_t *)surface); + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + cairo_destroy(cr); + + glyph.index = _cairo_scaled_glyph_index (scaled_glyph); + glyph.x = -x1; + glyph.y = -y1; + status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0), + 0, 0, &glyph, 1); + GdiFlush(); + + image = _compute_a8_mask (surface); + cairo_surface_set_device_offset ((cairo_surface_t *)image, -x1, -y1); + _cairo_scaled_glyph_set_surface (scaled_glyph, + &scaled_font->base, + (cairo_image_surface_t*)image); + cairo_surface_destroy (&surface->base); + + return status; } static void @@ -1355,7 +1594,9 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font cairo_path_fixed_t *path; cairo_matrix_t transform; cairo_fixed_t x, y; - UINT glyph_index_option; + + if (scaled_font->is_bitmap) + return CAIRO_INT_STATUS_UNSUPPORTED; hdc = _get_global_font_dc (); if (!hdc) @@ -1376,13 +1617,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font if (status) goto CLEANUP_PATH; - if (scaled_font->glyph_indexing) - glyph_index_option = GGO_GLYPH_INDEX; - else - glyph_index_option = 0; - bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | glyph_index_option, + GGO_NATIVE | GGO_GLYPH_INDEX, &metrics, 0, NULL, &matrix); if (bytesGlyph == GDI_ERROR) { @@ -1398,7 +1634,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font } if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | glyph_index_option, + GGO_NATIVE | GGO_GLYPH_INDEX, &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); goto CLEANUP_BUFFER; diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c index 57f1ab07e975..f7b96811ba79 100644 --- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c @@ -70,8 +70,11 @@ # define FEATURESETTING_PSLEVEL 0x0002 #endif +#if !defined(GRADIENT_FILL_RECT_H) +# define GRADIENT_FILL_RECT_H 0x00 +#endif + #define PELS_72DPI ((LONG)(72. / 0.0254)) -#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil) static const cairo_surface_backend_t cairo_win32_printing_surface_backend; static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend; @@ -457,11 +460,14 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa EndPath (surface->dc); SelectClipPath (surface->dc, RGN_AND); + SaveDC (surface->dc); /* Allow clip path to be reset during replay */ status = _cairo_meta_surface_replay (meta_surface, &surface->base); + + /* Restore both the clip save and our earlier path SaveDC */ + RestoreDC (surface->dc, -2); + if (status) return status; - - RestoreDC (surface->dc, -1); } } @@ -874,6 +880,7 @@ _cairo_win32_printing_surface_path_line_to (void *closure, cairo_point_t *point) { win32_path_info_t *path_info = closure; + path_info->surface->path_empty = FALSE; if (path_info->surface->has_ctm) { double x, y; @@ -899,6 +906,7 @@ _cairo_win32_printing_surface_path_curve_to (void *closure, win32_path_info_t *path_info = closure; POINT points[3]; + path_info->surface->path_empty = FALSE; if (path_info->surface->has_ctm) { double x, y; @@ -965,9 +973,8 @@ _cairo_win32_printing_surface_show_page (void *abstract_surface) { cairo_win32_surface_t *surface = abstract_surface; - if (surface->clip_saved_dc != 0) - RestoreDC (surface->dc, surface->clip_saved_dc); - RestoreDC (surface->dc, -1); + /* Undo both SaveDC's that we did in start_page */ + RestoreDC (surface->dc, -2); return CAIRO_STATUS_SUCCESS; } @@ -986,10 +993,9 @@ _cairo_win32_printing_surface_intersect_clip_path (void *abstract_surface return CAIRO_STATUS_SUCCESS; if (path == NULL) { - if (surface->clip_saved_dc != 0) { - RestoreDC (surface->dc, surface->clip_saved_dc); - surface->clip_saved_dc = 0; - } + RestoreDC (surface->dc, -1); + SaveDC (surface->dc); + return CAIRO_STATUS_SUCCESS; } @@ -1008,8 +1014,6 @@ _cairo_win32_printing_surface_intersect_clip_path (void *abstract_surface ASSERT_NOT_REACHED; } - if (surface->clip_saved_dc == 0) - surface->clip_saved_dc = SaveDC (surface->dc); SelectClipPath (surface->dc, RGN_AND); return status; @@ -1244,6 +1248,7 @@ _cairo_win32_printing_surface_fill (void *abstract_surface, assert (_cairo_win32_printing_surface_operation_supported (surface, op, source)); + surface->path_empty = TRUE; BeginPath (surface->dc); status = _cairo_win32_printing_surface_emit_path (surface, path); EndPath (surface->dc); @@ -1266,7 +1271,7 @@ _cairo_win32_printing_surface_fill (void *abstract_surface, FillPath (surface->dc); _cairo_win32_printing_surface_done_solid_brush (surface); - } else { + } else if (surface->path_empty == FALSE) { SaveDC (surface->dc); SelectClipPath (surface->dc, RGN_AND); status = _cairo_win32_printing_surface_paint_pattern (surface, source); @@ -1323,9 +1328,9 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac color = _cairo_win32_printing_surface_flatten_transparency (surface, &solid->color); - opaque = cairo_pattern_create_rgb (GetRValue (color), - GetGValue (color), - GetBValue (color)); + opaque = cairo_pattern_create_rgb (GetRValue (color) / 255.0, + GetGValue (color) / 255.0, + GetBValue (color) / 255.0); if (opaque->status) return opaque->status; source = opaque; @@ -1358,6 +1363,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac old_ctm = surface->ctm; old_has_ctm = surface->has_ctm; surface->has_ctm = TRUE; + surface->path_empty = TRUE; BeginPath (surface->dc); for (i = 0; i < num_glyphs; i++) { status = _cairo_scaled_glyph_lookup (scaled_font, @@ -1373,9 +1379,19 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac EndPath (surface->dc); surface->ctm = old_ctm; surface->has_ctm = old_has_ctm; - if (status == CAIRO_STATUS_SUCCESS) { - SelectClipPath (surface->dc, RGN_AND); - status = _cairo_win32_printing_surface_paint_pattern (surface, source); + if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) { + if (source->type == CAIRO_PATTERN_TYPE_SOLID) { + status = _cairo_win32_printing_surface_select_solid_brush (surface, source); + if (status) + return status; + + SetPolyFillMode (surface->dc, WINDING); + FillPath (surface->dc); + _cairo_win32_printing_surface_done_solid_brush (surface); + } else { + SelectClipPath (surface->dc, RGN_AND); + status = _cairo_win32_printing_surface_paint_pattern (surface, source); + } } RestoreDC (surface->dc, -1); @@ -1400,7 +1416,8 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface) cairo_win32_surface_t *surface = abstract_surface; XFORM xform; - SaveDC (surface->dc); + SaveDC (surface->dc); /* Save application context first, before doing MWT */ + SetGraphicsMode (surface->dc, GM_ADVANCED); GetWorldTransform(surface->dc, &xform); surface->ctm.xx = xform.eM11; @@ -1413,6 +1430,8 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface) if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY)) return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform"); + SaveDC (surface->dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */ + return CAIRO_STATUS_SUCCESS; } @@ -1445,22 +1464,16 @@ cairo_surface_t * cairo_win32_printing_surface_create (HDC hdc) { cairo_win32_surface_t *surface; - RECT rect; int xr, yr; - - /* Try to figure out the drawing bounds for the Device context - */ - if (GetClipBox (hdc, &rect) == ERROR) { - _cairo_win32_print_gdi_error ("cairo_win32_surface_create"); - /* XXX: Can we make a more reasonable guess at the error cause here? */ - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NIL_SURFACE; - } + RECT rect; surface = malloc (sizeof (cairo_win32_surface_t)); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NIL_SURFACE; + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + + if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) { + free (surface); + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } surface->image = NULL; @@ -1474,28 +1487,14 @@ cairo_win32_printing_surface_create (HDC hdc) surface->brush = NULL; surface->old_brush = NULL; - surface->clip_rect.x = (int16_t) rect.left; - surface->clip_rect.y = (int16_t) rect.top; - surface->clip_rect.width = (uint16_t) (rect.right - rect.left); - surface->clip_rect.height = (uint16_t) (rect.bottom - rect.top); - - if (surface->clip_rect.width == 0 || - surface->clip_rect.height == 0) - { - surface->saved_clip = NULL; - } else { - surface->saved_clip = CreateRectRgn (0, 0, 0, 0); - if (GetClipRgn (hdc, surface->saved_clip) == 0) { - DeleteObject(surface->saved_clip); - surface->saved_clip = NULL; - } - } - - surface->extents = surface->clip_rect; + GetClipBox(hdc, &rect); + surface->extents.x = rect.left; + surface->extents.y = rect.top; + surface->extents.width = rect.right - rect.left; + surface->extents.height = rect.bottom - rect.top; surface->flags = _cairo_win32_flags_for_dc (surface->dc); surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING; - surface->clip_saved_dc = 0; _cairo_win32_printing_surface_init_ps_mode (surface); _cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend, @@ -1507,8 +1506,8 @@ cairo_win32_printing_surface_create (HDC hdc) return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, - rect.right - rect.left, - rect.bottom - rect.top, + surface->extents.width, + surface->extents.height, &cairo_win32_surface_paginated_backend); } diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h index 0598876ef9db..be01ec61039f 100644 --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -71,21 +71,26 @@ typedef struct _cairo_win32_surface { cairo_surface_t *image; - cairo_rectangle_int_t clip_rect; - - HRGN saved_clip; - cairo_rectangle_int_t extents; + /* Initial clip bits + * We need these kept around so that we maintain + * whatever clip was set on the original DC at creation + * time when cairo is asked to reset the surface clip. + */ + cairo_rectangle_int_t clip_rect; + HRGN initial_clip_rgn; + cairo_bool_t had_simple_clip; + /* Surface DC flags */ uint32_t flags; /* printing surface bits */ cairo_paginated_mode_t paginated_mode; cairo_content_t content; + cairo_bool_t path_empty; cairo_bool_t has_ctm; cairo_matrix_t ctm; - int clip_saved_dc; HBRUSH brush, old_brush; } cairo_win32_surface_t; @@ -127,7 +132,7 @@ _cairo_win32_surface_finish (void *abstract_surface); cairo_int_status_t _cairo_win32_surface_get_extents (void *abstract_surface, - cairo_rectangle_int16_t *rectangle); + cairo_rectangle_int_t *rectangle); uint32_t _cairo_win32_flags_for_dc (HDC dc); @@ -167,4 +172,13 @@ _cairo_matrix_to_win32_xform (const cairo_matrix_t *m, xform->eDy = (FLOAT) m->y0; } +cairo_int_status_t +_cairo_win32_save_initial_clip (HDC dc, cairo_win32_surface_t *surface); + +cairo_int_status_t +_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface); + +void +_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header); + #endif /* CAIRO_WIN32_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index dd99b8f3c593..78e59cacf2d2 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -67,7 +67,6 @@ #endif #define PELS_72DPI ((LONG)(72. / 0.0254)) -#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil) static const cairo_surface_backend_t cairo_win32_surface_backend; @@ -91,7 +90,7 @@ _cairo_win32_print_gdi_error (const char *context) NULL, last_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, + (LPSTR) &lpMsgBuf, 0, NULL)) { fprintf (stderr, "%s: Unknown GDI error", context); } else { @@ -333,10 +332,8 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, int rowstride; surface = malloc (sizeof (cairo_win32_surface_t)); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NIL_SURFACE; - } + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); status = _create_dc_and_bitmap (surface, original_dc, format, width, height, @@ -346,10 +343,9 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, surface->image = cairo_image_surface_create_for_data (bits, format, width, height, rowstride); - if (surface->image->status) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = surface->image->status; + if (status) goto FAIL; - } surface->format = format; @@ -358,14 +354,15 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, surface->clip_rect.width = width; surface->clip_rect.height = height; - surface->saved_clip = NULL; + surface->initial_clip_rgn = NULL; + surface->had_simple_clip = FALSE; surface->extents = surface->clip_rect; _cairo_surface_init (&surface->base, &cairo_win32_surface_backend, _cairo_content_from_format (format)); - return (cairo_surface_t *)surface; + return &surface->base; FAIL: if (surface->bitmap) { @@ -373,10 +370,9 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, DeleteObject (surface->bitmap); DeleteDC (surface->dc); } - if (surface) - free (surface); + free (surface); - return NIL_SURFACE; + return _cairo_surface_create_in_error (status); } static cairo_surface_t * @@ -478,26 +474,11 @@ _cairo_win32_surface_finish (void *abstract_surface) DeleteObject (surface->bitmap); DeleteDC (surface->dc); } else { - /* otherwise, restore the old clip region on the DC */ - SelectClipRgn (surface->dc, surface->saved_clip); - - if (surface->saved_clip == NULL) { - /* We never had a clip region, so just restore the clip - * to the bounds. */ - if (surface->clip_rect.width != 0 && - surface->clip_rect.height != 0) - { - IntersectClipRect (surface->dc, - surface->clip_rect.x, - surface->clip_rect.y, - surface->clip_rect.x + surface->clip_rect.width, - surface->clip_rect.y + surface->clip_rect.height); - } - } + _cairo_win32_restore_initial_clip (surface); } - if (surface->saved_clip) - DeleteObject (surface->saved_clip); + if (surface->initial_clip_rgn) + DeleteObject (surface->initial_clip_rgn); return CAIRO_STATUS_SUCCESS; } @@ -570,8 +551,8 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur } status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0, - surface->clip_rect.width, - surface->clip_rect.height, &local); + surface->extents.width, + surface->extents.height, &local); if (status) return status; @@ -610,8 +591,8 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa image_rect->x = 0; image_rect->y = 0; - image_rect->width = surface->clip_rect.width; - image_rect->height = surface->clip_rect.height; + image_rect->width = surface->extents.width; + image_rect->height = surface->extents.height; *image_out = (cairo_image_surface_t *)surface->image; *image_extra = NULL; @@ -745,7 +726,7 @@ _composite_alpha_blend (cairo_win32_surface_t *dst, if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId || os.dwMajorVersion != 4 || os.dwMinorVersion != 10) { - HMODULE msimg32_dll = LoadLibrary ("msimg32"); + HMODULE msimg32_dll = LoadLibraryA ("msimg32"); if (msimg32_dll != NULL) alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll, @@ -1445,13 +1426,11 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface, * save the original clip when first setting a clip on surface. */ - if (region == NULL) { - /* Clear any clip set by cairo, return to the original */ - if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)"); + /* Clear any clip set by cairo, return to the original first */ + status = _cairo_win32_restore_initial_clip (surface); - status = CAIRO_STATUS_SUCCESS; - } else { + /* Then combine any new region with it */ + if (region) { cairo_rectangle_int_t extents; cairo_box_int_t *boxes; int num_boxes; @@ -1485,6 +1464,13 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface, _cairo_region_boxes_fini (region, boxes); } else { + /* XXX see notes in _cairo_win32_save_initial_clip -- + * this code will interact badly with a HDC which had an initial + * world transform -- we should probably manually transform the + * region rects, because SelectClipRgn takes device units, not + * logical units (unlike IntersectClipRect). + */ + data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT); data = malloc (data_size); if (!data) { @@ -1517,17 +1503,9 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface, if (!gdi_region) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - /* Combine the new region with the original clip */ - if (surface->saved_clip) { - if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR) - status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region"); - } - - /* Then select the new clip region into our surface if everything went ok */ - if (status == CAIRO_STATUS_SUCCESS) { - if (SelectClipRgn (surface->dc, gdi_region) == ERROR) - status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region"); - } + /* AND the new region into our DC */ + if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR) + status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region"); DeleteObject (gdi_region); } @@ -1709,20 +1687,10 @@ cairo_surface_t * cairo_win32_surface_create (HDC hdc) { cairo_win32_surface_t *surface; - RECT rect; + int depth; cairo_format_t format; - int clipBoxType; - - /* Try to figure out the drawing bounds for the Device context - */ - clipBoxType = GetClipBox (hdc, &rect); - if (clipBoxType == ERROR) { - _cairo_win32_print_gdi_error ("cairo_win32_surface_create"); - /* XXX: Can we make a more reasonable guess at the error cause here? */ - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NIL_SURFACE; - } + RECT rect; if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) { depth = GetDeviceCaps(hdc, BITSPIXEL); @@ -1738,17 +1706,19 @@ cairo_win32_surface_create (HDC hdc) format = CAIRO_FORMAT_A1; else { _cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)"); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NIL_SURFACE; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); } } else { format = CAIRO_FORMAT_RGB24; } surface = malloc (sizeof (cairo_win32_surface_t)); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NIL_SURFACE; + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + + if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) { + free (surface); + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } surface->image = NULL; @@ -1761,26 +1731,13 @@ cairo_win32_surface_create (HDC hdc) surface->brush = NULL; surface->old_brush = NULL; - surface->clip_rect.x = (int16_t) rect.left; - surface->clip_rect.y = (int16_t) rect.top; - surface->clip_rect.width = (uint16_t) (rect.right - rect.left); - surface->clip_rect.height = (uint16_t) (rect.bottom - rect.top); - - if (clipBoxType == COMPLEXREGION) { - surface->saved_clip = CreateRectRgn (0, 0, 0, 0); - if (GetClipRgn (hdc, surface->saved_clip) == 0) { - /* this should never happen */ - DeleteObject(surface->saved_clip); - surface->saved_clip = NULL; - } - } else { - surface->saved_clip = NULL; - } - - surface->extents = surface->clip_rect; + GetClipBox(hdc, &rect); + surface->extents.x = rect.left; + surface->extents.y = rect.top; + surface->extents.width = rect.right - rect.left; + surface->extents.height = rect.bottom - rect.top; surface->flags = _cairo_win32_flags_for_dc (surface->dc); - surface->clip_saved_dc = 0; _cairo_surface_init (&surface->base, &cairo_win32_surface_backend, _cairo_content_from_format (format)); @@ -1837,7 +1794,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc, HBITMAP saved_dc_bitmap; if (format != CAIRO_FORMAT_RGB24) - return NIL_SURFACE; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); /* XXX handle these eventually format != CAIRO_FORMAT_A8 || format != CAIRO_FORMAT_A1) @@ -1853,7 +1810,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc, ddb_dc = CreateCompatibleDC (hdc); if (ddb_dc == NULL) { _cairo_win32_print_gdi_error("CreateCompatibleDC"); - new_surf = (cairo_win32_surface_t*) NIL_SURFACE; + new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto FINISH; } @@ -1866,7 +1823,7 @@ cairo_win32_surface_create_with_ddb (HDC hdc, * video memory is probably exhausted. */ _cairo_win32_print_gdi_error("CreateCompatibleBitmap"); - new_surf = (cairo_win32_surface_t*) NIL_SURFACE; + new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); goto FINISH; } @@ -2050,3 +2007,120 @@ DllMain (HINSTANCE hinstDLL, #endif +cairo_int_status_t +_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface) +{ + RECT rect; + int clipBoxType; + int gm; + XFORM saved_xform; + + /* GetClipBox/GetClipRgn and friends interact badly with a world transform + * set. GetClipBox returns values in logical (transformed) coordinates; + * it's unclear what GetClipRgn returns, because the region is empty in the + * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates. + * Similarily, IntersectClipRect works in logical units, whereas SelectClipRgn + * works in device units. + * + * So, avoid the whole mess and get rid of the world transform + * while we store our initial data and when we restore initial coordinates. + * + * XXX we may need to modify x/y by the ViewportOrg or WindowOrg + * here in GM_COMPATIBLE; unclear. + */ + gm = GetGraphicsMode (hdc); + if (gm == GM_ADVANCED) { + GetWorldTransform (hdc, &saved_xform); + ModifyWorldTransform (hdc, NULL, MWT_IDENTITY); + } + + clipBoxType = GetClipBox (hdc, &rect); + if (clipBoxType == ERROR) { + _cairo_win32_print_gdi_error ("cairo_win32_surface_create"); + SetGraphicsMode (hdc, gm); + /* XXX: Can we make a more reasonable guess at the error cause here? */ + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + surface->clip_rect.x = rect.left; + surface->clip_rect.y = rect.top; + surface->clip_rect.width = rect.right - rect.left; + surface->clip_rect.height = rect.bottom - rect.top; + + surface->initial_clip_rgn = NULL; + surface->had_simple_clip = FALSE; + + if (clipBoxType == COMPLEXREGION) { + surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0); + if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) { + /* this should never happen */ + DeleteObject(surface->initial_clip_rgn); + surface->initial_clip_rgn = NULL; + } + } else if (clipBoxType == SIMPLEREGION) { + surface->had_simple_clip = TRUE; + } + + if (gm == GM_ADVANCED) + SetWorldTransform (hdc, &saved_xform); + + return CAIRO_STATUS_SUCCESS; +} + +cairo_int_status_t +_cairo_win32_restore_initial_clip (cairo_win32_surface_t *surface) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + XFORM saved_xform; + int gm = GetGraphicsMode (surface->dc); + if (gm == GM_ADVANCED) { + GetWorldTransform (surface->dc, &saved_xform); + ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY); + } + + /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */ + SelectClipRgn (surface->dc, surface->initial_clip_rgn); + + if (surface->had_simple_clip) { + /* then if we had a simple clip, intersect */ + IntersectClipRect (surface->dc, + surface->clip_rect.x, + surface->clip_rect.y, + surface->clip_rect.x + surface->clip_rect.width, + surface->clip_rect.y + surface->clip_rect.height); + } + + if (gm == GM_ADVANCED) + SetWorldTransform (surface->dc, &saved_xform); + + return status; +} + +void +_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header) +{ + RGNDATA *rd; + int z; + + if (header) + fprintf (stderr, "%s\n", header); + + if (rgn == NULL) { + fprintf (stderr, " NULL\n"); + } + + z = GetRegionData(rgn, 0, NULL); + rd = (RGNDATA*) malloc(z); + z = GetRegionData(rgn, z, rd); + + fprintf (stderr, " %d rects, bounds: %d %d %d %d\n", rd->rdh.nCount, rd->rdh.rcBound.left, rd->rdh.rcBound.top, rd->rdh.rcBound.right - rd->rdh.rcBound.left, rd->rdh.rcBound.bottom - rd->rdh.rcBound.top); + + for (z = 0; z < rd->rdh.nCount; z++) { + RECT r = ((RECT*)rd->Buffer)[z]; + fprintf (stderr, " [%d]: [%d %d %d %d]\n", z, r.left, r.top, r.right - r.left, r.bottom - r.top); + } + + free(rd); + fflush (stderr); +} diff --git a/gfx/cairo/cairo/src/cairo-win32.c b/gfx/cairo/cairo/src/cairo-win32.c new file mode 100644 index 000000000000..a656ff8e6a6e --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-win32.c @@ -0,0 +1,98 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ +/* Cairo - a vector graphics library with display and print output + * + * Copyright © 2007 Adrian Johnson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.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/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson + */ + +#define WIN32_LEAN_AND_MEAN +/* We require Windows 2000 features such as ETO_PDY */ +#if !defined(WINVER) || (WINVER < 0x0500) +# define WINVER 0x0500 +#endif +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) +# define _WIN32_WINNT 0x0500 +#endif + +#include "cairoint.h" + +#include +#include + +/* tmpfile() replacment for Windows. + * + * On Windows tmpfile() creates the file in the root directory. This + * may fail due to unsufficient privileges. + */ +FILE * +_cairo_win32_tmpfile (void) +{ + DWORD path_len; + WCHAR path_name[MAX_PATH + 1]; + WCHAR file_name[MAX_PATH + 1]; + HANDLE handle; + int fd; + FILE *fp; + + path_len = GetTempPathW (MAX_PATH, path_name); + if (path_len <= 0 || path_len >= MAX_PATH) + return NULL; + + if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0) + return NULL; + + handle = CreateFileW (file_name, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (handle == INVALID_HANDLE_VALUE) { + DeleteFileW (file_name); + return NULL; + } + + fd = _open_osfhandle((intptr_t) handle, 0); + if (fd < 0) { + CloseHandle (handle); + return NULL; + } + + fp = fdopen(fd, "w+b"); + if (fp == NULL) { + _close(fd); + return NULL; + } + + return fp; +} diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c index 451cc8f43066..6187db281d98 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c @@ -196,10 +196,8 @@ _cairo_xcb_surface_create_similar (void *abstract_src, cairo_xcb_surface_create_with_xrender_format (dpy, pixmap, src->screen, xrender_format, width, height); - if (surface->base.status) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (surface->base.status) + return surface; surface->owns_pixmap = TRUE; @@ -315,7 +313,7 @@ _get_image_surface (cairo_xcb_surface_t *surface, y2 = surface->height; if (interest_rect) { - cairo_rectangle_int16_t rect; + cairo_rectangle_int_t rect; rect.x = interest_rect->x; rect.y = interest_rect->y; @@ -1730,10 +1728,8 @@ _cairo_xcb_surface_create_internal (xcb_connection_t *dpy, const xcb_render_query_version_reply_t *r; surface = malloc (sizeof (cairo_xcb_surface_t)); - if (surface == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (surface == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); if (xrender_format) { depth = xrender_format->depth; @@ -1873,10 +1869,8 @@ cairo_xcb_surface_create (xcb_connection_t *c, { xcb_screen_t *screen = _cairo_xcb_screen_from_visual (c, visual); - if (screen == NULL) { - _cairo_error (CAIRO_STATUS_INVALID_VISUAL); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (screen == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL)); return _cairo_xcb_surface_create_internal (c, drawable, screen, visual, NULL, @@ -2411,7 +2405,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst, (cairo_surface_t **) &src, &attributes); } else { - cairo_rectangle_int16_t glyph_extents; + cairo_rectangle_int_t glyph_extents; status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, diff --git a/gfx/cairo/cairo/src/cairo-xlib-display.c b/gfx/cairo/cairo/src/cairo-xlib-display.c index efb53ba2a78a..d10ed1e0b96e 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-display.c +++ b/gfx/cairo/cairo/src/cairo-xlib-display.c @@ -34,6 +34,7 @@ #include "cairoint.h" #include "cairo-xlib-private.h" +#include "cairo-xlib-xrender-private.h" #include @@ -124,9 +125,6 @@ _cairo_xlib_display_discard_screens (cairo_xlib_display_t *display) cairo_xlib_display_t * _cairo_xlib_display_reference (cairo_xlib_display_t *display) { - if (display == NULL) - return NULL; - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count)); _cairo_reference_count_inc (&display->ref_count); @@ -137,9 +135,6 @@ _cairo_xlib_display_reference (cairo_xlib_display_t *display) void _cairo_xlib_display_destroy (cairo_xlib_display_t *display) { - if (display == NULL) - return; - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count)); if (! _cairo_reference_count_dec_and_test (&display->ref_count)) @@ -212,6 +207,7 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) } CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); + assert (display != NULL); _cairo_xlib_display_destroy (display); /* Return value in accordance with requirements of @@ -292,7 +288,14 @@ _cairo_xlib_display_get (Display *dpy) display->buggy_repeat = FALSE; if (strstr (ServerVendor (dpy), "X.Org") != NULL) { - if (VendorRelease (dpy) <= 60802000) + /* When modularized, the X.Org server VendorRelease was + * bogusly reset to a very small number, without any change in + * the ServerVendor string. We avoid considering the new + * servers with the small number as buggy by restricting the + * test to known bad releases. But there could be a problem + * again in the future if X.Org server versions ever climb + * back up to 6.7 or 6.8. */ + if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000) display->buggy_repeat = TRUE; } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) { if (VendorRelease (dpy) <= 40500000) diff --git a/gfx/cairo/cairo/src/cairo-xlib-private.h b/gfx/cairo/cairo/src/cairo-xlib-private.h index 05c7d0e4c193..3e04ecd80e14 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-private.h +++ b/gfx/cairo/cairo/src/cairo-xlib-private.h @@ -33,16 +33,12 @@ #ifndef CAIRO_XLIB_PRIVATE_H #define CAIRO_XLIB_PRIVATE_H -#include "cairoint.h" - #include "cairo-xlib.h" #include "cairo-compiler-private.h" #include "cairo-freelist-private.h" +#include "cairo-mutex-private.h" #include "cairo-reference-count-private.h" -#include "cairo-xlib-xrender-private.h" - -#include /* for XDestroyImage */ typedef struct _cairo_xlib_display cairo_xlib_display_t; typedef struct _cairo_xlib_hook cairo_xlib_hook_t; diff --git a/gfx/cairo/cairo/src/cairo-xlib-screen.c b/gfx/cairo/cairo/src/cairo-xlib-screen.c index 578a33a698f5..b759a85e31f5 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-screen.c +++ b/gfx/cairo/cairo/src/cairo-xlib-screen.c @@ -55,6 +55,7 @@ #include "cairoint.h" #include "cairo-xlib-private.h" +#include "cairo-xlib-xrender-private.h" #include @@ -243,9 +244,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in cairo_xlib_screen_info_t * _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info) { - if (info == NULL) - return NULL; - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count)); _cairo_reference_count_inc (&info->ref_count); @@ -272,9 +270,6 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info) cairo_xlib_screen_info_t **prev; cairo_xlib_screen_info_t *list; - if (info == NULL) - return; - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count)); if (! _cairo_reference_count_dec_and_test (&info->ref_count)) diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface-private.h b/gfx/cairo/cairo/src/cairo-xlib-surface-private.h index 3bbf43e23593..e5ccf905a179 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-xlib-surface-private.h @@ -34,6 +34,8 @@ #define CAIRO_XLIB_SURFACE_PRIVATE_H #include "cairo-xlib.h" +#include "cairo-xlib-private.h" +#include "cairo-xlib-xrender-private.h" #include "cairo-surface-private.h" diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index f5267e1cd608..be5aa0931c3d 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -42,6 +42,8 @@ #include "cairo-xlib-surface-private.h" #include "cairo-clip-private.h" +#include /* for XDestroyImage */ + /* Xlib doesn't define a typedef, so define one ourselves */ typedef int (*cairo_xlib_error_func_t) (Display *display, XErrorEvent *event); @@ -69,6 +71,10 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, int num_glyphs, cairo_scaled_font_t *scaled_font); +#if CAIRO_HAS_XLIB_XRENDER_SURFACE +slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format); +#endif + /* * Instead of taking two round trips for each blending request, * assume that if a particular drawable fails GetImage that it will @@ -170,10 +176,9 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src, cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen, xrender_format, width, height); - if (surface->base.status != CAIRO_STATUS_SUCCESS) { + if (surface->base.status) { XFreePixmap (dpy, pix); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return &surface->base; } surface->owns_pixmap = TRUE; @@ -252,8 +257,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src, width, height); if (surface->base.status != CAIRO_STATUS_SUCCESS) { XFreePixmap (src->dpy, pix); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return &surface->base; } surface->owns_pixmap = TRUE; @@ -469,7 +473,7 @@ _get_image_surface (cairo_xlib_surface_t *surface, y2 = surface->height; if (interest_rect) { - cairo_rectangle_int16_t rect; + cairo_rectangle_int_t rect; rect.x = interest_rect->x; rect.y = interest_rect->y; @@ -1011,6 +1015,7 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, break; case CAIRO_EXTEND_REFLECT: case CAIRO_EXTEND_PAD: + default: status = CAIRO_INT_STATUS_UNSUPPORTED; } if (status) @@ -1942,24 +1947,20 @@ _cairo_xlib_surface_create_internal (Display *dpy, cairo_xlib_screen_info_t *screen_info; screen_info = _cairo_xlib_screen_info_get (dpy, screen); - if (screen_info == NULL) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (screen_info == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); surface = malloc (sizeof (cairo_xlib_surface_t)); if (surface == NULL) { _cairo_xlib_screen_info_destroy (screen_info); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } if (! _cairo_xlib_add_close_display_hook (dpy, _cairo_xlib_surface_detach_display, surface, surface)) { free (surface); _cairo_xlib_screen_info_destroy (screen_info); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } if (xrender_format) { @@ -2089,10 +2090,8 @@ cairo_xlib_surface_create (Display *dpy, { Screen *screen = _cairo_xlib_screen_from_visual (dpy, visual); - if (screen == NULL) { - _cairo_error_throw (CAIRO_STATUS_INVALID_VISUAL); - return (cairo_surface_t*) &_cairo_surface_nil; - } + if (screen == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL)); CAIRO_MUTEX_INITIALIZE (); @@ -2423,11 +2422,22 @@ cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface) return surface->height; } -typedef struct _cairo_xlib_surface_font_private { - Display *dpy; +enum { + GLYPHSET_INDEX_ARGB32, + GLYPHSET_INDEX_A8, + GLYPHSET_INDEX_A1, + NUM_GLYPHSETS +}; + +typedef struct _cairo_xlib_font_glyphset_info { GlyphSet glyphset; cairo_format_t format; XRenderPictFormat *xrender_format; +} cairo_xlib_font_glyphset_info_t; + +typedef struct _cairo_xlib_surface_font_private { + Display *dpy; + cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS]; } cairo_xlib_surface_font_private_t; static void @@ -2445,17 +2455,23 @@ _cairo_xlib_surface_remove_scaled_font (Display *dpy, CAIRO_MUTEX_UNLOCK (scaled_font->mutex); if (font_private != NULL) { - XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset); + int i; + for (i = 0; i < NUM_GLYPHSETS; i++) { + cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; + if (glyphset_info->glyphset) { + XRenderFreeGlyphSet (font_private->dpy, glyphset_info->glyphset); + } + } free (font_private); } } static cairo_status_t _cairo_xlib_surface_font_init (Display *dpy, - cairo_scaled_font_t *scaled_font, - cairo_format_t format) + cairo_scaled_font_t *scaled_font) { cairo_xlib_surface_font_private_t *font_private; + int i; font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); if (!font_private) @@ -2470,9 +2486,18 @@ _cairo_xlib_surface_font_init (Display *dpy, font_private->dpy = dpy; - font_private->format = format; - font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format); - font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format); + for (i = 0; i < NUM_GLYPHSETS; i++) { + cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; + switch (i) { + case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break; + case GLYPHSET_INDEX_A8: glyphset_info->format = CAIRO_FORMAT_A8; break; + case GLYPHSET_INDEX_A1: glyphset_info->format = CAIRO_FORMAT_A1; break; + default: ASSERT_NOT_REACHED; break; + } + glyphset_info->xrender_format = NULL; + glyphset_info->glyphset = None; + } + scaled_font->surface_private = font_private; scaled_font->surface_backend = &cairo_xlib_surface_backend; @@ -2491,10 +2516,19 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) display = _cairo_xlib_display_get (font_private->dpy); if (display != NULL) { - cairo_status_t status = _cairo_xlib_display_queue_resource (display, - XRenderFreeGlyphSet, - font_private->glyphset); - (void) status; /* XXX cannot propagate failure */ + int i; + + for (i = 0; i < NUM_GLYPHSETS; i++) { + cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; + if (glyphset_info->glyphset) { + cairo_status_t status; + status = _cairo_xlib_display_queue_resource (display, + XRenderFreeGlyphSet, + glyphset_info->glyphset); + (void) status; /* XXX cannot propagate failure */ + } + } + _cairo_xlib_display_destroy (display); } @@ -2513,6 +2547,19 @@ static void _cairo_xlib_render_free_glyphs (Display *dpy, struct _cairo_xlib_ren &arg->glyph_index, 1); } +static cairo_xlib_font_glyphset_info_t * +_cairo_xlib_scaled_glyph_get_glyphset_info (cairo_scaled_glyph_t *scaled_glyph) +{ + return scaled_glyph->surface_private; +} + +static void +_cairo_xlib_scaled_glyph_set_glyphset_info (cairo_scaled_glyph_t *scaled_glyph, + cairo_xlib_font_glyphset_info_t *glyphset_info) +{ + scaled_glyph->surface_private = glyphset_info; +} + static void _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font) @@ -2525,7 +2572,7 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, struct _cairo_xlib_render_free_glyphs *arg = malloc (sizeof (*arg)); if (arg != NULL) { cairo_status_t status; - arg->glyphset = font_private->glyphset; + arg->glyphset = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph)->glyphset; arg->glyph_index = _cairo_scaled_glyph_index (scaled_glyph); status = _cairo_xlib_display_queue_work (display, (cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs, @@ -2551,6 +2598,32 @@ _native_byte_order_lsb (void) return *((char *) &x) == 1; } +static cairo_xlib_font_glyphset_info_t * +_cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scaled_font, + cairo_format_t format) +{ + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + cairo_xlib_font_glyphset_info_t *glyphset_info; + int glyphset_index; + + switch (format) { + default: + case CAIRO_FORMAT_RGB24: + case CAIRO_FORMAT_ARGB32: glyphset_index = GLYPHSET_INDEX_ARGB32; break; + case CAIRO_FORMAT_A8: glyphset_index = GLYPHSET_INDEX_A8; break; + case CAIRO_FORMAT_A1: glyphset_index = GLYPHSET_INDEX_A1; break; + } + + glyphset_info = &font_private->glyphset_info[glyphset_index]; + + if (glyphset_info->glyphset == None) { + glyphset_info->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(font_private->dpy, glyphset_info->format); + glyphset_info->glyphset = XRenderCreateGlyphSet (font_private->dpy, glyphset_info->xrender_format); + } + + return glyphset_info; +} + static cairo_status_t _cairo_xlib_surface_add_glyph (Display *dpy, cairo_scaled_font_t *scaled_font, @@ -2564,6 +2637,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph; cairo_image_surface_t *glyph_surface = scaled_glyph->surface; cairo_bool_t already_had_glyph_surface; + cairo_xlib_font_glyphset_info_t *glyphset_info; if (!glyph_surface) { @@ -2583,13 +2657,15 @@ _cairo_xlib_surface_add_glyph (Display *dpy, } if (scaled_font->surface_private == NULL) { - status = _cairo_xlib_surface_font_init (dpy, scaled_font, - glyph_surface->format); + status = _cairo_xlib_surface_font_init (dpy, scaled_font); if (status) return status; } font_private = scaled_font->surface_private; + glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font, + glyph_surface->format); + /* If the glyph surface has zero height or width, we create * a clear 1x1 surface, to avoid various X server bugs. */ @@ -2597,7 +2673,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, cairo_t *cr; cairo_surface_t *tmp_surface; - tmp_surface = cairo_image_surface_create (font_private->format, 1, 1); + tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1); cr = cairo_create (tmp_surface); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); @@ -2619,11 +2695,11 @@ _cairo_xlib_surface_add_glyph (Display *dpy, * create a temporary surface for the glyph image with the font's * format. */ - if (glyph_surface->format != font_private->format) { + if (glyph_surface->format != glyphset_info->format) { cairo_t *cr; cairo_surface_t *tmp_surface; - tmp_surface = cairo_image_surface_create (font_private->format, + tmp_surface = cairo_image_surface_create (glyphset_info->format, glyph_surface->width, glyph_surface->height); tmp_surface->device_transform = glyph_surface->base.device_transform; @@ -2719,11 +2795,13 @@ _cairo_xlib_surface_add_glyph (Display *dpy, glyph_index = _cairo_scaled_glyph_index (scaled_glyph); - XRenderAddGlyphs (dpy, font_private->glyphset, + XRenderAddGlyphs (dpy, glyphset_info->glyphset, &glyph_index, &(glyph_info), 1, (char *) data, glyph_surface->stride * glyph_surface->height); + _cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info); + if (data != glyph_surface->data) free (data); @@ -2773,19 +2851,23 @@ typedef struct { } p; } cairo_xlib_glyph_t; +/* compile-time assert that cairo_xlib_glyph_t is the same size as cairo_glyph_t */ +typedef int cairo_xlib_glyph_t_size_assertion [sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t) ? 1 : -1]; + #define GLYPH_INDEX_SKIP ((unsigned long) -1) -#define STACK_ELTS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (XGlyphElt8))) static cairo_status_t _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, cairo_xlib_glyph_t *glyphs, int num_glyphs, - int width, - int num_elts, cairo_scaled_font_t *scaled_font, cairo_operator_t op, cairo_xlib_surface_t *src, - cairo_surface_attributes_t *attributes) + cairo_surface_attributes_t *attributes, + /* info for this chunk */ + int num_elts, + int width, + cairo_xlib_font_glyphset_info_t *glyphset_info) { /* Which XRenderCompositeText function to use */ cairo_xrender_composite_text_func_t composite_text_func; @@ -2793,7 +2875,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, /* Element buffer stuff */ XGlyphElt8 *elts; - XGlyphElt8 stack_elts[STACK_ELTS_LEN]; + XGlyphElt8 stack_elts[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8)]; /* Reuse the input glyph array for output char generation */ char *char8 = (char *) glyphs; @@ -2805,8 +2887,6 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, int n; /* Num output glyphs in current element */ int j; /* Num output glyphs so far */ - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; - switch (width) { case 1: /* don't cast the 8-variant, to catch possible mismatches */ @@ -2824,7 +2904,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, } /* Allocate element array */ - if (num_elts <= STACK_ELTS_LEN) { + if (num_elts <= ARRAY_LENGTH (stack_elts)) { elts = stack_elts; } else { elts = _cairo_malloc_ab (num_elts, sizeof (XGlyphElt8)); @@ -2851,7 +2931,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, n = 0; } elts[nelt].chars = char8 + size * j; - elts[nelt].glyphset = font_private->glyphset; + elts[nelt].glyphset = glyphset_info->glyphset; elts[nelt].xOff = glyphs[i].p.i.x; elts[nelt].yOff = glyphs[i].p.i.y; } @@ -2877,7 +2957,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, _render_operator (op), src->src_picture, dst->dst_picture, - font_private->xrender_format, + glyphset_info->xrender_format, attributes->x_offset + elts[0].xOff, attributes->y_offset + elts[0].yOff, elts[0].xOff, elts[0].yOff, @@ -2889,8 +2969,6 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst, return CAIRO_STATUS_SUCCESS; } -#undef STACK_ELTS_LEN - static cairo_status_t _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, cairo_xlib_glyph_t *glyphs, @@ -2904,6 +2982,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_scaled_glyph_t *scaled_glyph; cairo_fixed_t x = 0, y = 0; + cairo_xlib_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info; unsigned long max_index = 0; int width = 1; @@ -2954,6 +3033,19 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, continue; } + /* Send unsent glyphs to the server */ + if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph) == NULL) { + status = _cairo_xlib_surface_add_glyph (dst->dpy, + scaled_font, + &scaled_glyph); + if (status) + return status; + } + + this_glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph); + if (!glyphset_info) + glyphset_info = this_glyphset_info; + old_width = width; /* Update max glyph index */ @@ -2969,11 +3061,20 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, /* If we will pass the max request size by adding this glyph, * flush current glyphs. Note that we account for a - * possible element being added below. */ - if (request_size + width > max_request_size - sz_xGlyphElt) { + * possible element being added below. + * + * Also flush if changing glyphsets, as Xrender limits one mask + * format per request, so we can either break up, or use a + * wide-enough mask format. We do the former. One reason to + * prefer the latter is the fact that Xserver ADDs all glyphs + * to the mask first, and then composes that to final surface, + * though it's not a big deal. + */ + if (request_size + width > max_request_size - sz_xGlyphElt || + (this_glyphset_info != glyphset_info)) { status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i, - old_width, num_elts, - scaled_font, op, src, attributes); + scaled_font, op, src, attributes, + num_elts, old_width, glyphset_info); if (status != CAIRO_STATUS_SUCCESS) return status; @@ -2986,7 +3087,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, num_elts = 0; num_out_glyphs = 0; x = y = 0; - + glyphset_info = this_glyphset_info; } /* Convert absolute glyph position to relative-to-current-point @@ -3001,16 +3102,6 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, request_size += sz_xGlyphElt; } - /* Send unsent glyphs to the server */ - if (scaled_glyph->surface_private == NULL) { - status = _cairo_xlib_surface_add_glyph (dst->dpy, - scaled_font, - &scaled_glyph); - if (status) - return status; - scaled_glyph->surface_private = (void *) 1; - } - /* adjust current-position */ x = this_x + scaled_glyph->x_advance; y = this_y + scaled_glyph->y_advance; @@ -3021,8 +3112,8 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, if (num_elts) status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs, - width, num_elts, - scaled_font, op, src, attributes); + scaled_font, op, src, attributes, + num_elts, width, glyphset_info); return status; } @@ -3116,7 +3207,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (status) goto BAIL0; } else { - cairo_rectangle_int16_t glyph_extents; + cairo_rectangle_int_t glyph_extents; status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, diff --git a/gfx/cairo/cairo/src/cairo-xlib-xrender-private.h b/gfx/cairo/cairo/src/cairo-xlib-xrender-private.h index db27c24c8e5c..11bbbebcc2b7 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-xrender-private.h +++ b/gfx/cairo/cairo/src/cairo-xlib-xrender-private.h @@ -33,12 +33,9 @@ #ifndef CAIRO_XLIB_XRENDER_PRIVATE_H #define CAIRO_XLIB_XRENDER_PRIVATE_H -#include "cairoint.h" - #if CAIRO_HAS_XLIB_XRENDER_SURFACE #include "cairo-xlib-xrender.h" -slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format); #include #include diff --git a/gfx/cairo/cairo/src/cairo-xlib-xrender.h b/gfx/cairo/cairo/src/cairo-xlib-xrender.h index f5c35dcd4685..572049d0eb72 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-xrender.h +++ b/gfx/cairo/cairo/src/cairo-xlib-xrender.h @@ -39,7 +39,7 @@ #include -#if CAIRO_HAS_XLIB_SURFACE +#if CAIRO_HAS_XLIB_XRENDER_SURFACE #include #include @@ -56,8 +56,8 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy, CAIRO_END_DECLS -#else /* CAIRO_HAS_XLIB_SURFACE */ -# error Cairo was not compiled with support for the xlib backend -#endif /* CAIRO_HAS_XLIB_SURFACE */ +#else /* CAIRO_HAS_XLIB_XRENDER_SURFACE */ +# error Cairo was not compiled with support for the xlib XRender backend +#endif /* CAIRO_HAS_XLIB_XRENDER_SURFACE */ #endif /* CAIRO_XLIB_XRENDER_H */ diff --git a/gfx/cairo/cairo/src/cairo.c b/gfx/cairo/cairo/src/cairo.c index a319792cda75..9535174c0e33 100644 --- a/gfx/cairo/cairo/src/cairo.c +++ b/gfx/cairo/cairo/src/cairo.c @@ -67,7 +67,7 @@ static const cairo_t _cairo_nil = { * a bit of a pain, but it should be easy to always catch as long as * one adds a new test case to test a trigger of the new status value. */ -#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_INDEX +#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_TEMP_FILE_ERROR /** * _cairo_error: @@ -1869,6 +1869,50 @@ cairo_close_path (cairo_t *cr) } slim_hidden_def(cairo_close_path); +/** + * cairo_path_extents: + * @cr: a cairo context + * @x1: left of the resulting extents + * @y1: top of the resulting extents + * @x2: right of the resulting extents + * @y2: bottom of the resulting extents + * + * Computes a bounding box in user-space coordinates covering the + * points on the current path. If the current path is empty, returns + * an empty rectangle ((0,0), (0,0)). Stroke parameters, fill rule, + * surface dimensions and clipping are not taken into account. + * + * Contrast with cairo_fill_extents() and cairo_stroke_extents() which + * return the extents of only the area that would be "inked" by + * the corresponding drawing operations. + * + * The result of cairo_path_extents() is defined as equivalent to the + * limit of cairo_stroke_extents() with CAIRO_LINE_CAP_ROUND as the + * line width approaches 0.0, (but never reaching the empty-rectangle + * returned by cairo_stroke_extents() for a line width of 0.0). + * + * Specifically, this means that zero-area sub-paths such as + * cairo_move_to();cairo_line_to() segments, (even degenerate cases + * where the coordinates to both calls are identical), will be + * considered as contributing to the extents. However, a lone + * cairo_move_to() will not contribute to the results of + * cairo_path_extents(). + * + * Since: 1.6 + **/ +void +cairo_path_extents (cairo_t *cr, + double *x1, double *y1, double *x2, double *y2) +{ + if (cr->status) + return; + + _cairo_gstate_path_extents (cr->gstate, + cr->path, + x1, y1, x2, y2); +} +slim_hidden_def (cairo_path_extents); + /** * cairo_paint: * @cr: a cairo context @@ -2236,10 +2280,16 @@ cairo_in_fill (cairo_t *cr, double x, double y) * @y2: bottom of the resulting extents * * Computes a bounding box in user coordinates covering the area that - * would be affected by a cairo_stroke() operation operation given the - * current path and stroke parameters. If the current path is empty, - * returns an empty rectangle (0,0, 0,0). Surface dimensions and - * clipping are not taken into account. + * would be affected, (the "inked" area), by a cairo_stroke() + * operation operation given the current path and stroke + * parameters. If the current path is empty, returns an empty + * rectangle ((0,0), (0,0)). Surface dimensions and clipping are not + * taken into account. + * + * Note that if the line width is set to exactly zero, then + * cairo_stroke_extents will return an empty rectangle. Contrast with + * cairo_path_extents() which can be used to compute the non-empty + * bounds as the line width approaches zero. * * See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(), * cairo_set_line_cap(), cairo_set_dash(), and @@ -2270,10 +2320,14 @@ cairo_stroke_extents (cairo_t *cr, * @y2: bottom of the resulting extents * * Computes a bounding box in user coordinates covering the area that - * would be affected by a cairo_fill() operation given the current path - * and fill parameters. If the current path is empty, returns an empty - * rectangle (0,0, 0,0). Surface dimensions and clipping are not taken - * into account. + * would be affected, (the "inked" area), by a cairo_fill() operation + * given the current path and fill parameters. If the current path is + * empty, returns an empty rectangle ((0,0), (0,0)). Surface + * dimensions and clipping are not taken into account. + * + * Contrast with cairo_path_extents(), which is similar, but returns + * non-zero extents for some paths no inked area, (such as a simple + * line segment). * * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve(). **/ @@ -2666,10 +2720,12 @@ cairo_set_font_options (cairo_t *cr, if (cr->status) return; - status = cairo_font_options_status ((cairo_font_options_t *) options); - if (status) { - _cairo_set_error (cr, status); - return; + if (options != NULL) { + status = cairo_font_options_status ((cairo_font_options_t *) options); + if (status) { + _cairo_set_error (cr, status); + return; + } } _cairo_gstate_set_font_options (cr->gstate, options); @@ -2812,18 +2868,18 @@ cairo_text_extents (cairo_t *cr, int num_glyphs; double x, y; + extents->x_bearing = 0.0; + extents->y_bearing = 0.0; + extents->width = 0.0; + extents->height = 0.0; + extents->x_advance = 0.0; + extents->y_advance = 0.0; + if (cr->status) return; - if (utf8 == NULL) { - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; + if (utf8 == NULL) return; - } cairo_get_current_point (cr, &x, &y); @@ -2831,14 +2887,10 @@ cairo_text_extents (cairo_t *cr, x, y, &glyphs, &num_glyphs); - if (status) { - if (glyphs) - free (glyphs); - _cairo_set_error (cr, status); - return; - } - - status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents); + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_gstate_glyph_extents (cr->gstate, + glyphs, num_glyphs, + extents); if (glyphs) free (glyphs); @@ -2872,6 +2924,13 @@ cairo_glyph_extents (cairo_t *cr, { cairo_status_t status; + extents->x_bearing = 0.0; + extents->y_bearing = 0.0; + extents->width = 0.0; + extents->height = 0.0; + extents->x_advance = 0.0; + extents->y_advance = 0.0; + if (cr->status) return; @@ -3019,6 +3078,9 @@ cairo_text_path (cairo_t *cr, const char *utf8) if (cr->status) return; + if (utf8 == NULL) + return; + cairo_get_current_point (cr, &x, &y); status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, @@ -3076,6 +3138,9 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs) if (cr->status) return; + if (num_glyphs == 0) + return; + status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs, cr->path); @@ -3317,7 +3382,7 @@ cairo_surface_t * cairo_get_target (cairo_t *cr) { if (cr->status) - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (cr->status); return _cairo_gstate_get_original_target (cr->gstate); } @@ -3326,17 +3391,19 @@ cairo_get_target (cairo_t *cr) * cairo_get_group_target: * @cr: a cairo context * - * Gets the target surface for the current group as started by the - * most recent call to cairo_push_group() or - * cairo_push_group_with_content(). + * Gets the current destination surface for the context. This is either + * the original target surface as passed to cairo_create() or the target + * surface for the current group as started by the most recent call to + * cairo_push_group() or cairo_push_group_with_content(). * - * This function will return NULL if called "outside" of any group - * rendering blocks, (that is, after the last balancing call to - * cairo_pop_group() or cairo_pop_group_to_source()). + * This function will always return a valid pointer, but the result + * can be a "nil" surface if @cr is already in an error state, + * (ie. cairo_status() != %CAIRO_STATUS_SUCCESS). + * A nil surface is indicated by cairo_surface_status() + * != %CAIRO_STATUS_SUCCESS. * - * Return value: the target group surface, or NULL if none. This - * object is owned by cairo. To keep a reference to it, you must call - * cairo_surface_reference(). + * Return value: the target surface. This object is owned by cairo. To + * keep a reference to it, you must call cairo_surface_reference(). * * Since: 1.2 **/ @@ -3344,7 +3411,7 @@ cairo_surface_t * cairo_get_group_target (cairo_t *cr) { if (cr->status) - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (cr->status); return _cairo_gstate_get_target (cr->gstate); } @@ -3551,6 +3618,8 @@ cairo_status_to_string (cairo_status_t status) return "invalid index passed to getter"; case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: return "clip region not representable in desired format"; + case CAIRO_STATUS_TEMP_FILE_ERROR: + return "error creating or writing to a temporary file"; } return ""; diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h index 65d8b361071a..157b6e1361a5 100644 --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h @@ -201,6 +201,7 @@ typedef struct _cairo_user_data_key { * @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2) * @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4) * @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4) + * @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6) * * #cairo_status_t is used to indicate errors that can occur when * using Cairo. In some cases it is returned directly by functions. @@ -233,7 +234,9 @@ typedef enum _cairo_status { CAIRO_STATUS_INVALID_DASH, CAIRO_STATUS_INVALID_DSC_COMMENT, CAIRO_STATUS_INVALID_INDEX, - CAIRO_STATUS_CLIP_NOT_REPRESENTABLE + CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, + CAIRO_STATUS_TEMP_FILE_ERROR + /* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairo.c */ } cairo_status_t; /** @@ -581,6 +584,11 @@ cairo_stroke_to_path (cairo_t *cr); cairo_public void cairo_close_path (cairo_t *cr); +cairo_public void +cairo_path_extents (cairo_t *cr, + double *x1, double *y1, + double *x2, double *y2); + /* Painting functions */ cairo_public void cairo_paint (cairo_t *cr); diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h index 5cfba110f3d1..381ca3d602c2 100644 --- a/gfx/cairo/cairo/src/cairoint.h +++ b/gfx/cairo/cairo/src/cairoint.h @@ -68,19 +68,14 @@ #include "cairo-compiler-private.h" -#ifdef _MSC_VER -#define snprintf _snprintf -#undef inline -#define inline __inline -#endif - -#ifdef __STRICT_ANSI__ -#undef inline -#define inline __inline__ -#endif - CAIRO_BEGIN_DECLS +#ifdef _WIN32 +cairo_private FILE * +_cairo_win32_tmpfile (void); +#define tmpfile() _cairo_win32_tmpfile() +#endif + #undef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -106,6 +101,10 @@ CAIRO_BEGIN_DECLS __FILE__, __LINE__, #expr); } while (0) #endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif + #undef ARRAY_LENGTH #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0]))) @@ -116,6 +115,8 @@ CAIRO_BEGIN_DECLS #define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int)) #endif +#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T)) + #define ASSERT_NOT_REACHED \ do { \ static const int NOT_REACHED = 0; \ @@ -177,152 +178,8 @@ be32_to_cpu(uint32_t v) #include "cairo-types-private.h" #include "cairo-cache-private.h" -#include "cairo-fixed-private.h" #include "cairo-reference-count-private.h" -typedef struct _cairo_region cairo_region_t; - -typedef struct _cairo_point { - cairo_fixed_t x; - cairo_fixed_t y; -} cairo_point_t; - -typedef struct _cairo_slope -{ - cairo_fixed_t dx; - cairo_fixed_t dy; -} cairo_slope_t, cairo_distance_t; - -typedef struct _cairo_point_double { - double x; - double y; -} cairo_point_double_t; - -typedef struct _cairo_distance_double { - double dx; - double dy; -} cairo_distance_double_t; - -typedef struct _cairo_line { - cairo_point_t p1; - cairo_point_t p2; -} cairo_line_t, cairo_box_t; - -typedef struct _cairo_trapezoid { - cairo_fixed_t top, bottom; - cairo_line_t left, right; -} cairo_trapezoid_t; - -typedef struct _cairo_rectangle_int16 { - int16_t x, y; - uint16_t width, height; -} cairo_rectangle_int16_t, cairo_glyph_size_t; - -typedef struct _cairo_rectangle_int32 { - int32_t x, y; - uint32_t width, height; -} cairo_rectangle_int32_t; - -typedef struct _cairo_point_int16 { - int16_t x, y; -} cairo_point_int16_t; - -typedef struct _cairo_point_int32 { - int16_t x, y; -} cairo_point_int32_t; - -typedef struct _cairo_box_int16 { - cairo_point_int16_t p1; - cairo_point_int16_t p2; -} cairo_box_int16_t; - -typedef struct _cairo_box_int32 { - cairo_point_int32_t p1; - cairo_point_int32_t p2; -} cairo_box_int32_t; - -#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16 -typedef cairo_rectangle_int16_t cairo_rectangle_int_t; -typedef cairo_point_int16_t cairo_point_int_t; -typedef cairo_box_int16_t cairo_box_int_t; -#define CAIRO_RECT_INT_MIN INT16_MIN -#define CAIRO_RECT_INT_MAX INT16_MAX -#elif CAIRO_FIXED_BITS == 32 -typedef cairo_rectangle_int32_t cairo_rectangle_int_t; -typedef cairo_point_int32_t cairo_point_int_t; -typedef cairo_box_int32_t cairo_box_int_t; -#define CAIRO_RECT_INT_MIN INT32_MIN -#define CAIRO_RECT_INT_MAX INT32_MAX -#else -#error Not sure how to pick a cairo_rectangle_int_t for your CAIRO_FIXED_BITS! -#endif - -typedef enum _cairo_direction { - CAIRO_DIRECTION_FORWARD, - CAIRO_DIRECTION_REVERSE -} cairo_direction_t; - -typedef struct _cairo_path_fixed cairo_path_fixed_t; -typedef enum _cairo_clip_mode { - CAIRO_CLIP_MODE_PATH, - CAIRO_CLIP_MODE_REGION, - CAIRO_CLIP_MODE_MASK -} cairo_clip_mode_t; -typedef struct _cairo_clip_path cairo_clip_path_t; - -typedef struct _cairo_edge { - cairo_line_t edge; - int clockWise; - - cairo_fixed_t current_x; -} cairo_edge_t; - -typedef struct _cairo_polygon { - cairo_status_t status; - - cairo_point_t first_point; - cairo_point_t current_point; - cairo_bool_t has_current_point; - - int num_edges; - int edges_size; - cairo_edge_t *edges; - cairo_edge_t edges_embedded[8]; -} cairo_polygon_t; - -typedef struct _cairo_spline_knots { - cairo_point_t a, b, c, d; -} cairo_spline_knots_t; -typedef struct _cairo_spline { - cairo_spline_knots_t knots; - - cairo_slope_t initial_slope; - cairo_slope_t final_slope; - - int num_points; - int points_size; - cairo_point_t *points; - cairo_point_t points_embedded[8]; -} cairo_spline_t; - -typedef struct _cairo_pen_vertex { - cairo_point_t point; - - cairo_slope_t slope_ccw; - cairo_slope_t slope_cw; -} cairo_pen_vertex_t; - -typedef struct _cairo_pen { - double radius; - double tolerance; - - cairo_pen_vertex_t *vertices; - int num_vertices; -} cairo_pen_t; - -typedef struct _cairo_color cairo_color_t; -typedef struct _cairo_image_surface cairo_image_surface_t; - cairo_private void _cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle); @@ -528,7 +385,7 @@ struct _cairo_scaled_font_backend { unsigned char *buffer, unsigned long *length); - void + cairo_warn cairo_int_status_t (*map_glyphs_to_unicode)(void *scaled_font, cairo_scaled_font_subset_t *font_subset); @@ -570,16 +427,6 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_ #endif -typedef struct _cairo_stroke_style { - double line_width; - cairo_line_cap_t line_cap; - cairo_line_join_t line_join; - double miter_limit; - double *dash; - unsigned int num_dashes; - double dash_offset; -} cairo_stroke_style_t; - struct _cairo_surface_backend { cairo_surface_type_t type; @@ -840,14 +687,6 @@ struct _cairo_surface_backend { cairo_antialias_t stroke_antialias); }; -typedef struct _cairo_format_masks { - int bpp; - unsigned long alpha_mask; - unsigned long red_mask; - unsigned long green_mask; - unsigned long blue_mask; -} cairo_format_masks_t; - #include "cairo-surface-private.h" struct _cairo_image_surface { @@ -887,12 +726,6 @@ struct _cairo_color { unsigned short alpha_short; }; -typedef enum { - CAIRO_STOCK_WHITE, - CAIRO_STOCK_BLACK, - CAIRO_STOCK_TRANSPARENT -} cairo_stock_t; - #define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE #define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST @@ -1014,6 +847,11 @@ typedef struct _cairo_traps { #define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT #define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_ft_scaled_font_backend +#else + +/* Paranoia: this should have been caught by configure. */ +#error No font backends are available. + #endif #define CAIRO_GSTATE_OPERATOR_DEFAULT CAIRO_OPERATOR_OVER @@ -1178,6 +1016,12 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, double *x2, double *y2, cairo_bool_t *is_tight); +cairo_private void +_cairo_gstate_path_extents (cairo_gstate_t *gstate, + cairo_path_fixed_t *path, + double *x1, double *y1, + double *x2, double *y2); + cairo_private cairo_status_t _cairo_gstate_paint (cairo_gstate_t *gstate); @@ -1423,13 +1267,6 @@ _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices); cairo_private unsigned char * _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out); -/* cairo_operator.c */ -cairo_private cairo_bool_t -_cairo_operator_always_opaque (cairo_operator_t op); - -cairo_private cairo_bool_t -_cairo_operator_always_translucent (cairo_operator_t op); - /* cairo_path.c */ cairo_private void _cairo_path_fixed_init (cairo_path_fixed_t *path); @@ -1521,9 +1358,19 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path, void *closure); cairo_private cairo_status_t +_cairo_path_fixed_interpret_flat (cairo_path_fixed_t *path, + cairo_direction_t dir, + cairo_path_fixed_move_to_func_t *move_to, + cairo_path_fixed_line_to_func_t *line_to, + cairo_path_fixed_close_path_func_t *close_path, + void *closure, + double tolerance); + +cairo_private void _cairo_path_fixed_bounds (cairo_path_fixed_t *path, double *x1, double *y1, - double *x2, double *y2); + double *x2, double *y2, + double tolerance); cairo_private void _cairo_path_fixed_device_transform (cairo_path_fixed_t *path, @@ -1578,7 +1425,7 @@ cairo_private cairo_status_t _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, - cairo_rectangle_int16_t *extents); + cairo_rectangle_int_t *extents); cairo_private cairo_status_t _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, @@ -1638,10 +1485,8 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style); /* cairo-surface.c */ -extern const cairo_private cairo_surface_t _cairo_surface_nil; -extern const cairo_private cairo_surface_t _cairo_surface_nil_read_error; -extern const cairo_private cairo_surface_t _cairo_surface_nil_write_error; -extern const cairo_private cairo_surface_t _cairo_surface_nil_file_not_found; +cairo_private cairo_surface_t * +_cairo_surface_create_in_error (cairo_status_t status); cairo_private cairo_status_t _cairo_surface_set_error (cairo_surface_t *surface, @@ -1957,6 +1802,9 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface); CAIRO_CONTENT_COLOR_ALPHA))\ == 0)) +cairo_private cairo_format_t +_cairo_format_width (cairo_format_t format); + cairo_private cairo_format_t _cairo_format_from_content (cairo_content_t content); @@ -2221,6 +2069,10 @@ _cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b); /* cairo_pattern.c */ +cairo_private cairo_status_t +_cairo_pattern_create_copy (cairo_pattern_t **pattern, + const cairo_pattern_t *other); + cairo_private cairo_status_t _cairo_pattern_init_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other); @@ -2316,11 +2168,16 @@ _cairo_utf8_to_ucs4 (const unsigned char *str, uint32_t **result, int *items_written); +#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_ATSUI_FONT+0 +# define CAIRO_HAS_UTF8_TO_UTF16 1 +#endif +#if CAIRO_HAS_UTF8_TO_UTF16 cairo_private cairo_status_t _cairo_utf8_to_utf16 (const unsigned char *str, int len, uint16_t **result, int *items_written); +#endif cairo_private cairo_status_t _cairo_error (cairo_status_t status); @@ -2373,6 +2230,7 @@ slim_hidden_proto (cairo_matrix_translate); slim_hidden_proto (cairo_move_to); slim_hidden_proto (cairo_new_path); slim_hidden_proto (cairo_paint); +slim_hidden_proto (cairo_path_extents); slim_hidden_proto (cairo_pattern_create_for_surface); slim_hidden_proto (cairo_pattern_create_rgb); slim_hidden_proto (cairo_pattern_create_rgba); @@ -2430,6 +2288,7 @@ slim_hidden_proto (cairo_surface_write_to_png_stream); CAIRO_END_DECLS #include "cairo-mutex-private.h" +#include "cairo-fixed-private.h" #include "cairo-wideint-private.h" #include "cairo-malloc-private.h" #include "cairo-hash-private.h" diff --git a/gfx/cairo/cairo/src/check-has-hidden-symbols.c b/gfx/cairo/cairo/src/check-has-hidden-symbols.c new file mode 100644 index 000000000000..12041277692a --- /dev/null +++ b/gfx/cairo/cairo/src/check-has-hidden-symbols.c @@ -0,0 +1,3 @@ +#include "cairoint.h" + +CAIRO_HAS_HIDDEN_SYMBOLS diff --git a/gfx/cairo/cairo/src/test-fallback-surface.c b/gfx/cairo/cairo/src/test-fallback-surface.c index f56db45feeb4..0bac87e010c5 100644 --- a/gfx/cairo/cairo/src/test-fallback-surface.c +++ b/gfx/cairo/cairo/src/test-fallback-surface.c @@ -76,13 +76,12 @@ _cairo_test_fallback_surface_create (cairo_content_t content, backing = _cairo_image_surface_create_with_content (content, width, height); if (cairo_surface_status (backing)) - return (cairo_surface_t*) &_cairo_surface_nil; + return backing; surface = malloc (sizeof (test_fallback_surface_t)); if (surface == NULL) { cairo_surface_destroy (backing); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } _cairo_surface_init (&surface->base, &test_fallback_surface_backend, diff --git a/gfx/cairo/cairo/src/test-meta-surface.c b/gfx/cairo/cairo/src/test-meta-surface.c index 4c08601e1b04..e56efccc6b8a 100644 --- a/gfx/cairo/cairo/src/test-meta-surface.c +++ b/gfx/cairo/cairo/src/test-meta-surface.c @@ -74,21 +74,26 @@ _cairo_test_meta_surface_create (cairo_content_t content, int height) { test_meta_surface_t *surface; + cairo_status_t status; surface = malloc (sizeof (test_meta_surface_t)); - if (surface == NULL) + if (surface == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FAIL; + } _cairo_surface_init (&surface->base, &test_meta_surface_backend, content); surface->meta = _cairo_meta_surface_create (content, width, height); - if (cairo_surface_status (surface->meta)) + status = cairo_surface_status (surface->meta); + if (status) goto FAIL_CLEANUP_SURFACE; surface->image = _cairo_image_surface_create_with_content (content, width, height); - if (cairo_surface_status (surface->image)) + status = cairo_surface_status (surface->image); + if (status) goto FAIL_CLEANUP_META; surface->image_reflects_meta = FALSE; @@ -100,8 +105,7 @@ _cairo_test_meta_surface_create (cairo_content_t content, FAIL_CLEANUP_SURFACE: free (surface); FAIL: - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); } static cairo_status_t @@ -309,7 +313,7 @@ _test_meta_surface_snapshot (void *abstract_other) status = _cairo_surface_get_extents (other->image, &extents); if (status) - return (cairo_surface_t*) &_cairo_surface_nil; + return _cairo_surface_create_in_error (status); surface = cairo_surface_create_similar (other->image, CAIRO_CONTENT_COLOR_ALPHA, @@ -319,7 +323,7 @@ _test_meta_surface_snapshot (void *abstract_other) status = _cairo_meta_surface_replay (other->meta, surface); if (status) { cairo_surface_destroy (surface); - surface = (cairo_surface_t*) &_cairo_surface_nil; + surface = _cairo_surface_create_in_error (status); } return surface; diff --git a/gfx/cairo/cairo/src/test-paginated-surface.c b/gfx/cairo/cairo/src/test-paginated-surface.c index 7d341ad78ba4..f640b606898d 100644 --- a/gfx/cairo/cairo/src/test-paginated-surface.c +++ b/gfx/cairo/cairo/src/test-paginated-surface.c @@ -77,13 +77,12 @@ _cairo_test_paginated_surface_create_for_data (unsigned char *data, stride); status = cairo_surface_status (target); if (status) - return (cairo_surface_t *) &_cairo_surface_nil; + return target; surface = malloc (sizeof (test_paginated_surface_t)); if (surface == NULL) { cairo_surface_destroy (target); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_surface_t *) &_cairo_surface_nil; + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } _cairo_surface_init (&surface->base, &test_paginated_surface_backend, diff --git a/gfx/cairo/fixed-24-8.patch b/gfx/cairo/fixed-24-8.patch new file mode 100644 index 000000000000..267d349365a5 --- /dev/null +++ b/gfx/cairo/fixed-24-8.patch @@ -0,0 +1,21 @@ +--- /Users/vladimir/proj/cairo/src/cairo-fixed-type-private.h 2008-01-22 15:20:39.000000000 -0800 ++++ cairo/src/cairo-fixed-type-private.h 2008-01-24 11:49:15.000000000 -0800 +@@ -54,17 +54,17 @@ typedef cairo_int128_t cairo_fixed_96_32 + * size of a fixed type. For now, it must be 32. + */ + #define CAIRO_FIXED_BITS 32 + + /* The number of fractional bits. Changing this involves + * making sure that you compute a double-to-fixed magic number. + * (see below). + */ +-#define CAIRO_FIXED_FRAC_BITS 16 ++#define CAIRO_FIXED_FRAC_BITS 24 + + /* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */ + typedef int32_t cairo_fixed_t; + + /* An unsigned type of the same size as cairo_fixed_t */ + typedef uint32_t cairo_fixed_unsigned_t; + + #endif /* CAIRO_FIXED_TYPE_PRIVATE_H */ diff --git a/gfx/cairo/libpixman/src/Makefile.in b/gfx/cairo/libpixman/src/Makefile.in index 599152b9d250..5b61f29c2a81 100644 --- a/gfx/cairo/libpixman/src/Makefile.in +++ b/gfx/cairo/libpixman/src/Makefile.in @@ -59,6 +59,8 @@ ifeq ($(OS_ARCH),SunOS) MODULE_OPTIMIZE_FLAGS = -xO5 endif ifeq ($(OS_ARCH),WINNT) +# FIXME: bug 413019 +OS_COMPILE_CFLAGS += -GL- MODULE_OPTIMIZE_FLAGS = -O2 endif endif diff --git a/gfx/cairo/libpixman/src/pixman-compose.c b/gfx/cairo/libpixman/src/pixman-compose.c index 4bc8163f72e9..e240850a6be6 100644 --- a/gfx/cairo/libpixman/src/pixman-compose.c +++ b/gfx/cairo/libpixman/src/pixman-compose.c @@ -124,11 +124,10 @@ SourcePictureClassify (source_image_t *pict, int offset1 = stride < 0 ? \ offset0 + ((-stride) >> 1) * ((pict->height) >> 1) : \ offset0 + (offset0 >> 2) -/* Note no trailing semicolon on the above macro; if it's there, then - * the typical usage YV12_SETUP(pict); will have an extra trailing ; - * which will be interpreted as an empty statement by some compilers - * (MSVC) -- which will then error out at any further variable - * declarations. +/* Note n trailing semicolon on the above macro; if it's there, then + * the typical usage of YV12_SETUP(pict); will have an extra trailing ; + * that some compilers will interpret as a statement -- and then any further + * variable declarations will cause an error. */ #define YV12_Y(line) \ @@ -3696,8 +3695,8 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin stride = pict->rowstride; /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2; - v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2; + v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2 - 1; + v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2 - 1; v.vector[2] = pixman_fixed_1; /* when using convolution filters one might get here without a transform */ diff --git a/gfx/cairo/libpixman/src/pixman-edge-imp.h b/gfx/cairo/libpixman/src/pixman-edge-imp.h index 2cf6d7358ee7..016bfaba7586 100644 --- a/gfx/cairo/libpixman/src/pixman-edge-imp.h +++ b/gfx/cairo/libpixman/src/pixman-edge-imp.h @@ -45,13 +45,28 @@ rasterizeEdges (pixman_image_t *image, int lxi; int rxi; - /* clip X */ lx = l->x; + rx = r->x; +#if N_BITS == 1 + /* For the non-antialiased case, round the coordinates up, in effect + * sampling the center of the pixel. (The AA case does a similar + * adjustment in RenderSamplesX) */ + lx += X_FRAC_FIRST(1); + rx += X_FRAC_FIRST(1); +#endif + /* clip X */ if (lx < 0) lx = 0; - rx = r->x; if (pixman_fixed_to_int (rx) >= width) +#if N_BITS == 1 rx = pixman_int_to_fixed (width); +#else + /* Use the last pixel of the scanline, covered 100%. + * We can't use the first pixel following the scanline, + * because accessing it could result in a buffer overrun. + */ + rx = pixman_int_to_fixed (width) - 1; +#endif /* Skip empty (or backwards) sections */ if (rx > lx) @@ -109,12 +124,7 @@ rasterizeEdges (pixman_image_t *image, AddAlpha (N_X_FRAC(N_BITS)); StepAlpha; } - /* Do not add in a 0 alpha here. This check is necessary - * to avoid a buffer overrun when rx is exactly on a pixel - * boundary. - */ - if (rxs != 0) - AddAlpha (rxs); + AddAlpha (rxs); } } #endif diff --git a/gfx/cairo/libpixman/src/pixman-edge.c b/gfx/cairo/libpixman/src/pixman-edge.c index 1ed6f10b495d..717284f7db27 100644 --- a/gfx/cairo/libpixman/src/pixman-edge.c +++ b/gfx/cairo/libpixman/src/pixman-edge.c @@ -25,7 +25,7 @@ #endif #include -#include "pixman.h" + #include "pixman-private.h" #ifdef PIXMAN_FB_ACCESSORS @@ -147,7 +147,11 @@ fbRasterizeEdges8 (pixman_image_t *image, lx = 0; rx = r->x; if (pixman_fixed_to_int (rx) >= width) - rx = pixman_int_to_fixed (width); + /* Use the last pixel of the scanline, covered 100%. + * We can't use the first pixel following the scanline, + * because accessing it could result in a buffer overrun. + */ + rx = pixman_int_to_fixed (width) - 1; /* Skip empty (or backwards) sections */ if (rx > lx) @@ -235,11 +239,7 @@ fbRasterizeEdges8 (pixman_image_t *image, add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi); } - /* Do not add in a 0 alpha here. This check is - * necessary to avoid a buffer overrun, (when rx - * is exactly on a pixel boundary). */ - if (rxs) - WRITE(image, ap + rxi, clip255 (READ(image, ap + rxi) + rxs)); + WRITE(image, ap + rxi, clip255 (READ(image, ap + rxi) + rxs)); } } diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c index 1c4abc278552..9b6846e16eca 100644 --- a/gfx/cairo/libpixman/src/pixman-image.c +++ b/gfx/cairo/libpixman/src/pixman-image.c @@ -28,7 +28,6 @@ #include #include -#include "pixman.h" #include "pixman-private.h" static void diff --git a/gfx/cairo/libpixman/src/pixman-pict.c b/gfx/cairo/libpixman/src/pixman-pict.c index f923d4b360b7..3c299b5a17dd 100644 --- a/gfx/cairo/libpixman/src/pixman-pict.c +++ b/gfx/cairo/libpixman/src/pixman-pict.c @@ -29,7 +29,7 @@ #include #include #include -#include "pixman.h" + #include "pixman-private.h" #include "pixman-mmx.h" @@ -1387,6 +1387,249 @@ pixman_image_composite_rect (pixman_op_t op, free (scanline_buffer); } +/* These "formats" both have depth 0, so they + * will never clash with any real ones + */ +#define PIXMAN_null PIXMAN_FORMAT(0,0,0,0,0,0) +#define PIXMAN_solid PIXMAN_FORMAT(0,1,0,0,0,0) + +#define NEED_COMPONENT_ALPHA (1 << 0) +#define NEED_PIXBUF (1 << 1) +#define NEED_SOLID_MASK (1 << 2) + +typedef struct +{ + pixman_op_t op; + pixman_format_code_t src_format; + pixman_format_code_t mask_format; + pixman_format_code_t dest_format; + CompositeFunc func; + uint32_t flags; +} FastPathInfo; + +#ifdef USE_MMX +static const FastPathInfo mmx_fast_paths[] = +{ + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8x0565mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8x0565mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8888x0565Cmmx, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8888x0565Cmmx, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8b8g8r8, PIXMAN_a8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8b8g8r8, PIXMAN_x8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8r8g8b8, PIXMAN_r5g6b5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8b8g8r8, PIXMAN_r5g6b5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8r8g8b8, PIXMAN_a8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8r8g8b8, PIXMAN_x8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8r8g8b8, PIXMAN_b5g6r5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8b8g8r8, PIXMAN_b5g6r5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK }, +#if 0 + /* FIXME: This code is commented out since it's apparently not actually faster than the generic code. */ + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeOver_x888x8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeOver_x888x8x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888mmx, 0 }, +#endif + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSolid_nx8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSolid_nx8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSolid_nx0565mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSrc_8888x0565mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8888mmx, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeSrc_8888x0565mmx, 0 }, + + { PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrcAdd_8888x8888mmx, 0 }, + { PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrcAdd_8888x8888mmx, 0 }, + { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeSrcAdd_8000x8000mmx, 0 }, + { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeSrcAdd_8888x8x8mmx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 }, + + { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeCopyAreammx, 0 }, + { PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeIn_8x8mmx, 0 }, + { PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeIn_nx8x8mmx, 0 }, + { PIXMAN_OP_NONE }, +}; +#endif + +static const FastPathInfo c_fast_paths[] = +{ + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8x0565, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8x0565, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r8g8b8, fbCompositeSolidMask_nx8x0888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b8g8r8, fbCompositeSolidMask_nx8x0888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8888x0565C, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8888x0565C, NEED_COMPONENT_ALPHA }, +#if 0 + /* FIXME: This code is commented out since it's apparently not actually faster than the generic code */ + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeOver_x888x8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeOver_x888x8x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888, 0 }, +#endif + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSrc_8888x0565, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeSrc_8888x0565, 0 }, +#if 0 + /* FIXME */ + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_r5g6b5, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_b5g6r5, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_r8g8b8, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_b8g8r8, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx1xn, 0 }, + { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx1xn, 0 }, +#endif + { PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrcAdd_8888x8888, 0 }, + { PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrcAdd_8888x8888, 0 }, + { PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeSrcAdd_8000x8000, 0 }, +#if 0 + /* FIXME */ + { PIXMAN_OP_ADD, PIXMAN_a1, PIXMAN_null, PIXMAN_a1, fbCompositeSrcAdd_1000x1000, 0 }, +#endif + { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeSrcAdd_8888x8x8, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSolidFill, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSolidFill, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSolidFill, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSolidFill, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8, fbCompositeSolidFill, 0 }, + { PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSolidFill, 0 }, + { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888xx888, 0 }, + { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888xx888, 0 }, + { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888xx888, 0 }, + { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888xx888, 0 }, +#if 0 + /* FIXME */ + { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrcSrc_nxn, 0 }, + { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrcSrc_nxn, 0 }, + { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrcSrc_nxn, 0 }, + { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrcSrc_nxn, 0 }, + { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSrcSrc_nxn, 0 }, + { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeSrcSrc_nxn, 0 }, +#endif + { PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeSrcIn_8x8, 0 }, + { PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeSolidMaskIn_nx8x8, 0 }, + { PIXMAN_OP_NONE }, +}; + +static pixman_bool_t +mask_is_solid (pixman_image_t *mask) +{ + if (mask->type == SOLID) + return TRUE; + + if (mask->type == BITS && + mask->common.repeat == PIXMAN_REPEAT_NORMAL && + mask->bits.width == 1 && + mask->bits.height == 1) + { + return TRUE; + } + + return FALSE; +} + +static const FastPathInfo * +get_fast_path (const FastPathInfo *fast_paths, + pixman_op_t op, + pixman_image_t *pSrc, + pixman_image_t *pMask, + pixman_image_t *pDst, + pixman_bool_t is_pixbuf) +{ + const FastPathInfo *info; + + for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++) + { + pixman_bool_t valid_src = FALSE; + pixman_bool_t valid_mask = FALSE; + + if (info->op != op) + continue; + + if ((info->src_format == PIXMAN_solid && can_get_solid (pSrc)) || + (pSrc->type == BITS && info->src_format == pSrc->bits.format)) + { + valid_src = TRUE; + } + + if (!valid_src) + continue; + + if ((info->mask_format == PIXMAN_null && !pMask) || + (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format)) + { + valid_mask = TRUE; + + if (info->flags & NEED_SOLID_MASK) + { + if (!pMask || !mask_is_solid (pMask)) + valid_mask = FALSE; + } + + if (info->flags & NEED_COMPONENT_ALPHA) + { + if (!pMask || !pMask->common.component_alpha) + valid_mask = FALSE; + } + } + + if (!valid_mask) + continue; + + if (info->dest_format != pDst->bits.format) + continue; + + if ((info->flags & NEED_PIXBUF) && !is_pixbuf) + continue; + + return info; + } + + return NULL; +} void pixman_image_composite (pixman_op_t op, @@ -1449,573 +1692,42 @@ pixman_image_composite (pixman_op_t op, && !pSrc->common.read_func && !pSrc->common.write_func && !(pMask && pMask->common.read_func) && !(pMask && pMask->common.write_func) && !pDst->common.read_func && !pDst->common.write_func) - switch (op) { - case PIXMAN_OP_OVER: - if (pMask) - { - if (can_get_solid(pSrc) && - !maskRepeat) - { - if (pSrc->type == SOLID || PIXMAN_FORMAT_COLOR(pSrc->bits.format)) { - switch (pMask->bits.format) { - case PIXMAN_a8: - switch (pDst->bits.format) { - case PIXMAN_r5g6b5: - case PIXMAN_b5g6r5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSolidMask_nx8x0565mmx; - else -#endif - func = fbCompositeSolidMask_nx8x0565; - break; - case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: - func = fbCompositeSolidMask_nx8x0888; - break; - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSolidMask_nx8x8888mmx; - else -#endif - func = fbCompositeSolidMask_nx8x8888; - break; - default: - break; - } - break; - case PIXMAN_a8r8g8b8: - if (pMask->common.component_alpha) { - switch (pDst->bits.format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSolidMask_nx8888x8888Cmmx; - else -#endif - func = fbCompositeSolidMask_nx8888x8888C; - break; - case PIXMAN_r5g6b5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSolidMask_nx8888x0565Cmmx; - else -#endif - func = fbCompositeSolidMask_nx8888x0565C; - break; - default: - break; - } - } - break; - case PIXMAN_a8b8g8r8: - if (pMask->common.component_alpha) { - switch (pDst->bits.format) { - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSolidMask_nx8888x8888Cmmx; - else -#endif - func = fbCompositeSolidMask_nx8888x8888C; - break; - case PIXMAN_b5g6r5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSolidMask_nx8888x0565Cmmx; - else -#endif - func = fbCompositeSolidMask_nx8888x0565C; - break; - default: - break; - } - } - break; - case PIXMAN_a1: - switch (pDst->bits.format) { - case PIXMAN_r5g6b5: - case PIXMAN_b5g6r5: - case PIXMAN_r8g8b8: - case PIXMAN_b8g8r8: - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: - { - uint32_t src; + { + const FastPathInfo *info; + pixman_bool_t pixbuf; -#if 0 - /* FIXME */ - fbComposeGetSolid(pSrc, src, pDst->bits.format); - if ((src & 0xff000000) == 0xff000000) - func = fbCompositeSolidMask_nx1xn; -#endif - break; - } - default: - break; - } - break; - default: - break; - } - } - if (func) - srcRepeat = FALSE; - } - else if (!srcRepeat) /* has mask and non-repeating source */ - { - if (pSrc->bits.bits == pMask->bits.bits && - xSrc == xMask && - ySrc == yMask && - !pMask->common.component_alpha && !maskRepeat) - { - /* source == mask: non-premultiplied data */ - switch (pSrc->bits.format) { - case PIXMAN_x8b8g8r8: - switch (pMask->bits.format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_a8b8g8r8: - switch (pDst->bits.format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888RevNPx8888mmx; -#endif - break; - case PIXMAN_r5g6b5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888RevNPx0565mmx; -#endif - break; - default: - break; - } - break; - default: - break; - } - break; - case PIXMAN_x8r8g8b8: - switch (pMask->bits.format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_a8b8g8r8: - switch (pDst->bits.format) { - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888RevNPx8888mmx; -#endif - break; - case PIXMAN_r5g6b5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888RevNPx0565mmx; -#endif - break; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - break; - } - else if (maskRepeat && - pMask->bits.width == 1 && - pMask->bits.height == 1) - { - switch (pSrc->bits.format) { -#ifdef USE_MMX - case PIXMAN_x8r8g8b8: - if ((pDst->bits.format == PIXMAN_a8r8g8b8 || - pDst->bits.format == PIXMAN_x8r8g8b8) && - pMask->bits.format == PIXMAN_a8 && pixman_have_mmx()) - func = fbCompositeSrc_x888xnx8888mmx; - break; - case PIXMAN_x8b8g8r8: - if ((pDst->bits.format == PIXMAN_a8b8g8r8 || - pDst->bits.format == PIXMAN_x8b8g8r8) && - pMask->bits.format == PIXMAN_a8 && pixman_have_mmx()) - func = fbCompositeSrc_x888xnx8888mmx; - break; - case PIXMAN_a8r8g8b8: - if ((pDst->bits.format == PIXMAN_a8r8g8b8 || - pDst->bits.format == PIXMAN_x8r8g8b8) && - pMask->bits.format == PIXMAN_a8 && pixman_have_mmx()) - func = fbCompositeSrc_8888x8x8888mmx; - break; - case PIXMAN_a8b8g8r8: - if ((pDst->bits.format == PIXMAN_a8b8g8r8 || - pDst->bits.format == PIXMAN_x8b8g8r8) && - pMask->bits.format == PIXMAN_a8 && pixman_have_mmx()) - func = fbCompositeSrc_8888x8x8888mmx; - break; -#endif - default: - break; - } + pixbuf = + pSrc && pSrc->type == BITS && + pMask && pMask->type == BITS && + pSrc->bits.bits == pMask->bits.bits && + xSrc == xMask && + ySrc == yMask && + !pMask->common.component_alpha && + !maskRepeat; - if (func) - maskRepeat = FALSE; - } - else - { -#if 0 - /* FIXME: This code is commented out since it's apparently not - * actually faster than the generic code. - */ - if (pMask->bits.format == PIXMAN_a8) - { - if ((pSrc->bits.format == PIXMAN_x8r8g8b8 && - (pDst->bits.format == PIXMAN_x8r8g8b8 || - pDst->bits.format == PIXMAN_a8r8g8b8)) || - (pSrc->bits.format == PIXMAN_x8b8g8r8 && - (pDst->bits.format == PIXMAN_x8b8g8r8 || - pDst->bits.format == PIXMAN_a8b8g8r8))) - { #ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeOver_x888x8x8888mmx; - else + info = NULL; + if (pixman_have_mmx()) + info = get_fast_path (mmx_fast_paths, op, pSrc, pMask, pDst, pixbuf); + if (!info) #endif - func = fbCompositeOver_x888x8x8888; - } - } -#endif - } - } - } - else /* no mask */ + info = get_fast_path (c_fast_paths, op, pSrc, pMask, pDst, pixbuf); + + if (info) { - if (can_get_solid(pSrc)) - { - /* no mask and repeating source */ - if (pSrc->type == SOLID || pSrc->bits.format == PIXMAN_a8r8g8b8) - { - switch (pDst->bits.format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: -#ifdef USE_MMX - if (pixman_have_mmx()) - { - srcRepeat = FALSE; - func = fbCompositeSolid_nx8888mmx; - } -#endif - break; - case PIXMAN_r5g6b5: -#ifdef USE_MMX - if (pixman_have_mmx()) - { - srcRepeat = FALSE; - func = fbCompositeSolid_nx0565mmx; - } -#endif - break; - default: - break; - } - break; - } - } - else if (! srcRepeat) - { - /* - * Formats without alpha bits are just Copy with Over - */ - if (pSrc->bits.format == pDst->bits.format && !PIXMAN_FORMAT_A(pSrc->bits.format)) - { -#ifdef USE_MMX - if (pixman_have_mmx() && - (pSrc->bits.format == PIXMAN_x8r8g8b8 || pSrc->bits.format == PIXMAN_x8b8g8r8)) - func = fbCompositeCopyAreammx; - else -#endif -#if 0 - /* FIXME */ - func = fbCompositeSrcSrc_nxn -#endif - ; - } - else switch (pSrc->bits.format) { - case PIXMAN_a8r8g8b8: - switch (pDst->bits.format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888x8888mmx; - else -#endif - func = fbCompositeSrc_8888x8888; - break; - case PIXMAN_r8g8b8: - func = fbCompositeSrc_8888x0888; - break; - case PIXMAN_r5g6b5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888x0565mmx; - else -#endif - func = fbCompositeSrc_8888x0565; - break; - default: - break; - } - break; - case PIXMAN_x8r8g8b8: - switch (pDst->bits.format) { - case PIXMAN_x8r8g8b8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeCopyAreammx; -#endif - break; - default: - break; - } - case PIXMAN_x8b8g8r8: - switch (pDst->bits.format) { - case PIXMAN_x8b8g8r8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeCopyAreammx; -#endif - break; - default: - break; - } - break; - case PIXMAN_a8b8g8r8: - switch (pDst->bits.format) { - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888x8888mmx; - else -#endif - func = fbCompositeSrc_8888x8888; - break; - case PIXMAN_b8g8r8: - func = fbCompositeSrc_8888x0888; - break; - case PIXMAN_b5g6r5: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrc_8888x0565mmx; - else -#endif - func = fbCompositeSrc_8888x0565; - break; - default: - break; - } - break; - default: - break; - } - } - } - break; - case PIXMAN_OP_ADD: - if (pMask == 0) - { - switch (pSrc->bits.format) { - case PIXMAN_a8r8g8b8: - switch (pDst->bits.format) { - case PIXMAN_a8r8g8b8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrcAdd_8888x8888mmx; - else -#endif - func = fbCompositeSrcAdd_8888x8888; - break; - default: - break; - } - break; - case PIXMAN_a8b8g8r8: - switch (pDst->bits.format) { - case PIXMAN_a8b8g8r8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrcAdd_8888x8888mmx; - else -#endif - func = fbCompositeSrcAdd_8888x8888; - break; - default: - break; - } - break; - case PIXMAN_a8: - switch (pDst->bits.format) { - case PIXMAN_a8: -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrcAdd_8000x8000mmx; - else -#endif - func = fbCompositeSrcAdd_8000x8000; - break; - default: - break; - } - break; - case PIXMAN_a1: - switch (pDst->bits.format) { - case PIXMAN_a1: -#if 0 - /* FIXME */ - func = fbCompositeSrcAdd_1000x1000; -#endif - break; - default: - break; - } - break; - default: - break; - } - } - else - { - if (can_get_solid (pSrc) && - pMask->bits.format == PIXMAN_a8 && - pDst->bits.format == PIXMAN_a8) - { + func = info->func; + + if (info->src_format == PIXMAN_solid) srcRepeat = FALSE; -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeSrcAdd_8888x8x8mmx; - else -#endif - func = fbCompositeSrcAdd_8888x8x8; - } - } - break; - case PIXMAN_OP_SRC: - if (pMask) - { -#ifdef USE_MMX - if (can_get_solid (pSrc)) - { - if (pMask->bits.format == PIXMAN_a8) - { - switch (pDst->bits.format) - { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: - if (pixman_have_mmx()) - { - srcRepeat = FALSE; - func = fbCompositeSolidMaskSrc_nx8x8888mmx; - } - break; - default: - break; - } - } - } -#endif - } - else - { - if (can_get_solid (pSrc)) - { - switch (pDst->bits.format) - { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - case PIXMAN_a8b8g8r8: - case PIXMAN_x8b8g8r8: - case PIXMAN_a8: - case PIXMAN_r5g6b5: - func = fbCompositeSolidFill; - srcRepeat = FALSE; - break; - default: - break; - } - } - else if (pSrc->bits.format == pDst->bits.format) - { -#ifdef USE_MMX - if (pSrc->bits.bits != pDst->bits.bits && pixman_have_mmx() && - (PIXMAN_FORMAT_BPP (pSrc->bits.format) == 16 || - PIXMAN_FORMAT_BPP (pSrc->bits.format) == 32)) - func = fbCompositeCopyAreammx; - else -#endif - /* FIXME */ -#if 0 - func = fbCompositeSrcSrc_nxn -#endif - ; - } - else if (((pSrc->bits.format == PIXMAN_a8r8g8b8 || - pSrc->bits.format == PIXMAN_x8r8g8b8) && - pDst->bits.format == PIXMAN_x8r8g8b8) || - ((pSrc->bits.format == PIXMAN_a8b8g8r8 || - pSrc->bits.format == PIXMAN_x8b8g8r8) && - pDst->bits.format == PIXMAN_x8b8g8r8)) - { - func = fbCompositeSrc_8888xx888; - } - } - break; - case PIXMAN_OP_IN: - if (pSrc->bits.format == PIXMAN_a8 && - pDst->bits.format == PIXMAN_a8 && - !pMask) - { -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeIn_8x8mmx; - else -#endif - func = fbCompositeSrcIn_8x8; - } - else if (srcRepeat && pMask && !pMask->common.component_alpha && - (pSrc->bits.format == PIXMAN_a8r8g8b8 || - pSrc->bits.format == PIXMAN_a8b8g8r8) && - (pMask->bits.format == PIXMAN_a8) && - pDst->bits.format == PIXMAN_a8) - { -#ifdef USE_MMX - if (pixman_have_mmx()) - func = fbCompositeIn_nx8x8mmx; - else -#endif - func = fbCompositeSolidMaskIn_nx8x8; - srcRepeat = FALSE; - } - break; - default: - break; - } + if (info->mask_format == PIXMAN_solid || + info->flags & NEED_SOLID_MASK) + { + maskRepeat = FALSE; + } + } + } + if ((srcRepeat && pSrc->bits.width == 1 && pSrc->bits.height == 1) || @@ -2034,7 +1746,8 @@ pixman_image_composite (pixman_op_t op, func = NULL; } - if (!func) { + if (!func) + { func = pixman_image_composite_rect; /* CompositeGeneral optimizes 1x1 repeating images itself */ diff --git a/gfx/cairo/libpixman/src/pixman-private.h b/gfx/cairo/libpixman/src/pixman-private.h index e957fd0bd188..4dd13fdfc950 100644 --- a/gfx/cairo/libpixman/src/pixman-private.h +++ b/gfx/cairo/libpixman/src/pixman-private.h @@ -29,6 +29,7 @@ # define BITMAP_BIT_ORDER LSBFirst #endif +#undef DEBUG #define DEBUG 0 #if defined (__GNUC__) @@ -41,16 +42,25 @@ #ifndef INT16_MIN # define INT16_MIN (-32767-1) +#endif + +#ifndef INT16_MAX # define INT16_MAX (32767) #endif #ifndef INT32_MIN # define INT32_MIN (-2147483647-1) +#endif + +#ifndef INT32_MAX # define INT32_MAX (2147483647) #endif #ifndef UINT32_MIN # define UINT32_MIN (0) +#endif + +#ifndef UINT32_MAX # define UINT32_MAX (4294967295U) #endif @@ -750,7 +760,7 @@ union pixman_image #define MAX_ALPHA(n) ((1 << (n)) - 1) #define N_Y_FRAC(n) ((n) == 1 ? 1 : (1 << ((n)/2)) - 1) -#define N_X_FRAC(n) ((1 << ((n)/2)) + 1) +#define N_X_FRAC(n) ((n) == 1 ? 1 : (1 << ((n)/2)) + 1) #define STEP_Y_SMALL(n) (pixman_fixed_1 / N_Y_FRAC(n)) #define STEP_Y_BIG(n) (pixman_fixed_1 - (N_Y_FRAC(n) - 1) * STEP_Y_SMALL(n)) diff --git a/gfx/cairo/libpixman/src/pixman-region.c b/gfx/cairo/libpixman/src/pixman-region.c index ac2380608144..496ce7728663 100644 --- a/gfx/cairo/libpixman/src/pixman-region.c +++ b/gfx/cairo/libpixman/src/pixman-region.c @@ -55,7 +55,6 @@ SOFTWARE. #include #include "pixman-private.h" -#include "pixman.h" typedef struct pixman_region16_point { int x, y; diff --git a/gfx/cairo/libpixman/src/pixman-remap.h b/gfx/cairo/libpixman/src/pixman-remap.h index 92a994803325..c40eab0a07a0 100644 --- a/gfx/cairo/libpixman/src/pixman-remap.h +++ b/gfx/cairo/libpixman/src/pixman-remap.h @@ -57,3 +57,5 @@ #define pixman_add_traps _moz_pixman_add_traps #define pixman_add_trapezoids _moz_pixman_add_trapezoids #define pixman_rasterize_trapezoid _moz_pixman_rasterize_trapezoid +#define pixman_transform_point_3d _moz_pixman_transform_point_3d + diff --git a/gfx/cairo/libpixman/src/pixman-utils.c b/gfx/cairo/libpixman/src/pixman-utils.c index 103a0a9b888a..73c1cdea3fdf 100644 --- a/gfx/cairo/libpixman/src/pixman-utils.c +++ b/gfx/cairo/libpixman/src/pixman-utils.c @@ -26,7 +26,7 @@ #endif #include -#include "pixman.h" + #include "pixman-private.h" #include "pixman-mmx.h" diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index 604e4a8023b6..2965acdcb311 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -90,6 +90,13 @@ typedef unsigned __int64 uint64_t; # include #endif +/* GCC visibility */ +#if defined(__GNUC__) && __GNUC__ >= 4 +#define PIXMAN_EXPORT __attribute__ ((visibility("default"))) +#else +#define PIXMAN_EXPORT +#endif + /* * Boolean */ @@ -158,6 +165,7 @@ struct pixman_transform pixman_fixed_t matrix[3][3]; }; +PIXMAN_EXPORT pixman_bool_t pixman_transform_point_3d (pixman_transform_t *transform, pixman_vector_t *vector); @@ -221,7 +229,9 @@ typedef enum PIXMAN_OP_CONJOINT_OUT_REVERSE = 0x28, PIXMAN_OP_CONJOINT_ATOP = 0x29, PIXMAN_OP_CONJOINT_ATOP_REVERSE = 0x2a, - PIXMAN_OP_CONJOINT_XOR = 0x2b + PIXMAN_OP_CONJOINT_XOR = 0x2b, + + PIXMAN_OP_NONE } pixman_op_t; /* @@ -265,62 +275,85 @@ typedef enum /* This function exists only to make it possible to preserve the X ABI - it should * go away at first opportunity. */ +PIXMAN_EXPORT void pixman_region_set_static_pointers (pixman_box16_t *empty_box, pixman_region16_data_t *empty_data, pixman_region16_data_t *broken_data); /* creation/destruction */ +PIXMAN_EXPORT void pixman_region_init (pixman_region16_t *region); +PIXMAN_EXPORT void pixman_region_init_rect (pixman_region16_t *region, int x, int y, unsigned int width, unsigned int height); +PIXMAN_EXPORT void pixman_region_init_with_extents (pixman_region16_t *region, pixman_box16_t *extents); +PIXMAN_EXPORT void pixman_region_fini (pixman_region16_t *region); /* manipulation */ +PIXMAN_EXPORT void pixman_region_translate (pixman_region16_t *region, int x, int y); +PIXMAN_EXPORT pixman_bool_t pixman_region_copy (pixman_region16_t *dest, pixman_region16_t *source); +PIXMAN_EXPORT pixman_bool_t pixman_region_intersect (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_region16_t *reg2); +PIXMAN_EXPORT pixman_bool_t pixman_region_union (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_region16_t *reg2); +PIXMAN_EXPORT pixman_bool_t pixman_region_union_rect (pixman_region16_t *dest, pixman_region16_t *source, int x, int y, unsigned int width, unsigned int height); +PIXMAN_EXPORT pixman_bool_t pixman_region_subtract (pixman_region16_t *regD, pixman_region16_t *regM, pixman_region16_t *regS); +PIXMAN_EXPORT pixman_bool_t pixman_region_inverse (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_box16_t *invRect); +PIXMAN_EXPORT pixman_bool_t pixman_region_contains_point (pixman_region16_t *region, int x, int y, pixman_box16_t *box); +PIXMAN_EXPORT pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *pixman_region16_t, pixman_box16_t *prect); +PIXMAN_EXPORT pixman_bool_t pixman_region_not_empty (pixman_region16_t *region); +PIXMAN_EXPORT pixman_box16_t * pixman_region_extents (pixman_region16_t *region); +PIXMAN_EXPORT int pixman_region_n_rects (pixman_region16_t *region); +PIXMAN_EXPORT pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region, int *n_rects); +PIXMAN_EXPORT pixman_bool_t pixman_region_equal (pixman_region16_t *region1, pixman_region16_t *region2); +PIXMAN_EXPORT pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region); +PIXMAN_EXPORT void pixman_region_reset (pixman_region16_t *region, pixman_box16_t *box); +PIXMAN_EXPORT pixman_bool_t pixman_region_init_rects (pixman_region16_t *region, pixman_box16_t *boxes, int count); /* Copy / Fill */ +PIXMAN_EXPORT pixman_bool_t pixman_blt (uint32_t *src_bits, uint32_t *dst_bits, int src_stride, @@ -330,6 +363,7 @@ pixman_bool_t pixman_blt (uint32_t *src_bits, int src_x, int src_y, int dst_x, int dst_y, int width, int height); +PIXMAN_EXPORT pixman_bool_t pixman_fill (uint32_t *bits, int stride, int bpp, @@ -337,7 +371,7 @@ pixman_bool_t pixman_fill (uint32_t *bits, int y, int width, int height, - uint32_t xor); + uint32_t _xor); /* * Images */ @@ -458,25 +492,30 @@ typedef enum { /* YUV formats */ PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0), - PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0) + PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0), } pixman_format_code_t; /* Constructors */ +PIXMAN_EXPORT pixman_image_t *pixman_image_create_solid_fill (pixman_color_t *color); +PIXMAN_EXPORT pixman_image_t *pixman_image_create_linear_gradient (pixman_point_fixed_t *p1, pixman_point_fixed_t *p2, const pixman_gradient_stop_t *stops, int n_stops); +PIXMAN_EXPORT pixman_image_t *pixman_image_create_radial_gradient (pixman_point_fixed_t *inner, pixman_point_fixed_t *outer, pixman_fixed_t inner_radius, pixman_fixed_t outer_radius, const pixman_gradient_stop_t *stops, int n_stops); +PIXMAN_EXPORT pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t *center, pixman_fixed_t angle, const pixman_gradient_stop_t *stops, int n_stops); +PIXMAN_EXPORT pixman_image_t *pixman_image_create_bits (pixman_format_code_t format, int width, int height, @@ -484,44 +523,63 @@ pixman_image_t *pixman_image_create_bits (pixman_format_code_t int rowstride_bytes); /* Destructor */ +PIXMAN_EXPORT pixman_image_t *pixman_image_ref (pixman_image_t *image); +PIXMAN_EXPORT pixman_bool_t pixman_image_unref (pixman_image_t *image); /* Set properties */ +PIXMAN_EXPORT pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image, pixman_region16_t *region); +PIXMAN_EXPORT void pixman_image_set_has_client_clip (pixman_image_t *image, pixman_bool_t clien_clip); +PIXMAN_EXPORT pixman_bool_t pixman_image_set_transform (pixman_image_t *image, const pixman_transform_t *transform); +PIXMAN_EXPORT void pixman_image_set_repeat (pixman_image_t *image, pixman_repeat_t repeat); +PIXMAN_EXPORT pixman_bool_t pixman_image_set_filter (pixman_image_t *image, pixman_filter_t filter, const pixman_fixed_t *filter_params, int n_filter_params); +PIXMAN_EXPORT void pixman_image_set_filter_params (pixman_image_t *image, pixman_fixed_t *params, int n_params); +PIXMAN_EXPORT void pixman_image_set_source_clipping (pixman_image_t *image, pixman_bool_t source_clipping); +PIXMAN_EXPORT void pixman_image_set_alpha_map (pixman_image_t *image, pixman_image_t *alpha_map, int16_t x, int16_t y); +PIXMAN_EXPORT void pixman_image_set_component_alpha (pixman_image_t *image, pixman_bool_t component_alpha); +PIXMAN_EXPORT void pixman_image_set_accessors (pixman_image_t *image, pixman_read_memory_func_t read_func, pixman_write_memory_func_t write_func); +PIXMAN_EXPORT void pixman_image_set_indexed (pixman_image_t *image, const pixman_indexed_t *indexed); +PIXMAN_EXPORT uint32_t *pixman_image_get_data (pixman_image_t *image); +PIXMAN_EXPORT int pixman_image_get_width (pixman_image_t *image); +PIXMAN_EXPORT int pixman_image_get_height (pixman_image_t *image); +PIXMAN_EXPORT int pixman_image_get_stride (pixman_image_t *image); +PIXMAN_EXPORT int pixman_image_get_depth (pixman_image_t *image); +PIXMAN_EXPORT pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, pixman_image_t *image, pixman_color_t *color, @@ -529,6 +587,7 @@ pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, const pixman_rectangle16_t *rects); /* Composite */ +PIXMAN_EXPORT pixman_bool_t pixman_compute_composite_region (pixman_region16_t * pRegion, pixman_image_t * pSrc, pixman_image_t * pMask, @@ -541,6 +600,7 @@ pixman_bool_t pixman_compute_composite_region (pixman_region16_t * pRegion, int16_t yDst, uint16_t width, uint16_t height); +PIXMAN_EXPORT void pixman_image_composite (pixman_op_t op, pixman_image_t *src, pixman_image_t *mask, @@ -605,12 +665,16 @@ struct pixman_trap pixman_span_fix_t top, bot; }; +PIXMAN_EXPORT pixman_fixed_t pixman_sample_ceil_y (pixman_fixed_t y, int bpp); +PIXMAN_EXPORT pixman_fixed_t pixman_sample_floor_y (pixman_fixed_t y, int bpp); +PIXMAN_EXPORT void pixman_edge_step (pixman_edge_t *e, int n); +PIXMAN_EXPORT void pixman_edge_init (pixman_edge_t *e, int bpp, pixman_fixed_t y_start, @@ -618,31 +682,35 @@ void pixman_edge_init (pixman_edge_t *e, pixman_fixed_t y_top, pixman_fixed_t x_bot, pixman_fixed_t y_bot); +PIXMAN_EXPORT void pixman_line_fixed_edge_init (pixman_edge_t *e, int bpp, pixman_fixed_t y, const pixman_line_fixed_t *line, int x_off, int y_off); +PIXMAN_EXPORT void pixman_rasterize_edges (pixman_image_t *image, pixman_edge_t *l, pixman_edge_t *r, pixman_fixed_t t, pixman_fixed_t b); +PIXMAN_EXPORT void pixman_add_traps (pixman_image_t *image, int16_t x_off, int16_t y_off, int ntrap, pixman_trap_t *traps); +PIXMAN_EXPORT void pixman_add_trapezoids (pixman_image_t *image, int16_t x_off, int y_off, int ntraps, const pixman_trapezoid_t *traps); +PIXMAN_EXPORT void pixman_rasterize_trapezoid (pixman_image_t *image, const pixman_trapezoid_t *trap, int x_off, int y_off); - #endif /* PIXMAN_H__ */ diff --git a/gfx/cairo/max-font-size.patch b/gfx/cairo/max-font-size.patch index 7b563a8ce3c0..465668407326 100644 --- a/gfx/cairo/max-font-size.patch +++ b/gfx/cairo/max-font-size.patch @@ -1,7 +1,7 @@ diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 59a5acb..8851387 100644 ---- a/src/cairo-ft-font.c -+++ b/src/cairo-ft-font.c +--- a/cairo/src/cairo-ft-font.c ++++ b/cairo/src/cairo-ft-font.c @@ -62,6 +62,10 @@ */ #define MAX_OPEN_FACES 10 diff --git a/gfx/cairo/nonfatal-assertions.patch b/gfx/cairo/nonfatal-assertions.patch index dcbb904abd26..1e7363b7c25f 100644 --- a/gfx/cairo/nonfatal-assertions.patch +++ b/gfx/cairo/nonfatal-assertions.patch @@ -1,6 +1,6 @@ diff -r b79d47dad1ea gfx/cairo/cairo/src/cairoint.h ---- a/gfx/cairo/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700 -+++ b/gfx/cairo/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200 +--- a/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700 ++++ b/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200 @@ -159,6 +159,13 @@ CAIRO_BEGIN_DECLS #ifndef M_PI diff --git a/gfx/cairo/quartz-get-image-surface.patch b/gfx/cairo/quartz-get-image-surface.patch new file mode 100644 index 000000000000..edc3953d8ed3 --- /dev/null +++ b/gfx/cairo/quartz-get-image-surface.patch @@ -0,0 +1,486 @@ +? gfx/cairo/quartz-get-image-surface.patch +Index: gfx/cairo/README +=================================================================== +RCS file: /cvsroot/mozilla/gfx/cairo/README,v +retrieving revision 1.70 +diff -u -p -8 -r1.70 README +--- gfx/cairo/README 26 Jan 2008 00:25:22 -0000 1.70 ++++ gfx/cairo/README 27 Jan 2008 23:52:34 -0000 +@@ -23,8 +23,10 @@ max-font-size.patch: Clamp freetype font + + win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1 + + nonfatal-assertions.patch: Make assertions non-fatal + + endian.patch: include cairo-platform.h for endian macros + + fixed-24-8.patch: Switch fixed point mode from 16.16 to 24.8 ++ ++quartz-get-image-surface.patch: Add cairo_quartz_get_image_surface API analogous to the win32 one +Index: gfx/cairo/cairo/src/cairo-quartz-private.h +=================================================================== +RCS file: /cvsroot/mozilla/gfx/cairo/cairo/src/cairo-quartz-private.h,v +retrieving revision 1.19 +diff -u -p -8 -r1.19 cairo-quartz-private.h +--- gfx/cairo/cairo/src/cairo-quartz-private.h 8 Dec 2007 07:09:15 -0000 1.19 ++++ gfx/cairo/cairo/src/cairo-quartz-private.h 27 Jan 2008 23:52:34 -0000 +@@ -43,16 +43,18 @@ + #ifdef CAIRO_HAS_QUARTZ_SURFACE + #include + + typedef struct cairo_quartz_surface { + cairo_surface_t base; + + void *imageData; + ++ cairo_surface_t *imageSurfaceEquiv; ++ + CGContextRef cgContext; + CGAffineTransform cgContextBaseCTM; + + cairo_rectangle_int_t extents; + + /* These are stored while drawing operations are in place, set up + * by quartz_setup_source() and quartz_finish_source() + */ +Index: gfx/cairo/cairo/src/cairo-quartz-surface.c +=================================================================== +RCS file: /cvsroot/mozilla/gfx/cairo/cairo/src/cairo-quartz-surface.c,v +retrieving revision 1.37 +diff -u -p -8 -r1.37 cairo-quartz-surface.c +--- gfx/cairo/cairo/src/cairo-quartz-surface.c 26 Jan 2008 00:25:15 -0000 1.37 ++++ gfx/cairo/cairo/src/cairo-quartz-surface.c 27 Jan 2008 23:52:35 -0000 +@@ -890,24 +890,30 @@ _cairo_quartz_get_image (cairo_quartz_su + unsigned char *imageData; + cairo_image_surface_t *isurf; + + if (IS_EMPTY(surface)) { + *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); + return CAIRO_STATUS_SUCCESS; + } + ++ if (surface->imageSurfaceEquiv) { ++ *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv); ++ return CAIRO_STATUS_SUCCESS; ++ } ++ + if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) { + unsigned int stride; + unsigned int bitinfo; + unsigned int bpc, bpp; + CGColorSpaceRef colorspace; + unsigned int color_comps; + + imageData = (unsigned char *) CGBitmapContextGetData(surface->cgContext); ++ + #ifdef USE_10_3_WORKAROUNDS + bitinfo = CGBitmapContextGetAlphaInfo (surface->cgContext); + #else + bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext); + #endif + stride = CGBitmapContextGetBytesPerRow (surface->cgContext); + bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext); + bpc = CGBitmapContextGetBitsPerComponent (surface->cgContext); +@@ -982,16 +988,21 @@ _cairo_quartz_surface_finish (void *abst + + /* Restore our saved gstate that we use to reset clipping */ + CGContextRestoreGState (surface->cgContext); + + CGContextRelease (surface->cgContext); + + surface->cgContext = NULL; + ++ if (surface->imageSurfaceEquiv) { ++ cairo_surface_destroy (surface->imageSurfaceEquiv); ++ surface->imageSurfaceEquiv = NULL; ++ } ++ + if (surface->imageData) { + free (surface->imageData); + surface->imageData = NULL; + } + + return CAIRO_STATUS_SUCCESS; + } + +@@ -1856,16 +1867,17 @@ _cairo_quartz_surface_create_internal (C + * required for proper behaviour of intersect_clip_path(NULL) + */ + CGContextSaveGState (cgContext); + + surface->cgContext = cgContext; + surface->cgContextBaseCTM = CGContextGetCTM (cgContext); + + surface->imageData = NULL; ++ surface->imageSurfaceEquiv = NULL; + + return surface; + } + + /** + * cairo_quartz_surface_create_for_cg_context + * @cgContext: the existing CGContext for which to create the surface + * @width: width of the surface, in pixels +@@ -2010,16 +2022,17 @@ cairo_quartz_surface_create (cairo_forma + if (surf->base.status) { + CGContextRelease (cgc); + free (imageData); + // create_internal will have set an error + return (cairo_surface_t*) surf; + } + + surf->imageData = imageData; ++ surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride); + + return (cairo_surface_t *) surf; + } + + /** + * cairo_quartz_surface_get_cg_context + * @surface: the Cairo Quartz surface + * +@@ -2137,8 +2150,19 @@ quartz_surface_to_png (cairo_quartz_surf + } + + ExportCGImageToPNGFile(imgref, dest); + + CGImageRelease(imgref); + #endif + } + ++cairo_surface_t * ++cairo_quartz_surface_get_image (cairo_surface_t *surface) ++{ ++ cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t*)surface; ++ ++ if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_QUARTZ) ++ return NULL; ++ ++ return quartz->imageSurfaceEquiv; ++} ++ +Index: gfx/cairo/cairo/src/cairo-quartz.h +=================================================================== +RCS file: /cvsroot/mozilla/gfx/cairo/cairo/src/cairo-quartz.h,v +retrieving revision 1.11 +diff -u -p -8 -r1.11 cairo-quartz.h +--- gfx/cairo/cairo/src/cairo-quartz.h 4 Apr 2007 01:09:15 -0000 1.11 ++++ gfx/cairo/cairo/src/cairo-quartz.h 27 Jan 2008 23:52:35 -0000 +@@ -52,15 +52,18 @@ cairo_quartz_surface_create (cairo_forma + cairo_public cairo_surface_t * + cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, + unsigned int width, + unsigned int height); + + cairo_public CGContextRef + cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); + ++cairo_public cairo_surface_t * ++cairo_quartz_surface_get_image (cairo_surface_t *surface); ++ + CAIRO_END_DECLS + + #else /* CAIRO_HAS_QUARTZ_SURFACE */ + # error Cairo was not compiled with support for the quartz backend + #endif /* CAIRO_HAS_QUARTZ_SURFACE */ + + #endif /* CAIRO_QUARTZ_H */ +Index: gfx/cairo/cairo/src/cairo-rename.h +=================================================================== +RCS file: /cvsroot/mozilla/gfx/cairo/cairo/src/cairo-rename.h,v +retrieving revision 1.21 +diff -u -p -8 -r1.21 cairo-rename.h +--- gfx/cairo/cairo/src/cairo-rename.h 26 Jan 2008 00:25:15 -0000 1.21 ++++ gfx/cairo/cairo/src/cairo-rename.h 27 Jan 2008 23:52:35 -0000 +@@ -164,16 +164,17 @@ + #define cairo_ps_surface_restrict_to_level _moz_cairo_ps_surface_restrict_to_level + #define cairo_ps_surface_set_eps _moz_cairo_ps_surface_set_eps + #define cairo_ps_surface_set_size _moz_cairo_ps_surface_set_size + #define cairo_push_group _moz_cairo_push_group + #define cairo_push_group_with_content _moz_cairo_push_group_with_content + #define cairo_quartz_surface_create _moz_cairo_quartz_surface_create + #define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context + #define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context ++#define cairo_quartz_surface_get_image _moz_cairo_quartz_surface_get_image + #define cairo_rectangle _moz_cairo_rectangle + #define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy + #define cairo_reference _moz_cairo_reference + #define cairo_rel_curve_to _moz_cairo_rel_curve_to + #define cairo_rel_line_to _moz_cairo_rel_line_to + #define cairo_rel_move_to _moz_cairo_rel_move_to + #define cairo_reset_clip _moz_cairo_reset_clip + #define cairo_restore _moz_cairo_restore +Index: gfx/src/thebes/nsThebesImage.cpp +=================================================================== +RCS file: /cvsroot/mozilla/gfx/src/thebes/nsThebesImage.cpp,v +retrieving revision 1.57 +diff -u -p -8 -r1.57 nsThebesImage.cpp +--- gfx/src/thebes/nsThebesImage.cpp 10 Jan 2008 22:13:13 -0000 1.57 ++++ gfx/src/thebes/nsThebesImage.cpp 27 Jan 2008 23:52:35 -0000 +@@ -106,33 +106,42 @@ nsThebesImage::Init(PRInt32 aWidth, PRIn + default: + format = gfxImageSurface::ImageFormatRGB24; + mAlphaDepth = 0; + break; + } + + mFormat = format; + +-#ifdef XP_WIN ++#if defined(XP_WIN) + if (!ShouldUseImageSurfaces()) { + mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format); + if (mWinSurface && mWinSurface->CairoStatus() == 0) { + // no error + mImageSurface = mWinSurface->GetImageSurface(); + } + } + +- if (!mImageSurface) { ++ if (!mImageSurface) + mWinSurface = nsnull; +- mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format); ++#elif defined(XP_MACOSX) ++ if (!ShouldUseImageSurfaces()) { ++ mQuartzSurface = new gfxQuartzSurface(gfxSize(mWidth, mHeight), format); ++ if (mQuartzSurface && mQuartzSurface->CairoStatus() == 0) { ++ mImageSurface = mQuartzSurface->GetImageSurface(); ++ } + } +-#else +- mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format); ++ ++ if (!mImageSurface) ++ mQuartzSurface = nsnull; + #endif + ++ if (!mImageSurface) ++ mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format); ++ + if (!mImageSurface || mImageSurface->CairoStatus()) { + mImageSurface = nsnull; + // guess + return NS_ERROR_OUT_OF_MEMORY; + } + + mStride = mImageSurface->Stride(); + +@@ -293,24 +302,32 @@ nsThebesImage::Optimize(nsIDeviceContext + } + if (!mOptSurface && !mFormatChanged) { + // just use the DIB if the format has not changed + mOptSurface = mWinSurface; + } + } + #endif + ++#ifdef XP_MACOSX ++ if (mQuartzSurface && !mFormatChanged) ++ mOptSurface = mQuartzSurface; ++#endif ++ + if (mOptSurface == nsnull) + mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat); + + if (mOptSurface) { + mImageSurface = nsnull; + #ifdef XP_WIN + mWinSurface = nsnull; + #endif ++#ifdef XP_MACOSX ++ mQuartzSurface = nsnull; ++#endif + } + + return NS_OK; + } + + nsColorMap * + nsThebesImage::GetColorMap() + { +Index: gfx/src/thebes/nsThebesImage.h +=================================================================== +RCS file: /cvsroot/mozilla/gfx/src/thebes/nsThebesImage.h,v +retrieving revision 1.17 +diff -u -p -8 -r1.17 nsThebesImage.h +--- gfx/src/thebes/nsThebesImage.h 27 Nov 2007 09:35:18 -0000 1.17 ++++ gfx/src/thebes/nsThebesImage.h 27 Jan 2008 23:52:35 -0000 +@@ -39,18 +39,20 @@ + #ifndef _NSTHEBESIMAGE_H_ + #define _NSTHEBESIMAGE_H_ + + #include "nsIImage.h" + + #include "gfxColor.h" + #include "gfxASurface.h" + #include "gfxImageSurface.h" +-#ifdef XP_WIN ++#if defined(XP_WIN) + #include "gfxWindowsSurface.h" ++#elif defined(XP_MACOSX) ++#include "gfxQuartzSurface.h" + #endif + + class nsThebesImage : public nsIImage + { + public: + nsThebesImage(); + ~nsThebesImage(); + +@@ -92,17 +94,23 @@ public: + *aSurface = ThebesSurface(); + NS_ADDREF(*aSurface); + return NS_OK; + } + + gfxASurface* ThebesSurface() { + if (mOptSurface) + return mOptSurface; +- ++#if defined(XP_WIN) ++ if (mWinSurface) ++ return mWinSurface; ++#elif defined(XP_MACOSX) ++ if (mQuartzSurface) ++ return mQuartzSurface; ++#endif + return mImageSurface; + } + + void SetHasNoAlpha(); + + protected: + static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight) { + NS_ASSERTION(aWidth > 0, "invalid image width"); +@@ -146,18 +154,20 @@ protected: + #ifdef XP_WIN + PRPackedBool mIsDDBSurface; + #endif + + gfxRGBA mSinglePixelColor; + + nsRefPtr mImageSurface; + nsRefPtr mOptSurface; +-#ifdef XP_WIN ++#if defined(XP_WIN) + nsRefPtr mWinSurface; ++#elif defined(XP_MACOSX) ++ nsRefPtr mQuartzSurface; + #endif + + PRUint8 mAlphaDepth; + + // this function should return true if + // we should (temporarily) not allocate any + // platform native surfaces and instead use + // image surfaces for everything. +Index: gfx/thebes/public/gfxQuartzSurface.h +=================================================================== +RCS file: /cvsroot/mozilla/gfx/thebes/public/gfxQuartzSurface.h,v +retrieving revision 1.11 +diff -u -p -8 -r1.11 gfxQuartzSurface.h +--- gfx/thebes/public/gfxQuartzSurface.h 7 Jan 2008 00:50:18 -0000 1.11 ++++ gfx/thebes/public/gfxQuartzSurface.h 27 Jan 2008 23:52:36 -0000 +@@ -35,16 +35,17 @@ + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + #ifndef GFX_QUARTZSURFACE_H + #define GFX_QUARTZSURFACE_H + + #include "gfxASurface.h" ++#include "gfxImageSurface.h" + + #include + + class THEBES_API gfxQuartzSurface : public gfxASurface { + public: + gfxQuartzSurface(const gfxSize& size, gfxImageFormat format, PRBool aForPrinting = PR_FALSE); + gfxQuartzSurface(CGContextRef context, const gfxSize& size, PRBool aForPrinting = PR_FALSE); + gfxQuartzSurface(cairo_surface_t *csurf, PRBool aForPrinting = PR_FALSE); +@@ -52,15 +53,17 @@ public: + virtual ~gfxQuartzSurface(); + + const gfxSize& GetSize() const { return mSize; } + + CGContextRef GetCGContext() { return mCGContext; } + + virtual PRInt32 GetDefaultContextFlags() const; + ++ already_AddRefed GetImageSurface(); ++ + protected: + CGContextRef mCGContext; + gfxSize mSize; + PRPackedBool mForPrinting; + }; + + #endif /* GFX_QUARTZSURFACE_H */ +Index: gfx/thebes/src/gfxQuartzSurface.cpp +=================================================================== +RCS file: /cvsroot/mozilla/gfx/thebes/src/gfxQuartzSurface.cpp,v +retrieving revision 1.12 +diff -u -p -8 -r1.12 gfxQuartzSurface.cpp +--- gfx/thebes/src/gfxQuartzSurface.cpp 7 Jan 2008 00:50:18 -0000 1.12 ++++ gfx/thebes/src/gfxQuartzSurface.cpp 27 Jan 2008 23:52:36 -0000 +@@ -89,8 +89,28 @@ PRInt32 gfxQuartzSurface::GetDefaultCont + + return 0; + } + + gfxQuartzSurface::~gfxQuartzSurface() + { + CGContextRelease(mCGContext); + } ++ ++already_AddRefed ++gfxQuartzSurface::GetImageSurface() ++{ ++ if (!mSurfaceValid) { ++ NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?"); ++ return nsnull; ++ } ++ ++ NS_ASSERTION(CairoSurface() != nsnull, "CairoSurface() shouldn't be nsnull when mSurfaceValid is TRUE!"); ++ ++ cairo_surface_t *isurf = cairo_quartz_surface_get_image(CairoSurface()); ++ if (!isurf) ++ return nsnull; ++ ++ nsRefPtr asurf = gfxASurface::Wrap(isurf); ++ gfxImageSurface *imgsurf = (gfxImageSurface*) asurf.get(); ++ NS_ADDREF(imgsurf); ++ return imgsurf; ++} +Index: gfx/thebes/src/gfxWindowsSurface.cpp +=================================================================== +RCS file: /cvsroot/mozilla/gfx/thebes/src/gfxWindowsSurface.cpp,v +retrieving revision 1.32 +diff -u -p -8 -r1.32 gfxWindowsSurface.cpp +--- gfx/thebes/src/gfxWindowsSurface.cpp 7 Jan 2008 00:50:18 -0000 1.32 ++++ gfx/thebes/src/gfxWindowsSurface.cpp 27 Jan 2008 23:52:36 -0000 +@@ -120,16 +120,23 @@ gfxWindowsSurface::~gfxWindowsSurface() + else + ::DeleteDC(mDC); + } + } + + already_AddRefed + gfxWindowsSurface::GetImageSurface() + { ++ if (!mSurfaceValid) { ++ NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?"); ++ return nsnull; ++ } ++ ++ NS_ASSERTION(CairoSurface() != nsnull, "CairoSurface() shouldn't be nsnull when mSurfaceValid is TRUE!"); ++ + if (mForPrinting) + return nsnull; + + cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface()); + if (!isurf) + return nsnull; + + nsRefPtr asurf = gfxASurface::Wrap(isurf); diff --git a/gfx/src/nsRect.cpp b/gfx/src/nsRect.cpp index 47e2f62d1a7e..3dce71e45b12 100644 --- a/gfx/src/nsRect.cpp +++ b/gfx/src/nsRect.cpp @@ -39,19 +39,6 @@ #include "nsString.h" #include "nsIDeviceContext.h" -#ifdef MIN -#undef MIN -#endif - -#ifdef MAX -#undef MAX -#endif - -#define MIN(a,b)\ - ((a) < (b) ? (a) : (b)) -#define MAX(a,b)\ - ((a) > (b) ? (a) : (b)) - // Containment PRBool nsRect::Contains(nscoord aX, nscoord aY) const { @@ -85,11 +72,11 @@ PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2) nscoord ymost2 = aRect2.YMost(); nscoord temp; - x = MAX(aRect1.x, aRect2.x); - y = MAX(aRect1.y, aRect2.y); + x = PR_MAX(aRect1.x, aRect2.x); + y = PR_MAX(aRect1.y, aRect2.y); // Compute the destination width - temp = MIN(xmost1, xmost2); + temp = PR_MIN(xmost1, xmost2); if (temp <= x) { Empty(); return PR_FALSE; @@ -97,7 +84,7 @@ PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2) width = temp - x; // Compute the destination height - temp = MIN(ymost1, ymost2); + temp = PR_MIN(ymost1, ymost2); if (temp <= y) { Empty(); return PR_FALSE; @@ -134,12 +121,12 @@ PRBool nsRect::UnionRect(const nsRect &aRect1, const nsRect &aRect2) nscoord ymost2 = aRect2.YMost(); // Compute the origin - x = MIN(aRect1.x, aRect2.x); - y = MIN(aRect1.y, aRect2.y); + x = PR_MIN(aRect1.x, aRect2.x); + y = PR_MIN(aRect1.y, aRect2.y); // Compute the size - width = MAX(xmost1, xmost2) - x; - height = MAX(ymost1, ymost2) - y; + width = PR_MAX(xmost1, xmost2) - x; + height = PR_MAX(ymost1, ymost2) - y; } return result; @@ -168,8 +155,8 @@ void nsRect::Deflate(nscoord aDx, nscoord aDy) { x += aDx; y += aDy; - width -= 2 * aDx; - height -= 2 * aDy; + width = PR_MAX(0, width - 2 * aDx); + height = PR_MAX(0, height - 2 * aDy); } // Deflate the rect by the specified margin @@ -177,8 +164,8 @@ void nsRect::Deflate(const nsMargin &aMargin) { x += aMargin.left; y += aMargin.top; - width -= aMargin.left + aMargin.right; - height -= aMargin.top + aMargin.bottom; + width = PR_MAX(0, width - aMargin.LeftRight()); + height = PR_MAX(0, height - aMargin.TopBottom()); } // scale the rect but round to smallest containing rect @@ -252,11 +239,11 @@ PRBool nsIntRect::IntersectRect(const nsIntRect &aRect1, const nsIntRect &aRect2 PRInt32 ymost2 = aRect2.YMost(); PRInt32 temp; - x = MAX(aRect1.x, aRect2.x); - y = MAX(aRect1.y, aRect2.y); + x = PR_MAX(aRect1.x, aRect2.x); + y = PR_MAX(aRect1.y, aRect2.y); // Compute the destination width - temp = MIN(xmost1, xmost2); + temp = PR_MIN(xmost1, xmost2); if (temp <= x) { Empty(); return PR_FALSE; @@ -264,7 +251,7 @@ PRBool nsIntRect::IntersectRect(const nsIntRect &aRect1, const nsIntRect &aRect2 width = temp - x; // Compute the destination height - temp = MIN(ymost1, ymost2); + temp = PR_MIN(ymost1, ymost2); if (temp <= y) { Empty(); return PR_FALSE; @@ -301,12 +288,12 @@ PRBool nsIntRect::UnionRect(const nsIntRect &aRect1, const nsIntRect &aRect2) PRInt32 ymost2 = aRect2.YMost(); // Compute the origin - x = MIN(aRect1.x, aRect2.x); - y = MIN(aRect1.y, aRect2.y); + x = PR_MIN(aRect1.x, aRect2.x); + y = PR_MIN(aRect1.y, aRect2.y); // Compute the size - width = MAX(xmost1, xmost2) - x; - height = MAX(ymost1, ymost2) - y; + width = PR_MAX(xmost1, xmost2) - x; + height = PR_MAX(ymost1, ymost2) - y; } return result; diff --git a/gfx/src/thebes/Makefile.in b/gfx/src/thebes/Makefile.in index 584a6da4891a..7222bcf22530 100644 --- a/gfx/src/thebes/Makefile.in +++ b/gfx/src/thebes/Makefile.in @@ -160,9 +160,6 @@ CFLAGS += $(TK_CFLAGS) ifdef MOZ_ENABLE_GTK2 DEFINES += -DMOZ_ENABLE_GTK2 -endif - -ifdef MOZ_ENABLE_PANGO CXXFLAGS += $(MOZ_PANGO_CFLAGS) endif diff --git a/gfx/thebes/crashtests/405268-1.xhtml b/gfx/thebes/crashtests/405268-1.xhtml new file mode 100644 index 000000000000..ecb6ecf21870 --- /dev/null +++ b/gfx/thebes/crashtests/405268-1.xhtml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/gfx/thebes/crashtests/410728-1.xml b/gfx/thebes/crashtests/410728-1.xml new file mode 100644 index 000000000000..deaeb8fc5536 --- /dev/null +++ b/gfx/thebes/crashtests/410728-1.xml @@ -0,0 +1,14 @@ + + +]> + + f ̲ + - + + + - + ̲ + diff --git a/gfx/thebes/crashtests/crashtests.list b/gfx/thebes/crashtests/crashtests.list index 605e165519da..3b96703ee963 100644 --- a/gfx/thebes/crashtests/crashtests.list +++ b/gfx/thebes/crashtests/crashtests.list @@ -21,5 +21,7 @@ load 398042-1.xhtml load 398042-2.xhtml load 404112-1.html load 404112-2.html +load 405268-1.xhtml load 407761-1.html load 407842.html +load 410728-1.xml diff --git a/gfx/thebes/public/gfxContext.h b/gfx/thebes/public/gfxContext.h index ba5e01c1e1a7..29f71b18ebcf 100644 --- a/gfx/thebes/public/gfxContext.h +++ b/gfx/thebes/public/gfxContext.h @@ -538,6 +538,7 @@ public: /** ** Extents - returns user space extent of current path **/ + gfxRect GetUserPathExtent(); gfxRect GetUserFillExtent(); gfxRect GetUserStrokeExtent(); @@ -580,4 +581,35 @@ private: PRInt32 mFlags; }; + +/** + * Sentry helper class for functions with multiple return points that need to + * call Save() on a gfxContext and have Restore() called automatically on the + * gfxContext before they return. + */ +class THEBES_API gfxContextAutoSaveRestore +{ +public: + gfxContextAutoSaveRestore() : mContext(nsnull) {} + + gfxContextAutoSaveRestore(gfxContext *aContext) : mContext(aContext) { + mContext->Save(); + } + + ~gfxContextAutoSaveRestore() { + if (mContext) { + mContext->Restore(); + } + } + + void SetContext(gfxContext *aContext) { + NS_ASSERTION(!mContext, "Not going to call Restore() on some context!!!"); + mContext = aContext; + mContext->Save(); + } + +private: + gfxContext *mContext; +}; + #endif /* GFX_CONTEXT_H */ diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index 59c5ebb06e87..5af3471d916a 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -52,6 +52,10 @@ #include "nsMathUtils.h" #include "nsBidiUtils.h" +#ifdef DEBUG +#include +#endif + class gfxContext; class gfxTextRun; class nsIAtom; @@ -352,6 +356,9 @@ class THEBES_API gfxFont { public: nsrefcnt AddRef(void) { NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); + if (mExpirationState.IsTracked()) { + gfxFontCache::GetCache()->RemoveObject(this); + } ++mRefCnt; NS_LOG_ADDREF(this, mRefCnt, "gfxFont", sizeof(*this)); return mRefCnt; @@ -1260,6 +1267,8 @@ public: #ifdef DEBUG // number of entries referencing this textrun in the gfxTextRunWordCache PRUint32 mCachedWords; + + void Dump(FILE* aOutput); #endif protected: @@ -1438,9 +1447,6 @@ public: void *closure); PRBool ForEachFont(FontCreationCallback fc, void *closure); - /* this will call back fc with the a generic font based on the style's langgroup */ - void FindGenericFontFromStyle(FontCreationCallback fc, void *closure); - const nsString& GetFamilies() { return mFamilies; } protected: @@ -1448,12 +1454,25 @@ protected: gfxFontStyle mStyle; nsTArray< nsRefPtr > mFonts; + /* If aResolveGeneric is true, then CSS/Gecko generic family names are + * replaced with preferred fonts. + * + * If aResolveFontName is true then fc() is called only for existing fonts + * and with actual font names. If false then fc() is called with each + * family name in aFamilies (after resolving CSS/Gecko generic family names + * if aResolveGeneric). + */ static PRBool ForEachFontInternal(const nsAString& aFamilies, const nsACString& aLangGroup, PRBool aResolveGeneric, + PRBool aResolveFontName, FontCreationCallback fc, void *closure); + /* this will call back fc with the a generic font based on the style's langgroup */ + void FindGenericFontFromStyle(PRBool aResolveFontName, + FontCreationCallback fc, void *closure); + static PRBool FontResolverProc(const nsAString& aName, void *aClosure); }; #endif diff --git a/gfx/thebes/public/gfxPangoFonts.h b/gfx/thebes/public/gfxPangoFonts.h index 97692b9749ad..46edd37ebb95 100644 --- a/gfx/thebes/public/gfxPangoFonts.h +++ b/gfx/thebes/public/gfxPangoFonts.h @@ -57,8 +57,6 @@ #include "nsDataHashtable.h" #include "nsClassHashtable.h" -class FontSelector; - class gfxPangoTextRun; class gfxPangoFont : public gfxFont { @@ -66,19 +64,16 @@ public: gfxPangoFont (const nsAString& aName, const gfxFontStyle *aFontStyle); virtual ~gfxPangoFont (); + static already_AddRefed GetOrMakeFont(PangoFont *aPangoFont); static void Shutdown(); virtual const gfxFont::Metrics& GetMetrics(); - PangoFontDescription *GetPangoFontDescription() { if (!mPangoFontDesc) RealizeFont(); return mPangoFontDesc; } - PangoContext *GetPangoContext() { if (!mPangoFontDesc) RealizeFont(); return mPangoCtx; } - - void GetMozLang(nsACString &aMozLang); - void GetActualFontFamily(nsACString &aFamily); - PangoFont *GetPangoFont() { if (!mPangoFont) RealizePangoFont(); return mPangoFont; } - gfxFloat GetAdjustedSize() { if (!mPangoFontDesc) RealizeFont(); return mAdjustedSize; } + + // Check GetStyle()->sizeAdjust != 0.0 before calling this + gfxFloat GetAdjustedSize() { if (!mPangoFont) RealizePangoFont(); return mAdjustedSize; } PRUint32 GetGlyph(const PRUint32 aChar); @@ -93,9 +88,6 @@ public: } protected: - PangoFontDescription *mPangoFontDesc; - PangoContext *mPangoCtx; - PangoFont *mPangoFont; cairo_scaled_font_t *mCairoFont; @@ -104,16 +96,15 @@ protected: Metrics mMetrics; gfxFloat mAdjustedSize; - void RealizeFont(PRBool force = PR_FALSE); - void RealizePangoFont(PRBool aForce = PR_FALSE); + gfxPangoFont(PangoFont *aPangoFont, const nsAString &aName, + const gfxFontStyle *aFontStyle); + void RealizePangoFont(); void GetCharSize(const char aChar, gfxSize& aInkSize, gfxSize& aLogSize, PRUint32 *aGlyphID = nsnull); virtual PRBool SetupCairoFont(gfxContext *aContext); }; -class FontSelector; - class THEBES_API gfxPangoFontGroup : public gfxFontGroup { public: gfxPangoFontGroup (const nsAString& families, @@ -133,8 +124,6 @@ public: } protected: - friend class FontSelector; - // ****** Textrun glyph conversion helpers ****** /** @@ -168,9 +157,6 @@ protected: static PRBool FontCallback (const nsAString& fontName, const nsACString& genericName, void *closure); - -private: - nsTArray mAdditionalStyles; }; class gfxPangoFontWrapper { diff --git a/gfx/thebes/src/Makefile.in b/gfx/thebes/src/Makefile.in index b7f37004225e..76a81c9df8df 100644 --- a/gfx/thebes/src/Makefile.in +++ b/gfx/thebes/src/Makefile.in @@ -144,7 +144,7 @@ include $(topsrcdir)/config/rules.mk CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS) CFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS) -ifdef MOZ_ENABLE_PANGO +ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) CXXFLAGS += $(MOZ_PANGO_CFLAGS) endif diff --git a/gfx/thebes/src/gfxAtsuiFonts.cpp b/gfx/thebes/src/gfxAtsuiFonts.cpp index 32478489d229..fe1b259aab79 100644 --- a/gfx/thebes/src/gfxAtsuiFonts.cpp +++ b/gfx/thebes/src/gfxAtsuiFonts.cpp @@ -805,7 +805,7 @@ gfxAtsuiFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh, PRUint32 aNex if (!selectedFont) { FontEntry *fe; - fe = gfxQuartzFontCache::SharedFontCache()->FindFontForChar(aCh, aPrevMatchedFont); + fe = gfxQuartzFontCache::SharedFontCache()->FindFontForChar(aCh, GetFontAt(0)); if (fe) { selectedFont = FindFontFor(fe->GetFontID()); return selectedFont.forget(); @@ -1434,7 +1434,7 @@ static void MirrorSubstring(ATSUTextLayout layout, nsAutoArrayPtr& mi class CmapFontMatcher { public: CmapFontMatcher(const PRUnichar *aString, PRUint32 aBeginOffset, PRUint32 aEndOffset, gfxAtsuiFontGroup* aFontGroup) : - mString(aString), mOffset(aBeginOffset), mPrevOffset(aBeginOffset), mEndOffset(aEndOffset), mPrevCh(0), mFirstPass(PR_TRUE), mFontGroup(aFontGroup), mMatchedFont(0), mNextMatchedFont(0) + mString(aString), mOffset(aBeginOffset), mPrevOffset(aBeginOffset), mEndOffset(aEndOffset), mPrevCh(0), mFirstRange(PR_TRUE), mFontGroup(aFontGroup), mMatchedFont(0), mNextMatchedFont(0) {} // match the next substring that uses the same font, returns the length matched @@ -1445,7 +1445,7 @@ public: matchStartOffset = mPrevOffset; - if ( !mFirstPass ) { + if ( !mFirstRange ) { mMatchedFont = mNextMatchedFont; } @@ -1473,9 +1473,9 @@ public: mPrevCh = ch; // no previous match, set one up - if ( mFirstPass ) { + if ( mFirstRange ) { mMatchedFont = font; - mFirstPass = PR_FALSE; + mFirstRange = PR_FALSE; } else if ( font != mMatchedFont ) { mPrevOffset = chStartOffset; mNextMatchedFont = font; @@ -1498,7 +1498,7 @@ private: PRUint32 mPrevOffset; PRUint32 mEndOffset; PRUint32 mPrevCh; - PRBool mFirstPass; + PRBool mFirstRange; gfxAtsuiFontGroup *mFontGroup; nsRefPtr mMatchedFont; nsRefPtr mNextMatchedFont; diff --git a/gfx/thebes/src/gfxContext.cpp b/gfx/thebes/src/gfxContext.cpp index 2588064a968c..26077e069d2b 100644 --- a/gfx/thebes/src/gfxContext.cpp +++ b/gfx/thebes/src/gfxContext.cpp @@ -740,6 +740,14 @@ gfxContext::PointInStroke(const gfxPoint& pt) return cairo_in_stroke(mCairo, pt.x, pt.y); } +gfxRect +gfxContext::GetUserPathExtent() +{ + double xmin, ymin, xmax, ymax; + cairo_path_extents(mCairo, &xmin, &ymin, &xmax, &ymax); + return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin); +} + gfxRect gfxContext::GetUserFillExtent() { diff --git a/gfx/thebes/src/gfxFont.cpp b/gfx/thebes/src/gfxFont.cpp index d43141f7dc1f..5af50cb8b30d 100644 --- a/gfx/thebes/src/gfxFont.cpp +++ b/gfx/thebes/src/gfxFont.cpp @@ -118,9 +118,6 @@ gfxFontCache::Lookup(const nsAString &aName, gfxFont *font = entry->mFont; NS_ADDREF(font); - if (font->GetExpirationState()->IsTracked()) { - RemoveObject(font); - } return font; } @@ -131,15 +128,16 @@ gfxFontCache::AddNew(gfxFont *aFont) HashEntry *entry = mFonts.PutEntry(key); if (!entry) return; - if (entry->mFont) { - // This is weird. Someone's asking us to overwrite an existing font. - // Oh well, make it happen ... just ensure that we're not tracking - // the old font - if (entry->mFont->GetExpirationState()->IsTracked()) { - RemoveObject(entry->mFont); - } - } + gfxFont *oldFont = entry->mFont; entry->mFont = aFont; + // If someone's asked us to replace an existing font entry, then that's a + // bit weird, but let it happen, and expire the old font if it's not used. + if (oldFont && oldFont->GetExpirationState()->IsTracked()) { + // if oldFont == aFont, recount should be > 0, + // so we shouldn't be here. + NS_ASSERTION(aFont != oldFont, "new font is tracked for expiry!"); + NotifyExpired(oldFont); + } } void @@ -168,7 +166,11 @@ void gfxFontCache::DestroyFont(gfxFont *aFont) { Key key(aFont->GetName(), aFont->GetStyle()); - mFonts.RemoveEntry(key); + HashEntry *entry = mFonts.GetEntry(key); + if (entry && entry->mFont == aFont) + mFonts.RemoveEntry(key); + NS_ASSERTION(aFont->GetRefCount() == 0, + "Destroying with non-zero ref count!"); delete aFont; } @@ -648,7 +650,7 @@ gfxFontGroup::ForEachFont(FontCreationCallback fc, void *closure) { return ForEachFontInternal(mFamilies, mStyle.langGroup, - PR_TRUE, fc, closure); + PR_TRUE, PR_TRUE, fc, closure); } PRBool @@ -658,7 +660,7 @@ gfxFontGroup::ForEachFont(const nsAString& aFamilies, void *closure) { return ForEachFontInternal(aFamilies, aLangGroup, - PR_FALSE, fc, closure); + PR_FALSE, PR_TRUE, fc, closure); } struct ResolveData { @@ -678,6 +680,7 @@ PRBool gfxFontGroup::ForEachFontInternal(const nsAString& aFamilies, const nsACString& aLangGroup, PRBool aResolveGeneric, + PRBool aResolveFontName, FontCreationCallback fc, void *closure) { @@ -765,14 +768,20 @@ gfxFontGroup::ForEachFontInternal(const nsAString& aFamilies, if (!family.IsEmpty()) { NS_LossyConvertUTF16toASCII gf(genericFamily); - ResolveData data(fc, gf, closure); - PRBool aborted; - gfxPlatform *pf = gfxPlatform::GetPlatform(); - nsresult rv = pf->ResolveFontName(family, - gfxFontGroup::FontResolverProc, - &data, aborted); - if (NS_FAILED(rv) || aborted) - return PR_FALSE; + if (aResolveFontName) { + ResolveData data(fc, gf, closure); + PRBool aborted; + gfxPlatform *pf = gfxPlatform::GetPlatform(); + nsresult rv = pf->ResolveFontName(family, + gfxFontGroup::FontResolverProc, + &data, aborted); + if (NS_FAILED(rv) || aborted) + return PR_FALSE; + } + else { + if (!fc(family, gf, closure)) + return PR_FALSE; + } } if (generic && aResolveGeneric) { @@ -783,7 +792,8 @@ gfxFontGroup::ForEachFontInternal(const nsAString& aFamilies, nsXPIDLString value; nsresult rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(value)); if (NS_SUCCEEDED(rv)) { - ForEachFontInternal(value, lang, PR_FALSE, fc, closure); + ForEachFontInternal(value, lang, PR_FALSE, aResolveFontName, + fc, closure); } } @@ -801,7 +811,8 @@ gfxFontGroup::FontResolverProc(const nsAString& aName, void *aClosure) } void -gfxFontGroup::FindGenericFontFromStyle(FontCreationCallback fc, +gfxFontGroup::FindGenericFontFromStyle(PRBool aResolveFontName, + FontCreationCallback fc, void *closure) { nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); @@ -825,7 +836,7 @@ gfxFontGroup::FindGenericFontFromStyle(FontCreationCallback fc, rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(familyName)); if (NS_SUCCEEDED(rv)) { ForEachFontInternal(familyName, mStyle.langGroup, - PR_FALSE, fc, closure); + PR_FALSE, aResolveFontName, fc, closure); } prefName.AssignLiteral("font.name-list."); @@ -836,7 +847,7 @@ gfxFontGroup::FindGenericFontFromStyle(FontCreationCallback fc, rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(familyName)); if (NS_SUCCEEDED(rv)) { ForEachFontInternal(familyName, mStyle.langGroup, - PR_FALSE, fc, closure); + PR_FALSE, aResolveFontName, fc, closure); } } } @@ -1979,3 +1990,36 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext) } } } + +#ifdef DEBUG +void +gfxTextRun::Dump(FILE* aOutput) { + if (!aOutput) { + aOutput = stdout; + } + + PRUint32 i; + fputc('"', aOutput); + for (i = 0; i < mCharacterCount; ++i) { + PRUnichar ch = GetChar(i); + if (ch >= 32 && ch < 128) { + fputc(ch, aOutput); + } else { + fprintf(aOutput, "\\u%4x", ch); + } + } + fputs("\" [", aOutput); + for (i = 0; i < mGlyphRuns.Length(); ++i) { + if (i > 0) { + fputc(',', aOutput); + } + gfxFont* font = mGlyphRuns[i].mFont; + const gfxFontStyle* style = font->GetStyle(); + NS_ConvertUTF16toUTF8 fontName(font->GetName()); + fprintf(aOutput, "%d: %s %f/%d/%d/%s", mGlyphRuns[i].mCharacterOffset, + fontName.get(), style->size, + style->weight, style->style, style->langGroup.get()); + } + fputc(']', aOutput); +} +#endif diff --git a/gfx/thebes/src/gfxOS2Fonts.cpp b/gfx/thebes/src/gfxOS2Fonts.cpp index 2e14f713ab55..6dba994ee179 100644 --- a/gfx/thebes/src/gfxOS2Fonts.cpp +++ b/gfx/thebes/src/gfxOS2Fonts.cpp @@ -429,7 +429,7 @@ gfxOS2FontGroup::gfxOS2FontGroup(const nsAString& aFamilies, nsStringArray familyArray; ForEachFont(FontCallback, &familyArray); - FindGenericFontFromStyle(FontCallback, &familyArray); + FindGenericFontFromStyle(PR_TRUE, FontCallback, &familyArray); // To be able to easily search for glyphs in other fonts, append a few good // replacement candidates to the list. The best ones are the Unicode fonts that diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index fbd685ed2a1d..23823325748e 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -23,6 +23,7 @@ * Masayuki Nakano * Behdad Esfahbod * Mats Palmgren + * Karl Tomlinson , Mozilla Corporation * * based on nsFontMetricsPango.cpp by * Christopher Blizzard @@ -119,7 +120,11 @@ gfxPangoFontGroup::FontCallback (const nsAString& fontName, { nsStringArray *sa = static_cast(closure); - if (FFRECountHyphens(fontName) < 3 && sa->IndexOf(fontName) < 0) { + // We ignore prefs that have three hypens since they are X style prefs. + if (genericName.Length() && FFRECountHyphens(fontName) >= 3) + return PR_TRUE; + + if (sa->IndexOf(fontName) < 0) { sa->AppendString(fontName); } @@ -154,24 +159,37 @@ gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families, nsStringArray familyArray; - ForEachFont (FontCallback, &familyArray); + // Leave non-existing fonts in the list so that fontconfig can get the + // best match. + ForEachFontInternal(families, aStyle->langGroup, PR_TRUE, PR_FALSE, + FontCallback, &familyArray); - FindGenericFontFromStyle (FontCallback, &familyArray); + FindGenericFontFromStyle(PR_FALSE, FontCallback, &familyArray); - // XXX If there are no actual fonts, we should use dummy family. - // Pango will resolve from this. - // behdad: yep, looks good. - if (familyArray.Count() == 0) { + // Construct a string suitable for fontconfig + nsAutoString fcFamilies; + if (familyArray.Count()) { + int i = 0; + while (1) { + fcFamilies.Append(*familyArray[i]); + ++i; + if (i >= familyArray.Count()) + break; + fcFamilies.Append(NS_LITERAL_STRING(",")); + } + } + else { + // XXX If there are no fonts, we should use dummy family. + // Pango will resolve from this. + // behdad: yep, looks good. // printf("%s(%s)\n", NS_ConvertUTF16toUTF8(families).get(), // aStyle->langGroup.get()); - familyArray.AppendString(NS_LITERAL_STRING("sans-serif")); + fcFamilies.Append(NS_LITERAL_STRING("sans-serif")); } - for (int i = 0; i < familyArray.Count(); i++) { - nsRefPtr font = GetOrMakeFont(*familyArray[i], &mStyle); - if (font) { - mFonts.AppendElement(font); - } + nsRefPtr font = GetOrMakeFont(fcFamilies, &mStyle); + if (font) { + mFonts.AppendElement(font); } } @@ -192,21 +210,38 @@ gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle) gfxPangoFont::gfxPangoFont(const nsAString &aName, const gfxFontStyle *aFontStyle) : gfxFont(aName, aFontStyle), - mPangoFontDesc(nsnull), mPangoCtx(nsnull), mPangoFont(nsnull), - mCairoFont(nsnull), mHasMetrics(PR_FALSE), mAdjustedSize(0) + mPangoFont(nsnull), mCairoFont(nsnull), + mHasMetrics(PR_FALSE), mAdjustedSize(0) { } +// key for locating a gfxPangoFont corresponding to a PangoFont +static GQuark GetFontQuark() +{ + // Not using g_quark_from_static_string() because this module may be + // unloaded (which would leave a dangling pointer). Using + // g_quark_from_string() instead, which creates a small shutdown leak. + static GQuark quark = g_quark_from_string("moz-gfxFont"); + return quark; +} + +gfxPangoFont::gfxPangoFont(PangoFont *aPangoFont, const nsAString &aName, + const gfxFontStyle *aFontStyle) + : gfxFont(aName, aFontStyle), + mPangoFont(aPangoFont), mCairoFont(nsnull), + mHasMetrics(PR_FALSE), mAdjustedSize(aFontStyle->size) +{ + g_object_ref(mPangoFont); + g_object_set_qdata(G_OBJECT(mPangoFont), GetFontQuark(), this); +} + gfxPangoFont::~gfxPangoFont() { - if (mPangoCtx) - g_object_unref(mPangoCtx); - - if (mPangoFont) + if (mPangoFont) { + if (g_object_get_qdata(G_OBJECT(mPangoFont), GetFontQuark()) == this) + g_object_set_qdata(G_OBJECT(mPangoFont), GetFontQuark(), NULL); g_object_unref(mPangoFont); - - if (mPangoFontDesc) - pango_font_description_free(mPangoFontDesc); + } if (mCairoFont) cairo_scaled_font_destroy(mCairoFont); @@ -238,6 +273,17 @@ ThebesStyleToPangoStyle (const gfxFontStyle *fs) return PANGO_STYLE_NORMAL; } +static PRUint8 +PangoStyleToThebesStyle (PangoStyle aPangoStyle) +{ + if (aPangoStyle == PANGO_STYLE_ITALIC) + return FONT_STYLE_ITALIC; + if (aPangoStyle == FONT_STYLE_OBLIQUE) + return FONT_STYLE_OBLIQUE; + + return FONT_STYLE_NORMAL; +} + static PangoWeight ThebesStyleToPangoWeight (const gfxFontStyle *fs) { @@ -281,7 +327,7 @@ ThebesStyleToPangoWeight (const gfxFontStyle *fs) /* Map to final PANGO_WEIGHT value */ static const int fcWeights[5] = { 349, - 499, + 449, 649, 749, 900 @@ -290,78 +336,139 @@ ThebesStyleToPangoWeight (const gfxFontStyle *fs) return (PangoWeight)fcWeights[fcWeight]; } +/* Note this doesn't check sizeAdjust */ +static PangoFontDescription * +NewPangoFontDescription(const nsAString &aName, const gfxFontStyle *aFontStyle) +{ + PangoFontDescription *fontDesc = pango_font_description_new(); + + pango_font_description_set_family(fontDesc, + NS_ConvertUTF16toUTF8(aName).get()); + pango_font_description_set_absolute_size(fontDesc, + aFontStyle->size * PANGO_SCALE); + pango_font_description_set_style(fontDesc, + ThebesStyleToPangoStyle(aFontStyle)); + pango_font_description_set_weight(fontDesc, + ThebesStyleToPangoWeight(aFontStyle)); + return fontDesc; +} + +/** + * The following gfxPangoFonts are accessed from the PangoFont, not from the + * gfxFontCache hash table. The gfxFontCache hash table is keyed by desired + * family and style, whereas here we only know actual family and style. There + * may be more than one of these fonts with the same family and style, but + * different PangoFont and actual font face. + * + * The point of this is to record the exact font face for gfxTextRun glyph + * indices. The style of this font does not necessarily represent the exact + * gfxFontStyle used to build the text run. Notably, the language is not + * recorded, but is used for GetMetrics().aveCharWidth. However, the font + * that should be used for aveCharWidth is gfxPangoFontGroup::GetFontAt(0), + * which is not constructed here. + */ + +/* static */ +already_AddRefed +gfxPangoFont::GetOrMakeFont(PangoFont *aPangoFont) +{ + gfxPangoFont *font = static_cast + (g_object_get_qdata(G_OBJECT(aPangoFont), GetFontQuark())); + + if (!font) { + PangoFontDescription *desc = + pango_font_describe_with_absolute_size(aPangoFont); + + // Shouldn't actually need to take too much care about the correct + // family or style, as size is the only thing expected to be + // important. + gfxFloat size = + pango_font_description_get_size(desc) / FLOAT_PANGO_SCALE; + PRUint8 style = + PangoStyleToThebesStyle(pango_font_description_get_style(desc)); + PRUint16 weight = pango_font_description_get_weight(desc); + NS_NAMED_LITERAL_CSTRING(langGroup, "x-unicode"); + gfxFontStyle fontStyle(style, weight, size, langGroup, 0.0, + PR_TRUE, PR_FALSE); + + // (The PangoFontDescription owns the family string) + const char *family = pango_font_description_get_family(desc); + font = new gfxPangoFont(aPangoFont, + NS_ConvertUTF8toUTF16(family), &fontStyle); + + pango_font_description_free(desc); + if (!font) + return nsnull; + + // Do not add this font to the gfxFontCache hash table as this may not + // be the PangoFont that fontconfig chooses for this style. + } + NS_ADDREF(font); + return font; +} + +static PangoFont* +LoadPangoFont(PangoContext *aPangoCtx, const PangoFontDescription *aPangoFontDesc) +{ + gfxPangoFontCache *cache = gfxPangoFontCache::GetPangoFontCache(); + if (!cache) + return nsnull; // Error + PangoFont* pangoFont = cache->Get(aPangoFontDesc); + if (!pangoFont) { + pangoFont = pango_context_load_font(aPangoCtx, aPangoFontDesc); + if (pangoFont) { + cache->Put(aPangoFontDesc, pangoFont); + } + } + return pangoFont; +} + void -gfxPangoFont::RealizeFont(PRBool force) +gfxPangoFont::RealizePangoFont() { // already realized? - if (!force && mPangoFontDesc) + if (mPangoFont) return; - if (mPangoCtx) - g_object_unref(mPangoCtx); - if (mPangoFontDesc) - pango_font_description_free(mPangoFontDesc); - if (mPangoFont) { - g_object_unref(mPangoFont); - mPangoFont = nsnull; - } + PangoFontDescription *pangoFontDesc = + NewPangoFontDescription(mName, GetStyle()); - mPangoFontDesc = pango_font_description_new(); - - pango_font_description_set_family(mPangoFontDesc, NS_ConvertUTF16toUTF8(mName).get()); - gfxFloat size = mAdjustedSize != 0.0f ? mAdjustedSize : GetStyle()->size; - pango_font_description_set_absolute_size(mPangoFontDesc, size * PANGO_SCALE); - pango_font_description_set_style(mPangoFontDesc, ThebesStyleToPangoStyle(GetStyle())); - pango_font_description_set_weight(mPangoFontDesc, ThebesStyleToPangoWeight(GetStyle())); - - //printf ("%s, %f, %d, %d\n", NS_ConvertUTF16toUTF8(mName).get(), GetStyle()->size, ThebesStyleToPangoStyle(GetStyle()), ThebesStyleToPangoWeight(GetStyle())); - mPangoCtx = gdk_pango_context_get (); + PangoContext *pangoCtx = gdk_pango_context_get(); if (!GetStyle()->langGroup.IsEmpty()) { PangoLanguage *lang = GetPangoLanguage(GetStyle()->langGroup); if (lang) - pango_context_set_language(mPangoCtx, lang); + pango_context_set_language(pangoCtx, lang); } - pango_context_set_font_description(mPangoCtx, mPangoFontDesc); + mPangoFont = LoadPangoFont(pangoCtx, pangoFontDesc); - NS_ASSERTION(mHasMetrics == PR_FALSE, "throwing away our good metrics...."); - mHasMetrics = PR_FALSE; + gfxFloat size = GetStyle()->size; + // Checking mPangoFont to avoid infinite recursion through GetCharSize + if (size != 0.0 && GetStyle()->sizeAdjust != 0.0 && mPangoFont) { + // Could try xHeight from TrueType/OpenType fonts. + gfxSize isz, lsz; + GetCharSize('x', isz, lsz); + if (isz.height != 0.0) { + gfxFloat aspect = isz.height / size; + size = GetStyle()->GetAdjustedSize(aspect); - if (mAdjustedSize != 0.0f) - return; - - mAdjustedSize = GetStyle()->size; - if (mAdjustedSize == 0.0f || GetStyle()->sizeAdjust == 0.0f) - return; - - gfxSize isz, lsz; - GetCharSize('x', isz, lsz); - gfxFloat aspect = isz.height / GetStyle()->size; - mAdjustedSize = GetStyle()->GetAdjustedSize(aspect); - RealizeFont(PR_TRUE); -} - -void -gfxPangoFont::RealizePangoFont(PRBool aForce) -{ - if (!aForce && mPangoFont) - return; - if (mPangoFont) { - g_object_unref(mPangoFont); - mPangoFont = nsnull; + pango_font_description_set_absolute_size(pangoFontDesc, + size * PANGO_SCALE); + g_object_unref(mPangoFont); + mPangoFont = LoadPangoFont(pangoCtx, pangoFontDesc); + } } - RealizeFont(); - gfxPangoFontCache *cache = gfxPangoFontCache::GetPangoFontCache(); - if (!cache) - return; // Error - mPangoFont = cache->Get(mPangoFontDesc); - if (mPangoFont) - return; - mPangoFont = pango_context_load_font(mPangoCtx, mPangoFontDesc); - if (!mPangoFont) - return; // Error - cache->Put(mPangoFontDesc, mPangoFont); + + NS_ASSERTION(mHasMetrics == PR_FALSE, "metrics will be invalid..."); + mAdjustedSize = size; + if (!g_object_get_qdata(G_OBJECT(mPangoFont), GetFontQuark())) + g_object_set_qdata(G_OBJECT(mPangoFont), GetFontQuark(), this); + + if (pangoFontDesc) + pango_font_description_free(pangoFontDesc); + if (pangoCtx) + g_object_unref(pangoCtx); } void @@ -376,6 +483,9 @@ gfxPangoFont::GetCharSize(char aChar, gfxSize& aInkSize, gfxSize& aLogSize, return; } + // XXXkt: Why not use pango_font_get_glyph_extents? This function isn't + // currently being used for characters likely to involve glyph clusters. + // I don't think pango_shape will fallback to other fonts. PangoAnalysis analysis; // Initialize new fields, gravity and flags in pango 1.16 // (or padding in 1.14). @@ -430,7 +540,7 @@ gfxPangoFont::GetMetrics() PangoFont *font; PangoFontMetrics *pfm; if (NS_LIKELY(GetStyle()->size > 0.0)) { - font = GetPangoFont(); // RealizeFont is called here. + font = GetPangoFont(); // RealizePangoFont is called here. PangoLanguage *lang = GetPangoLanguage(GetStyle()->langGroup); // XXX @@ -641,14 +751,12 @@ gfxPangoFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength, PRBool gfxPangoFontGroup::CanTakeFastPath(PRUint32 aFlags) { - if (!PANGO_IS_FC_FONT (GetFontAt(0)->GetPangoFont ())) - return FALSE; - - // Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't - // We need to always use Pango for RTL text, in case glyph mirroring is required - return (aFlags & - (gfxTextRunFactory::TEXT_OPTIMIZE_SPEED | gfxTextRunFactory::TEXT_IS_RTL)) == - gfxTextRunFactory::TEXT_OPTIMIZE_SPEED; + // Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't. + // We need to always use Pango for RTL text, in case glyph mirroring is + // required. + PRBool speed = aFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED; + PRBool isRTL = aFlags & gfxTextRunFactory::TEXT_IS_RTL; + return speed && !isRTL && PANGO_IS_FC_FONT(GetFontAt(0)->GetPangoFont()); } #endif @@ -698,10 +806,6 @@ gfxPangoFontGroup::InitTextRun(gfxTextRun *aTextRun, const gchar *aUTF8Text, } #endif - pango_context_set_base_dir(GetFontAt(0)->GetPangoContext(), - (aTextRun->IsRightToLeft() - ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR)); - CreateGlyphRunsItemizing(aTextRun, aUTF8Text, aUTF8Length, aUTF8HeaderLength); #endif } @@ -790,36 +894,28 @@ SetupClusterBoundaries(gfxTextRun* aTextRun, const gchar *aUTF8, PRUint32 aUTF8L if (!buffer.AppendElements(aUTF8Length + 1)) return; + pango_break(aUTF8, aUTF8Length, aAnalysis, + buffer.Elements(), buffer.Length()); + const gchar *p = aUTF8; const gchar *end = aUTF8 + aUTF8Length; + const PangoLogAttr *attr = buffer.Elements(); gfxTextRun::CompressedGlyph g; - while (p < end) { - PangoLogAttr *attr = buffer.Elements(); - pango_break(p, end - p, aAnalysis, attr, buffer.Length()); - - while (p < end) { - if (!attr->is_cursor_position) { - aTextRun->SetGlyphs(aUTF16Offset, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull); - } - ++aUTF16Offset; - - gunichar ch = g_utf8_get_char(p); - NS_ASSERTION(!IS_SURROGATE(ch), "Shouldn't have surrogates in UTF8"); - if (ch >= 0x10000) { - ++aUTF16Offset; - } - // We produced this utf8 so we don't need to worry about malformed stuff - p = g_utf8_next_char(p); - ++attr; - - if (ch == 0) { - // pango_break (pango 1.16.2) only analyses text before the - // first NUL (but sets one extra attr), so call pango_break - // again to analyse after the NUL. - break; - } + if (!attr->is_cursor_position) { + aTextRun->SetGlyphs(aUTF16Offset, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull); } + ++aUTF16Offset; + + gunichar ch = g_utf8_get_char(p); + NS_ASSERTION(ch != 0, "Shouldn't have NUL in pango_break"); + NS_ASSERTION(!IS_SURROGATE(ch), "Shouldn't have surrogates in UTF8"); + if (ch >= 0x10000) { + ++aUTF16Offset; + } + // We produced this utf8 so we don't need to worry about malformed stuff + p = g_utf8_next_char(p); + ++attr; } } @@ -969,6 +1065,7 @@ gfxPangoFontGroup::SetGlyphs(gfxTextRun *aTextRun, gfxPangoFont *aFont, utf8Index = 0; // The next glyph cluster in logical order. gint nextGlyphClusterStart = logGlyphs[utf8Index]; + NS_ASSERTION(nextGlyphClusterStart >= 0, "No glyphs! - NUL in string?"); while (utf8Index < aUTF8Length) { if (utf16Offset >= textRunLength) { NS_ERROR("Someone has added too many glyphs!"); @@ -983,44 +1080,32 @@ gfxPangoFontGroup::SetGlyphs(gfxTextRun *aTextRun, gfxPangoFont *aFont, do { ++utf8Index; nextGlyphClusterStart = logGlyphs[utf8Index]; - } while (nextGlyphClusterStart < 0 && aUTF8[utf8Index] != '\0'); + } while (nextGlyphClusterStart < 0); const gchar *clusterUTF8 = &aUTF8[clusterUTF8Start]; PRUint32 clusterUTF8Length = utf8Index - clusterUTF8Start; PRBool haveMissingGlyph = PR_FALSE; gint glyphIndex = glyphClusterStart; - if (glyphClusterStart < 0) { - // No glyphs - This happens with a NUL: Pango doesn't create - // glyphs for these, not even missing-glyph glyphIDs. - // Treat a NUL byte as a missing glyph. - haveMissingGlyph = PR_TRUE; - // Any non-NUL UTF8 bytes are unexpected. - NS_ASSERTION(*clusterUTF8 == '\0' && clusterUTF8Length == 1, - "No glyphs and not a NUL"); - if (aAbortOnMissingGlyph && - (*clusterUTF8 != '\0' || clusterUTF8Length != 1)) { - return NS_ERROR_FAILURE; - } - } else { - do { - if (IS_EMPTY_GLYPH(glyphs[glyphIndex].glyph)) { - // The zero width characters return empty glyph ID at - // shaping, we should override it. - glyphs[glyphIndex].glyph = aFont->GetGlyph(' '); - glyphs[glyphIndex].geometry.width = 0; - } else if (IS_MISSING_GLYPH(glyphs[glyphIndex].glyph)) { - // Does pango ever provide more than one glyph in the - // cluster if there is a missing glyph? - // behdad: yes - haveMissingGlyph = PR_TRUE; - } - glyphIndex++; - } while (glyphIndex < numGlyphs && - logClusters[glyphIndex] == gint(clusterUTF8Start)); - if (haveMissingGlyph && aAbortOnMissingGlyph) - return NS_ERROR_FAILURE; - } + // It's now unncecessary to do NUL handling here. + do { + if (IS_EMPTY_GLYPH(glyphs[glyphIndex].glyph)) { + // The zero width characters return empty glyph ID at + // shaping, we should override it. + glyphs[glyphIndex].glyph = aFont->GetGlyph(' '); + glyphs[glyphIndex].geometry.width = 0; + } else if (IS_MISSING_GLYPH(glyphs[glyphIndex].glyph)) { + // Does pango ever provide more than one glyph in the + // cluster if there is a missing glyph? + // behdad: yes + haveMissingGlyph = PR_TRUE; + } + glyphIndex++; + } while (glyphIndex < numGlyphs && + logClusters[glyphIndex] == gint(clusterUTF8Start)); + + if (haveMissingGlyph && aAbortOnMissingGlyph) + return NS_ERROR_FAILURE; nsresult rv; if (haveMissingGlyph) { @@ -1139,26 +1224,20 @@ gfxPangoFontGroup::CreateGlyphRunsItemizing(gfxTextRun *aTextRun, PRUint32 aUTF8HeaderLen) { - PangoContext *context = gdk_pango_context_get (); + PangoContext *context = gdk_pango_context_get(); - PangoFontDescription *fontDesc = pango_font_description_new(); - - // these should be FontEntries or something similar rather than gfxPangoFonts... - nsString fontList; - - for (PRUint32 i = 0; i < mFonts.Length(); i++) { - fontList.Append(mFonts[i]->GetName()); - fontList.Append(NS_LITERAL_STRING(",")); + PangoFontDescription *fontDesc = + NewPangoFontDescription(GetFontAt(0)->GetName(), GetStyle()); + if (GetStyle()->sizeAdjust != 0.0) { + gfxFloat size = + static_cast(GetFontAt(0))->GetAdjustedSize(); + pango_font_description_set_absolute_size(fontDesc, size * PANGO_SCALE); } - PangoLanguage *lang = GetPangoLanguage(GetStyle()->langGroup); - - pango_font_description_set_family(fontDesc, NS_ConvertUTF16toUTF8(fontList).get()); - pango_font_description_set_absolute_size(fontDesc, GetStyle()->size * PANGO_SCALE); - pango_font_description_set_style(fontDesc, ThebesStyleToPangoStyle(GetStyle())); - pango_font_description_set_weight(fontDesc, ThebesStyleToPangoWeight(GetStyle())); - pango_context_set_font_description(context, fontDesc); + pango_font_description_free(fontDesc); + + PangoLanguage *lang = GetPangoLanguage(GetStyle()->langGroup); // we should set this to null if we don't have a text language from the page... // except that we almost always have something... @@ -1170,6 +1249,10 @@ gfxPangoFontGroup::CreateGlyphRunsItemizing(gfxTextRun *aTextRun, PRUint32 utf16Offset = 0; PRBool isRTL = aTextRun->IsRightToLeft(); GList *pos = items; + PangoGlyphString *glyphString = pango_glyph_string_new(); + if (!glyphString) + goto out; // OOM + for (; pos && pos->data; pos = pos->next) { PangoItem *item = (PangoItem *)pos->data; NS_ASSERTION(isRTL == item->analysis.level % 2, "RTL assumption mismatch"); @@ -1177,54 +1260,62 @@ gfxPangoFontGroup::CreateGlyphRunsItemizing(gfxTextRun *aTextRun, PRUint32 offset = item->offset; PRUint32 length = item->length; if (offset < aUTF8HeaderLen) { - if (offset + length <= aUTF8HeaderLen) { - pango_item_free(item); + if (offset + length <= aUTF8HeaderLen) continue; - } + length -= aUTF8HeaderLen - offset; offset = aUTF8HeaderLen; } - // need to append glyph runs here. - PangoGlyphString *glyphString = pango_glyph_string_new(); - if (!glyphString) - return; // OOM - - pango_shape(aUTF8 + offset, length, &item->analysis, glyphString); - /* look up the gfxPangoFont from the PangoFont */ - // XXX we need a function to do this.. until then do this - // behdad: use g_object_[sg]et_qdata() for it. - PangoFontDescription *d = pango_font_describe(item->analysis.font); - nsRefPtr font = GetOrMakeFont(NS_ConvertUTF8toUTF16(pango_font_description_get_family(d)), GetStyle()); - - //printf("Using %s\n", pango_font_description_get_family(d)); - - pango_font_description_free(d); - SetupClusterBoundaries(aTextRun, aUTF8 + offset, length, utf16Offset, &item->analysis); + nsRefPtr font = + gfxPangoFont::GetOrMakeFont(item->analysis.font); nsresult rv = aTextRun->AddGlyphRun(font, utf16Offset, PR_TRUE); if (NS_FAILED(rv)) { NS_ERROR("AddGlyphRun Failed"); - pango_glyph_string_free(glyphString); - return; + goto out; } PRUint32 spaceWidth = NS_lround(font->GetMetrics().spaceWidth * FLOAT_PANGO_SCALE); - rv = SetGlyphs(aTextRun, font, aUTF8 + offset, length, &utf16Offset, glyphString, spaceWidth, PR_FALSE); + const gchar *p = aUTF8 + offset; + const gchar *end = p + length; + while (p < end) { + if (*p == 0) { + aTextRun->SetMissingGlyph(utf16Offset, 0); + ++p; + ++utf16Offset; + continue; + } - pango_glyph_string_free(glyphString); + // It's necessary to loop over pango_shape as it treats + // NULs as string terminators + const gchar *text = p; + do { + ++p; + } while(p < end && *p != 0); + gint len = p - text; + + pango_shape(text, len, &item->analysis, glyphString); + SetupClusterBoundaries(aTextRun, text, len, utf16Offset, &item->analysis); + SetGlyphs(aTextRun, font, text, len, &utf16Offset, glyphString, spaceWidth, PR_FALSE); + } } + aTextRun->SortGlyphRuns(); + +out: + if (glyphString) + pango_glyph_string_free(glyphString); + + for (pos = items; pos; pos = pos->next) + pango_item_free((PangoItem *)pos->data); + if (items) g_list_free(items); - pango_font_description_free(fontDesc); - g_object_unref(context); - - aTextRun->SortGlyphRuns(); } diff --git a/gfx/thebes/src/gfxPlatformGtk.cpp b/gfx/thebes/src/gfxPlatformGtk.cpp index a5bbeb1456ce..563e0ef76ba2 100644 --- a/gfx/thebes/src/gfxPlatformGtk.cpp +++ b/gfx/thebes/src/gfxPlatformGtk.cpp @@ -137,6 +137,9 @@ gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size, // in more context, including the display and/or target surface type that // we should try to match Display* display = GDK_DISPLAY(); + if (!display) + return nsnull; + if (!UseGlitz()) { GdkPixmap* pixmap = nsnull; XRenderPictFormat* xrenderFormat = diff --git a/gfx/thebes/src/gfxTextRunWordCache.cpp b/gfx/thebes/src/gfxTextRunWordCache.cpp index d317f22f53b4..25b65285ec8e 100644 --- a/gfx/thebes/src/gfxTextRunWordCache.cpp +++ b/gfx/thebes/src/gfxTextRunWordCache.cpp @@ -37,10 +37,29 @@ #include "gfxTextRunWordCache.h" +#ifdef DEBUG +#include +#endif + /** * Cache individual "words" (strings delimited by white-space or white-space-like * characters that don't involve kerning or ligatures) in textruns. - */ + * + * The characters treated as word boundaries are defined by IsWordBoundary + * below. The characters are: space, NBSP, and all the characters + * defined by gfxFontGroup::IsInvalidChar. The latter are all converted + * to invisible missing glyphs in this code. Thus, this class ensures + * that none of those invalid characters are ever passed to platform + * textrun implementations. + * + * Some platforms support marks combining with spaces to form clusters. + * In such cases we treat "before the space" as a word boundary but + * "after the space" is not a word boundary; words with a leading space + * are kept out of the cache. Also, words at the start of text, which start + * with combining marks that would combine with a space if there was one, + * are also kept out of the cache. + */ + class TextRunWordCache { public: TextRunWordCache() { @@ -83,6 +102,10 @@ public: */ void RemoveTextRun(gfxTextRun *aTextRun); +#ifdef DEBUG + void Dump(); +#endif + protected: struct CacheHashKey { void *mFontOrGroup; @@ -151,13 +174,17 @@ protected: PRUint32 aStart, PRUint32 aEnd, PRUint32 aHash, nsTArray* aDeferredWords); void FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun, - gfxContext *aContext, + const gfxFontGroup::Parameters *aParams, const nsTArray& aDeferredWords, PRBool aSuccessful); void RemoveWord(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, PRUint32 aHash); nsTHashtable mCache; + +#ifdef DEBUG + static PLDHashOperator PR_CALLBACK CacheDumpEntry(CacheHashEntry* aEntry, void* userArg); +#endif }; static PRLogModuleInfo *gWordCacheLog = PR_NewLogModule("wordCache"); @@ -295,7 +322,7 @@ TextRunWordCache::LookupWord(gfxTextRun *aTextRun, gfxFont *aFirstFont, */ void TextRunWordCache::FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun, - gfxContext *aContext, + const gfxFontGroup::Parameters *aParams, const nsTArray& aDeferredWords, PRBool aSuccessful) { @@ -310,23 +337,37 @@ TextRunWordCache::FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun, gfxTextRun *source = word->mSourceTextRun; if (!source) { source = aNewRun; - // we created a cache entry for this word based on the assumption + } + // If the word starts inside a cluster we don't want this word + // in the cache, so we'll remove the associated cache entry + PRBool wordStartsInsideCluster = + !source->IsClusterStart(word->mSourceOffset); + if (source == aNewRun) { + // We created a cache entry for this word based on the assumption // that the word matches GetFontAt(0). If this assumption is false, // we need to remove that cache entry and replace it with an entry // keyed off the fontgroup. - if (!aSuccessful || - GetWordFontOrGroup(aNewRun, word->mSourceOffset, word->mLength) != font) { + PRBool rekeyWithFontGroup = + GetWordFontOrGroup(aNewRun, word->mSourceOffset, word->mLength) != font; + if (!aSuccessful || wordStartsInsideCluster || rekeyWithFontGroup) { + // We need to remove the current placeholder cache entry CacheHashKey key(aTextRun, font, word->mDestOffset, word->mLength, word->mHash); NS_ASSERTION(mCache.GetEntry(key), "This entry should have been added previously!"); mCache.RemoveEntry(key); +#ifdef DEBUG + --aTextRun->mCachedWords; +#endif PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): removed using font", aTextRun, word->mDestOffset, word->mLength, word->mHash)); - if (aSuccessful) { + if (aSuccessful && !wordStartsInsideCluster) { key.mFontOrGroup = fontGroup; CacheHashEntry *groupEntry = mCache.PutEntry(key); if (groupEntry) { +#ifdef DEBUG + ++aTextRun->mCachedWords; +#endif PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): added using fontgroup", aTextRun, word->mDestOffset, word->mLength, word->mHash)); groupEntry->mTextRun = aTextRun; groupEntry->mWordOffset = word->mDestOffset; @@ -341,9 +382,38 @@ TextRunWordCache::FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun, // Copy the word. If the source is aNewRun, then // allow CopyGlyphDataFrom to steal the internal data of // aNewRun since that's only temporary anyway. - aTextRun->CopyGlyphDataFrom(source, - word->mSourceOffset, word->mLength, word->mDestOffset, - source == aNewRun); + PRUint32 sourceOffset = word->mSourceOffset; + PRUint32 destOffset = word->mDestOffset; + PRUint32 length = word->mLength; + nsAutoPtr tmpTextRun; + PRBool stealData = source == aNewRun; + if (wordStartsInsideCluster) { + NS_ASSERTION(sourceOffset > 0, "How can the first character be inside a cluster?"); + if (destOffset > 0 && IsBoundarySpace(aTextRun->GetChar(destOffset - 1))) { + // We should copy over data for the preceding space + // as well. The glyphs have probably been attached + // to that character. + --sourceOffset; + --destOffset; + ++length; + } else { + // URK! This case sucks! We have combining marks + // at the start of the text. We had to prepend a space + // just so we could detect these are combining marks + // (so we can keep this "word" out of the cache). + // But now the data in aNewRun is no use to us. We + // need to find out what the platform would do + // if the marks were at the start of the text. + tmpTextRun = aNewRun->GetFontGroup()->MakeTextRun( + aTextRun->GetTextUnicode(), length, aParams, + aNewRun->GetFlags()); + source = tmpTextRun; + sourceOffset = 0; + stealData = PR_TRUE; + } + } + aTextRun->CopyGlyphDataFrom(source, sourceOffset, length, + destOffset, stealData); // Fill in additional spaces PRUint32 endCharIndex; if (i + 1 < aDeferredWords.Length()) { @@ -355,7 +425,7 @@ TextRunWordCache::FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun, for (charIndex = word->mDestOffset + word->mLength; charIndex < endCharIndex; ++charIndex) { if (IsBoundarySpace(aTextRun->GetChar(charIndex))) { - aTextRun->SetSpaceGlyph(font, aContext, charIndex); + aTextRun->SetSpaceGlyph(font, aParams->mContext, charIndex); } } } @@ -413,9 +483,9 @@ TextRunWordCache::MakeTextRun(const PRUnichar *aText, PRUint32 aLength, PRBool hit = LookupWord(textRun, font, wordStart, i, hash, deferredWords.Length() == 0 ? nsnull : &deferredWords); if (!hit) { - if (tempString.Length() > 0) { - tempString.AppendElement(' '); - } + // Always put a space before the word so we can detect + // combining characters at the start of a word + tempString.AppendElement(' '); PRUint32 offset = tempString.Length(); PRUint32 length = i - wordStart; PRUnichar *chars = tempString.AppendElements(length); @@ -455,7 +525,7 @@ TextRunWordCache::MakeTextRun(const PRUnichar *aText, PRUint32 aLength, newRun = aFontGroup->MakeTextRun(tempString.Elements(), tempString.Length(), ¶ms, aFlags | gfxTextRunFactory::TEXT_IS_PERSISTENT); - FinishTextRun(textRun, newRun, aParams->mContext, deferredWords, newRun != nsnull); + FinishTextRun(textRun, newRun, aParams, deferredWords, newRun != nsnull); return textRun.forget(); } @@ -538,7 +608,7 @@ TextRunWordCache::MakeTextRun(const PRUint8 *aText, PRUint32 aLength, newRun = aFontGroup->MakeTextRun(tempString.Elements(), tempString.Length(), ¶ms, aFlags | gfxTextRunFactory::TEXT_IS_PERSISTENT); - FinishTextRun(textRun, newRun, aParams->mContext, deferredWords, newRun != nsnull); + FinishTextRun(textRun, newRun, aParams, deferredWords, newRun != nsnull); return textRun.forget(); } @@ -660,6 +730,28 @@ TextRunWordCache::CacheHashEntry::HashKey(const KeyTypePointer aKey) aKey->mOptimizeSpeed*8; } +#ifdef DEBUG +PLDHashOperator PR_CALLBACK +TextRunWordCache::CacheDumpEntry(CacheHashEntry* aEntry, void* userArg) +{ + FILE* output = static_cast(userArg); + if (!aEntry->mTextRun) { + fprintf(output, "\n"); + return PL_DHASH_NEXT; + } + fprintf(output, "Word at %x:%d => ", aEntry->mTextRun, aEntry->mWordOffset); + aEntry->mTextRun->Dump(output); + fprintf(output, " (hashed by %s)\n", aEntry->mHashedByFont ? "font" : "fontgroup"); + return PL_DHASH_NEXT; +} + +void +TextRunWordCache::Dump() +{ + mCache.EnumerateEntries(CacheDumpEntry, stdout); +} +#endif + static TextRunWordCache *gTextRunWordCache = nsnull; nsresult diff --git a/gfx/thebes/src/gfxWindowsFonts.cpp b/gfx/thebes/src/gfxWindowsFonts.cpp index 8ab384fc1274..1b9e502b3c25 100644 --- a/gfx/thebes/src/gfxWindowsFonts.cpp +++ b/gfx/thebes/src/gfxWindowsFonts.cpp @@ -1337,7 +1337,7 @@ public: // close out the previous range prevRange.end = origI; - TextRange r(i, i+1); + TextRange r(origI, i+1); r.font = fe; mRanges.AppendElement(r); } diff --git a/gfx/thebes/test/Makefile.in b/gfx/thebes/test/Makefile.in index 117120674348..570adc2a5511 100644 --- a/gfx/thebes/test/Makefile.in +++ b/gfx/thebes/test/Makefile.in @@ -96,11 +96,8 @@ endif ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) OS_LIBS += $(MOZ_PANGO_LIBS) $(MOZ_XFT_LIBS) $(XLIBS) +CXXFLAGS += $(MOZ_PANGO_CFLAGS) endif CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS) CFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS) - -ifdef MOZ_ENABLE_PANGO -CXXFLAGS += $(MOZ_PANGO_CFLAGS) -endif diff --git a/gfx/thebes/test/gfxFontSelectionTest.cpp b/gfx/thebes/test/gfxFontSelectionTest.cpp index 57dc91b395b8..31185a034e9d 100644 --- a/gfx/thebes/test/gfxFontSelectionTest.cpp +++ b/gfx/thebes/test/gfxFontSelectionTest.cpp @@ -184,7 +184,7 @@ struct TestEntry { #elif defined(XP_MACOSX) if (strcmp(platform, "macosx")) return; -#elif defined(MOZ_ENABLE_PANGO) +#elif defined(XP_UNIX) if (strcmp(platform, "gtk2-pango")) return; #else diff --git a/intl/build/Makefile.in b/intl/build/Makefile.in index 1e17cf725497..34bb4b1e1e6e 100644 --- a/intl/build/Makefile.in +++ b/intl/build/Makefile.in @@ -106,7 +106,7 @@ endif include $(topsrcdir)/config/rules.mk -ifdef MOZ_ENABLE_PANGO +ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) EXTRA_DSO_LDOPTS += \ $(MOZ_PANGO_LIBS) \ $(NULL) diff --git a/intl/locale/src/Makefile.in b/intl/locale/src/Makefile.in index 9e06dd688383..8346b58b3833 100644 --- a/intl/locale/src/Makefile.in +++ b/intl/locale/src/Makefile.in @@ -81,6 +81,10 @@ EXPORT_RESOURCE = \ $(srcdir)/language.properties \ $(NULL) +EXTRA_JS_MODULES = \ + PluralForm.jsm \ + $(NULL) + # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 diff --git a/intl/locale/src/PluralForm.jsm b/intl/locale/src/PluralForm.jsm new file mode 100644 index 000000000000..472f3cecb718 --- /dev/null +++ b/intl/locale/src/PluralForm.jsm @@ -0,0 +1,176 @@ +/* ***** 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 Plural Form l10n Code. + * + * The Initial Developer of the Original Code is + * Edward Lee . + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 ***** */ + +EXPORTED_SYMBOLS = [ "PluralForm" ]; + +/** + * This module provides the PluralForm object which contains a method to figure + * out which plural form of a word to use for a given number based on the + * current localization. + * + * See: http://developer.mozilla.org/en/docs/Localization_and_Plurals + * + * List of methods: + * + * string pluralForm + * get(int aNum, string aWords) + * + * int numForms + * numForms() + */ + +const Cc = Components.classes; +const Ci = Components.interfaces; + +const kIntlProperties = "chrome://global/locale/intl.properties"; + +// These are the available plural functions that give the appropriate index +// based on the plural rule number specified. The first element is the number +// of plural forms and the second is the function to figure out the index. +let gFunctions = [ + // 0: Chinese + [1, function(n) 0], + // 1: English + [2, function(n) n!=1?1:0], + // 2: French + [2, function(n) n>1?1:0], + // 3: Latvian + [3, function(n) n%10==1&&n%100!=11?1:n!=0?2:0], + // 4: Scottish Gaelic + [3, function(n) n==1?0:n==2?1:2], + // 5: Romanian + [3, function(n) n==1?0:n==0||n%100>0&&n%100<20?1:2], + // 6: Lithuanian + [3, function(n) n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?2:1], + // 7: Russian + [3, function(n) n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2], + // 8: Slovak + [3, function(n) n==1?0:n>=2&&n<=4?1:2], + // 9: Polish + [3, function(n) n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2], + // 10: Slovenian + [4, function(n) n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3], + // 11: Irish Gaeilge + [5, function(n) n==1?0:n==2?1:n>=3&&n<=6?2:n>=7&&n<=10?3:4], + // 12: Arabic + [4, function(n) n==1?0:n==2?1:n<=10?2:3], + // 13: Maltese + [4, function(n) n==1?0:n==0||n%100>0&&n%100<=10?1:n%100>10&&n%100<20?2:3], + // 14: Macedonian + [3, function(n) n%10==1?0:n%10==2?1:2], +]; + +let gNumForms; + +let PluralForm = { + /** + * Get the correct plural form of a word based on the number + * + * @param aNum + * The number to decide which plural form to use + * @param aWords + * A semi-colon (;) separated string of words to pick the plural form + * @return The appropriate plural form of the word + */ + get: (function initGetPluralForm() + { + // initGetPluralForm gets called right away when this module is loaded and + // creates getPluralForm function. The function it creates is based on the + // value of pluralRule specified in the intl stringbundle. + // See: http://developer.mozilla.org/en/docs/Localization_and_Plurals + + // Get the plural rule number from the intl stringbundle + let ruleNum = Number(Cc["@mozilla.org/intl/stringbundle;1"]. + getService(Ci.nsIStringBundleService).createBundle(kIntlProperties). + GetStringFromName("pluralRule")); + + // Default to "all plural" if the value is out of bounds or invalid + if (ruleNum < 0 || ruleNum >= gFunctions.length || isNaN(ruleNum)) { + log(["Invalid rule number: ", ruleNum, " -- defaulting to 0"]); + ruleNum = 0; + } + + // Get the desired pluralRule function + let pluralFunc; + [gNumForms, pluralFunc] = gFunctions[ruleNum]; + + // Return a function that gets the right plural form + return function(aNum, aWords) { + // Figure out which index to use for the semi-colon separated words + let index = pluralFunc(aNum ? Number(aNum) : 0); + let words = aWords ? aWords.split(/;/) : [""]; + + // Explicitly check bounds to avoid strict warnings + let ret = index < words.length ? words[index] : undefined; + + // Check for array out of bounds or empty strings + if ((ret == undefined) || (ret == "")) { + // Report the caller to help figure out who is causing badness + let caller = this.get.caller ? this.get.caller.name : "top"; + + // Display a message in the error console + log(["Index #", index, " of '", aWords, "' for value ", aNum, + " is invalid -- plural rule #", ruleNum, "; called by ", caller]); + + // Default to the first entry (which might be empty, but not undefined) + ret = words[0]; + } + + return ret; + }; + })(), + + /** + * Get the number of forms for the current plural rule + * + * @return The number of forms + */ + numForms: function() gNumForms, +}; + +/** + * Private helper function to log errors to the error console and command line + * + * @param aMsg + * Error message to log or an array of strings to concat + */ +function log(aMsg) +{ + let msg = "PluralForm.jsm: " + (aMsg.join ? aMsg.join("") : aMsg); + Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). + logStringMessage(msg); + dump(msg + "\n"); +} diff --git a/widget/src/cocoa/nsIMenuCommandDispatcher.idl b/intl/locale/tests/unit/test_pluralForm_english.js similarity index 59% rename from widget/src/cocoa/nsIMenuCommandDispatcher.idl rename to intl/locale/tests/unit/test_pluralForm_english.js index a836a77f256c..db3638dd8213 100644 --- a/widget/src/cocoa/nsIMenuCommandDispatcher.idl +++ b/intl/locale/tests/unit/test_pluralForm_english.js @@ -1,7 +1,5 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 +/* ***** 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 @@ -13,15 +11,14 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla Communicator. + * The Original Code is Plural Form l10n Test Code. * * The Initial Developer of the Original Code is - * Netscape Communications Corp. - * Portions created by the Initial Developer are Copyright (C) 1999 + * Edward Lee . + * Portions created by the Initial Developer are Copyright (C) 2008 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Mike Pinkerton * * 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,30 +34,25 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" +/** + * This unit test makes sure the plural form for the default language (by + * development), English, is working for the PluralForm javascript module. + */ +Components.utils.import("resource://gre/modules/PluralForm.jsm"); -interface nsIMenuItem; - - -// -// nsIMenuCommandDispatcher -// -// A central manager for registering and unregistering CommandIDs -// and their associated content node in the DOM. -// - -[scriptable, uuid(d1969b7e-1dd1-11b2-a442-c5a01ae643d1)] -interface nsIMenuCommandDispatcher : nsISupports +function run_test() { - // Given a menu item, creates a unique 4-character command ID and - // maps it to the item. Returns the id for use by the client. - unsigned long Register ( in nsIMenuItem aItem ) ; - - // Removes the mapping between the given 4-character command ID - // and its associated menu item. - void Unregister ( in unsigned long aCommandID ) ; - -}; // nsIMenuCommandDispatcher + // English has 2 plural forms + do_check_eq(2, PluralForm.numForms()); + // Make sure for good inputs, things work as expected + for (var num = 0; num <= 200; num++) + do_check_eq(num == 1 ? "word" : "words", PluralForm.get(num, "word;words")); + // Not having enough plural forms defaults to the first form + do_check_eq("word", PluralForm.get(2, "word")); + + // Empty forms defaults to the first form + do_check_eq("word", PluralForm.get(2, "word;")); +} diff --git a/intl/lwbrk/src/Makefile.in b/intl/lwbrk/src/Makefile.in index 0bce229b8b08..97a15c9df798 100644 --- a/intl/lwbrk/src/Makefile.in +++ b/intl/lwbrk/src/Makefile.in @@ -58,7 +58,7 @@ CPPSRCS = \ nsSemanticUnitScanner.cpp \ $(NULL) -ifdef MOZ_ENABLE_PANGO +ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) CPPSRCS += \ nsPangoBreaker.cpp \ $(NULL) @@ -84,7 +84,7 @@ endif include $(topsrcdir)/config/rules.mk -ifdef MOZ_ENABLE_PANGO +ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) CXXFLAGS += \ $(MOZ_PANGO_CFLAGS) \ $(NULL) diff --git a/intl/unicharutil/public/Makefile.in b/intl/unicharutil/public/Makefile.in index 491c5273e523..87bb59c0cb83 100644 --- a/intl/unicharutil/public/Makefile.in +++ b/intl/unicharutil/public/Makefile.in @@ -46,7 +46,6 @@ MODULE = unicharutil EXPORTS = \ nsICaseConversion.h \ - nsIOrderIdFormater.h \ nsITextTransform.h \ nsIUGenCategory.h \ nsUnicharUtilCIID.h \ diff --git a/intl/unicharutil/src/nsCharsOrderIdFormater.cpp b/intl/unicharutil/src/nsCharsOrderIdFormater.cpp deleted file mode 100644 index 3cfd6cb5a189..000000000000 --- a/intl/unicharutil/src/nsCharsOrderIdFormater.cpp +++ /dev/null @@ -1,159 +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 mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - -#include "pratom.h" -#include "nsUUDll.h" -#include "nsCharsOrderIdFormater.h" - - -nsCharsOrderIdFormater::nsCharsOrderIdFormater( nsCharsList* aList) -{ - mList = aList; - mBase = aList->Length(); -} - -nsCharsOrderIdFormater::~nsCharsOrderIdFormater() -{ - delete mList; -} - -NS_IMETHOD ToString( PRUint32 aOrder, nsString& aResult) -{ - aResult = ""; - - PRUint32 current; - PRUint32 remain = aOrder; - - do { - current = aOrder % mBase; - remain = aOrder / mBase; - aResult.Insert(mList->Get(current),0); - - } while( remain != 0); - return NS_OK; -} - -NS_IMPL_ISUPPORTS1(nsCharsOrderIdFormater, nsIOrderIdFormater) - -class nsCharsOrderIdFormaterFactory : public nsIFactory { - NS_DECL_ISUPPORTS -public: - nsCharsOrderIdFormaterFactory(const nsCID &aCID) { - mCID = aCID; - }; - virtual ~nsCharsOrderIdFormaterFactory() { - }; - NS_IMETHOD CreateInstance(nsISupports *aDelegate, - const nsIID &aIID, - void **aResult); - NS_IMETHOD LockFactory(PRBool aLock) { - return NS_OK; - }; - -private: - nsCID mCID; -} - -NS_IMPL_ISUPPORTS1(nsCharsOrderIdFormaterFactory, nsIFactory) - -NS_IMETHODIMP nsCharsOrderIdFormaterFactory::CreateInstance( - nsISupports *aDelegate, - const nsIID &aIID, - void **aResult) -{ - if(NULL == aResult) - return NS_ERROR_NULL_POINTER; - *aResult = NULL; - - nsISupports *inst = nsnull; - if(mCID.Equals(kLowerAToZOrderIdCID)) { - inst = new nsCharOrderIdFormater(new nsRangeCharsList('a', 'z')); - } else if(mCID.Equals(kUpperAToZOrderIdCID)) { - inst = new nsCharOrderIdFormater(new nsRangeCharsList('A', 'Z')); - } else if(mCID.Equals(k0To9OrderIdCID)) { - inst = new nsCharOrderIdFormater(new nsRangeCharsList('0', '9')); - } else if(mCID.Equals(kHeavenlyStemOrderIdCID)) { - static PRUnichar gHeavenlyStemList[] = { - 0x7532, 0x4e59, 0x4e19, 0x4e01, 0x620a, - 0x5df1, 0x5e9a, 0x8f9b, 0x58ce, 0x7678 - }; - nsAutoString tmp(gHeavenlyStemList, - sizeof(gHeavenlyStemList)/sizeof(PRUnichar)); - inst = new nsCharOrderIdFormater(new nsStringCharsList(tmp)); - } else if(mCID.Equals(kEarthlyBranchOrderIdCID)) { - static PRUnichar gEarthlyBranchList[] = { - 0x5b50, 0x4e11, 0x5bc5, 0x536f, 0x8fb0, 0x5df3, - 0x5348, 0x672a, 0x7533, 0x9149, 0x620c, 0x4ea5 - }; - nsAutoString tmp(gEarthlyBranchList, - sizeof(gEarthlyBranchList)/sizeof(PRUnichar)); - inst = new nsCharOrderIdFormater(new nsStringCharsList(tmp)); - } else if(mCID.Equals(kBoPoMoFoOrderIdCID)) { - // - // Note: Although Unicode standard encode 0x312A-0x312C as BoPoMoFo, - // these three are origional designed for Mid China dialet - // and have never been used for Maderine. Therefore, we - // do not use them for order id. - inst = new nsCharOrderIdFormater(new nsRangeCharsList(0x3105, 0x3129)); - } else if(mCID.Equals(kKatakanaOrderIdCID)) { - // XXX fake list- need to verify with momoi about the real seq. - static PRUnichar gKatakanaList[] = { - 0x3042, 0x3044, 0x3046, 0x3048, 0x304a - }; - nsAutoString tmp(gKatakanaClassList, sizeof(gKatakanaList)/sizeof(PRUnichar)); - inst = new nsCharOrderIdFormater(new nsStringCharsList(tmp)); - } else if(mCID.Equals(kHiraganaOrderIdCID)) { - // XXX fake list- need to verify with momoi about the real seq. - static PRUnichar gHiraganaList[] = { - 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa - }; - nsAutoString tmp(gHiraganaList, sizeof(gHiraganaList)/sizeof(PRUnichar)); - inst = new nsCharOrderIdFormater(new nsStringCharsList(tmp)); - } else { - return NS_ERROR_ILLEGAL_VALUE; - } - - - if(NULL == inst ) - return NS_ERROR_OUT_OF_MEMORY; - nsresult res = inst->QueryInterface(aIID, aResult); - if(NS_FAILED(res)) { - delete inst; - } - return res; -} - diff --git a/intl/unicharutil/src/nsRangeCharsList.cpp b/intl/unicharutil/src/nsRangeCharsList.cpp deleted file mode 100644 index 16213f9b9e04..000000000000 --- a/intl/unicharutil/src/nsRangeCharsList.cpp +++ /dev/null @@ -1,59 +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 mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - -#include "nsRangeCharsList.h" - -nsRangeCharsList::nsRangeCharsList(PRUnichar aStart, PRUnichar aEnd) -{ - mStart = aStart; - mEnd = aEnd; -} -nsRangeCharsList::~nsRangeCharsList() -{ -} - -PRUnichar nsRangeCharsList::Get( PRUint32 aIdx) -{ - return mStart + aIdx; -} - - -PRUint32 nsRangeCharsList::Length() -{ - return mEnd - mStart + 1; -} - diff --git a/intl/unicharutil/src/nsStringCharsList.cpp b/intl/unicharutil/src/nsStringCharsList.cpp deleted file mode 100644 index 6de7fde5230b..000000000000 --- a/intl/unicharutil/src/nsStringCharsList.cpp +++ /dev/null @@ -1,57 +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 mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** */ - -#include "nsStringCharsList.h" - -nsStringCharsList::nsStringCharsList(nsString& aList) - : mList(aList) -{ -} - -nsStringCharsList::~nsStringCharsList() -{ -} - -PRUnichar nsStringCharsList::Get( PRUint32 aIdx) -{ - return (PRUnichar)mList(aIdx); -} - -PRUint32 nsStringCharsList::Length() -{ - return mList.Length(); -} diff --git a/jpeg/Makefile.in b/jpeg/Makefile.in index 7b949cdf3421..fb422455957d 100644 --- a/jpeg/Makefile.in +++ b/jpeg/Makefile.in @@ -47,6 +47,10 @@ LIBRARY_NAME = mozjpeg ifeq ($(OS_ARCH),WINNT) LIBRARY_NAME = jpeg$(MOZ_BITS)$(VERSION_NUMBER) +# FIXME: bug 413019 +ifndef GNU_CC +OS_COMPILE_CFLAGS += -GL- +endif endif GRE_MODULE = 1 diff --git a/jpeg/jconfig.h b/jpeg/jconfig.h index e7f0c63ecc66..f61cab5c8c42 100644 --- a/jpeg/jconfig.h +++ b/jpeg/jconfig.h @@ -74,13 +74,6 @@ */ #undef RIGHT_SHIFT_IS_UNSIGNED -#ifdef XP_MAC /* Macintosh */ - -#define ALIGN_TYPE long /* for sane memory alignment */ -#define NO_GETENV /* we do have the function, but it's dead */ - -#endif /* XP_MAC */ - #endif /* JPEG_INTERNALS */ @@ -101,3 +94,13 @@ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ + +/* SSE* alignment support - only use on platforms that support declspec and __attribute__ */ + +#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__) +#define ALIGN16_const_vector_short(name) __declspec(align(16)) const short name[8] +#define ALIGN16_const_vector_uchar(name) __declspec(align(16)) const unsigned char name[16] +#else +#define ALIGN16_const_vector_short(name) const short name[8] __attribute__ ((aligned (16))) +#define ALIGN16_const_vector_uchar(name) const unsigned char name[16] __attribute__ ((aligned (16))) +#endif ! XP_WIN32 && _M_IX86 && !__GNUC diff --git a/jpeg/jdapimin.c b/jpeg/jdapimin.c index 6d4a675883f7..c07918c2278d 100644 --- a/jpeg/jdapimin.c +++ b/jpeg/jdapimin.c @@ -21,14 +21,19 @@ #include "jpeglib.h" #ifdef HAVE_MMX_INTEL_MNEMONICS +#include "intrin.h" int MMXAvailable; static int mmxsupport(); #endif -#ifdef HAVE_SSE2_INTEL_MNEMONICS +#ifdef HAVE_SSE2_INTRINSICS int SSE2Available = 0; +#ifdef HAVE_SSE2_INTEL_MNEMONICS static int sse2support(); -#endif +#else +static int sse2supportGCC(); +#endif ! HAVE_SSE2_INTEL_MNEMONICS +#endif ! HAVE_SSE2_INTRINSICS /* @@ -57,7 +62,17 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) cpuidDetected = 1; } -#endif +#else +#ifdef HAVE_SSE2_INTRINSICS + static int cpuidDetected = 0; + + if(!cpuidDetected) { + SSE2Available = sse2supportGCC(); + cpuidDetected = 1; + } + +#endif ! HAVE_SSE2_INTRINSICS +#endif ! HAVE_MMX_INTEL_MNEMONICS /* For debugging purposes, zero the whole master structure. * But error manager pointer is already there, so save and restore it. @@ -427,73 +442,48 @@ jpeg_finish_decompress (j_decompress_ptr cinfo) #ifdef HAVE_MMX_INTEL_MNEMONICS - - static int mmxsupport() { - int mmx_supported = 0; + int CPUInfo[4]; - _asm { - pushfd //Save Eflag to stack - pop eax //Get Eflag from stack into eax - mov ecx, eax //Make another copy of Eflag in ecx - xor eax, 0x200000 //Toggle ID bit in Eflag [i.e. bit(21)] - push eax //Save modified Eflag back to stack - - popfd //Restored modified value back to Eflag reg - pushfd //Save Eflag to stack - pop eax //Get Eflag from stack - xor eax, ecx //Compare the new Eflag with the original Eflag - jz NOT_SUPPORTED //If the same, CPUID instruction is not supported, - //skip following instructions and jump to - //NOT_SUPPORTED label - - xor eax, eax //Set eax to zero - - cpuid - - cmp eax, 1 //make sure eax return non-zero value - jl NOT_SUPPORTED //If eax is zero, mmx not supported - - xor eax, eax //set eax to zero - inc eax //Now increment eax to 1. This instruction is - //faster than the instruction "mov eax, 1" - - cpuid - - and edx, 0x00800000 //mask out all bits but mmx bit(24) - cmp edx, 0 // 0 = mmx not supported - jz NOT_SUPPORTED // non-zero = Yes, mmx IS supported - - mov mmx_supported, 1 //set return value to 1 - -NOT_SUPPORTED: - mov eax, mmx_supported //move return value to eax - - } - - return mmx_supported; + __cpuid(CPUInfo, 1); + if (CPUInfo[3] & (0x1 << 23)) + return 1; + else + return 0; } #endif #ifdef HAVE_SSE2_INTEL_MNEMONICS - static int sse2support() { - int sse2available = 0; - int my_edx; - _asm - { - mov eax, 01 - cpuid - mov my_edx, edx - } - if (my_edx & (0x1 << 26)) - sse2available = 1; - else sse2available = 2; + int CPUInfo[4]; - return sse2available; + __cpuid(CPUInfo, 1); + if (CPUInfo[3] & (0x1 << 26)) + return 1; + else + return 2; } +#else +#ifdef HAVE_SSE2_INTRINSICS +static int sse2supportGCC() +{ -#endif + /* Mac Intel started with Core Duo chips which have SSE2 Support */ + +#if defined(__GNUC__) && defined(__i386__) +#if defined(XP_MACOSX) + return 1; +#endif ! XP_MACOSX +#endif ! GNUC && i386 + + /* Add checking for SSE2 support for other platforms here */ + + /* We don't have SSE2 intrinsics support */ + + return 2; +} +#endif ! HAVE_SSE2_INTRINSICS +#endif ! HAVE_SSE2_INTEL_MNEMONICS diff --git a/jpeg/jdcolor.c b/jpeg/jdcolor.c index 6c04dfe8aa1b..a8b8db5284b9 100644 --- a/jpeg/jdcolor.c +++ b/jpeg/jdcolor.c @@ -11,6 +11,7 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" +#include "jconfig.h" /* Private subobject */ @@ -18,11 +19,15 @@ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ + /* These fields are not needed anymore as these are now static tables */ + +#if 0 /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +#endif } my_color_deconverter; typedef my_color_deconverter * my_cconvert_ptr; @@ -61,6 +66,191 @@ typedef my_color_deconverter * my_cconvert_ptr; #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. @@ -69,6 +259,10 @@ typedef my_color_deconverter * my_cconvert_ptr; LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) { + + /* The code below was used to generate the static tables above */ + +#if 0 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; int i; INT32 x; @@ -102,6 +296,7 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; } +#endif ! 0 } @@ -123,16 +318,12 @@ ycc_rgb_convert (j_decompress_ptr cinfo, { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; + JSAMPLE * range_limit_y; + JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; + JSAMPLE * range_limit = cinfo->sample_range_limit; SHIFT_TEMPS while (--num_rows >= 0) { @@ -145,12 +336,13 @@ ycc_rgb_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); + range_limit_y = range_limit + y; /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; - outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + outptr[RGB_RED] = range_limit_y[Cr_r_tab[cr]]; + outptr[RGB_GREEN] = range_limit_y[ + ((int) RIGHT_SHIFT(Cb_g_tab[cb] + Cr_g_tab[cr], SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr[RGB_BLUE] = range_limit_y[Cb_b_tab[cb]]; outptr += RGB_PIXELSIZE; } } @@ -238,7 +430,6 @@ gray_rgb_convert (j_decompress_ptr cinfo, * Adobe-style YCCK->CMYK conversion. * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same * conversion as above, while passing K (black) unchanged. - * We assume build_ycc_rgb_table has been called. */ METHODDEF(void) @@ -248,16 +439,13 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; + JSAMPLE * range_limit_y; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { @@ -271,12 +459,13 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); + range_limit_y = range_limit + MAXJSAMPLE - y; /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + outptr[0] = range_limit_y + Cr_r_tab[cr]; /* red */ + outptr[1] = range_limit_y + /* green */ + ((int) RIGHT_SHIFT(Cb_g_tab[cb] + Cr_g_tab[cr], + SCALEBITS)); + outptr[2] = range_limit_y + Cb_b_tab[cb]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ outptr += 4; diff --git a/jpeg/jddctmgr.c b/jpeg/jddctmgr.c index afdb180af134..3a0e8fd399a1 100644 --- a/jpeg/jddctmgr.c +++ b/jpeg/jddctmgr.c @@ -19,7 +19,9 @@ #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ +#ifdef HAVE_SSE2_INTRINSICS extern int SSE2Available; +#endif /* * The decompressor input side (jdinput.c) saves away the appropriate diff --git a/jpeg/jdmaster.c b/jpeg/jdmaster.c index 2802c5b7b297..37ae7866ef5b 100644 --- a/jpeg/jdmaster.c +++ b/jpeg/jdmaster.c @@ -15,6 +15,104 @@ #include "jinclude.h" #include "jpeglib.h" +/* Use static array */ + +const char static_range_table[ (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE) ]={ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, + 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, + 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f +}; /* Private state */ @@ -248,6 +346,14 @@ LOCAL(void) prepare_range_limit_table (j_decompress_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { + /* Use a static table and allow negative subscripts of simple table */ + + cinfo->sample_range_limit = (JSAMPLE *) static_range_table + (MAXJSAMPLE+1); + + /* This code is used to create the values for the static table used above */ + +#if 0 + JSAMPLE * table; int i; @@ -270,6 +376,8 @@ prepare_range_limit_table (j_decompress_ptr cinfo) (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); + +#endif ! 0 } diff --git a/jpeg/jmorecfg.h b/jpeg/jmorecfg.h index 43245dd6cef7..f912c5b96736 100644 --- a/jpeg/jmorecfg.h +++ b/jpeg/jmorecfg.h @@ -112,8 +112,18 @@ typedef short JCOEF; /* SSE2 code appears broken for some cpus (bug 247437) */ #define HAVE_SSE2_INTEL_MNEMONICS +#define HAVE_SSE2_INTRINSICS #endif +#if defined(__GNUC__) && defined(__i386__) +#if defined(XP_MACOSX) +#define HAVE_SSE2_INTRINSICS +#endif ! XP_MACOSX +#endif ! GNUC && i386 + +/* Add support for other platforms here */ + + /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination diff --git a/js/src/config/SunOS5.10.mk b/js/src/config/SunOS5.10.mk new file mode 100644 index 000000000000..dc0b0a091898 --- /dev/null +++ b/js/src/config/SunOS5.10.mk @@ -0,0 +1,50 @@ +# -*- Mode: makefile -*- +# +# ***** 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 Communicator client code, released +# March 31, 1998. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1999 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# 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 ***** + +# +# Config stuff for SunOS5.10, using vendor gcc and NSPR +# + +include $(DEPTH)/config/SunOS5.5.mk + +INCLUDES += -I/usr/sfw/include/mozilla/nspr +OTHER_LIBS += -L/usr/sfw/lib/mozilla -R/usr/sfw/lib/mozilla + +CC=gcc + diff --git a/js/src/js.cpp b/js/src/js.cpp index fe2d46c6565e..87e41c7b412f 100644 --- a/js/src/js.cpp +++ b/js/src/js.cpp @@ -524,7 +524,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc) break; #ifdef MOZ_SHARK case 'k': - js_ConnectShark(); + JS_ConnectShark(); break; #endif default: @@ -1694,7 +1694,7 @@ DumpHeap(JSContext *cx, uintN argc, jsval *vp) static JSBool DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - JSAtom *atom; + jsid id; JSObject *obj2; JSProperty *prop; JSBool ok; @@ -1707,19 +1707,18 @@ DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) if (!JS_ValueToObject(cx, argv[0], &obj)) return JS_FALSE; argv[0] = OBJECT_TO_JSVAL(obj); - atom = js_ValueToStringAtom(cx, argv[1]); - if (!atom) + if (!js_ValueToStringId(cx, argv[1], &id)) return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) + if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) return JS_FALSE; if (!prop) { ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL, JSPROP_EXPORTED, NULL); } else { - ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); + ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs); if (ok) { attrs |= JSPROP_EXPORTED; - ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); + ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs); } OBJ_DROP_PROPERTY(cx, obj2, prop); } @@ -2448,7 +2447,7 @@ EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, ok = JS_FALSE; goto out; } - v = BOOLEAN_TO_JSVAL(v); + v = BOOLEAN_TO_JSVAL(lazy); ok = JS_SetProperty(cx, sobj, "lazy", &v); if (!ok) goto out; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index deccf6366879..510c41e21bb5 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -200,8 +200,7 @@ JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, } switch (c) { case 'b': - if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *))) - return JS_FALSE; + *va_arg(ap, JSBool *) = js_ValueToBoolean(*sp); break; case 'c': if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *))) @@ -259,6 +258,7 @@ JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, obj = js_ValueToFunctionObject(cx, sp, 0); if (!obj) return JS_FALSE; + *sp = OBJECT_TO_JSVAL(obj); *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj); break; case 'v': @@ -459,7 +459,7 @@ JS_RemoveArgumentFormatter(JSContext *cx, const char *format) JS_PUBLIC_API(JSBool) JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp) { - JSBool ok, b; + JSBool ok; JSObject *obj; JSString *str; jsdouble d, *dp; @@ -496,10 +496,8 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp) } break; case JSTYPE_BOOLEAN: - ok = js_ValueToBoolean(cx, v, &b); - if (ok) - *vp = BOOLEAN_TO_JSVAL(b); - break; + *vp = js_ValueToBoolean(v); + return JS_TRUE; default: { char numBuf[12]; JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type); @@ -579,7 +577,8 @@ JS_PUBLIC_API(JSBool) JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp) { CHECK_REQUEST(cx); - return js_ValueToBoolean(cx, v, bp); + *bp = js_ValueToBoolean(v); + return JS_TRUE; } JS_PUBLIC_API(JSType) @@ -2528,7 +2527,7 @@ JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type) sizeof(JSString)); if (!str) return NULL; - JSSTRING_INIT(str, chars, length); + JSFLATSTR_INIT(str, chars, length); return str; } @@ -2565,23 +2564,15 @@ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) JS_PUBLIC_API(JSBool) JS_ValueToId(JSContext *cx, jsval v, jsid *idp) { - JSAtom *atom; - CHECK_REQUEST(cx); - if (JSVAL_IS_INT(v)) { + if (JSVAL_IS_INT(v)) *idp = INT_JSVAL_TO_JSID(v); - } else { #if JS_HAS_XML_SUPPORT - if (JSVAL_IS_OBJECT(v)) { - *idp = OBJECT_JSVAL_TO_JSID(v); - return JS_TRUE; - } + else if (!JSVAL_IS_PRIMITIVE(v)) + *idp = OBJECT_JSVAL_TO_JSID(v); #endif - atom = js_ValueToStringAtom(cx, v); - if (!atom) - return JS_FALSE; - *idp = ATOM_TO_JSID(atom); - } + else + return js_ValueToStringId(cx, v, idp); return JS_TRUE; } @@ -2769,7 +2760,7 @@ bad: JS_PUBLIC_API(JSClass *) JS_GetClass(JSContext *cx, JSObject *obj) { - return GC_AWARE_GET_CLASS(cx, obj); + return OBJ_GET_CLASS(cx, obj); } #else JS_PUBLIC_API(JSClass *) @@ -2811,7 +2802,7 @@ JS_GetPrivate(JSContext *cx, JSObject *obj) jsval v; JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); - v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE); + v = obj->fslots[JSSLOT_PRIVATE]; if (!JSVAL_IS_INT(v)) return NULL; return JSVAL_TO_PRIVATE(v); @@ -2821,7 +2812,7 @@ JS_PUBLIC_API(JSBool) JS_SetPrivate(JSContext *cx, JSObject *obj, void *data) { JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data)); + obj->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(data); return JS_TRUE; } @@ -2840,7 +2831,7 @@ JS_GetPrototype(JSContext *cx, JSObject *obj) JSObject *proto; CHECK_REQUEST(cx); - proto = GC_AWARE_GET_PROTO(cx, obj); + proto = OBJ_GET_PROTO(cx, obj); /* Beware ref to dead object (we may be called from obj's finalizer). */ return proto && proto->map ? proto : NULL; @@ -2861,7 +2852,7 @@ JS_GetParent(JSContext *cx, JSObject *obj) { JSObject *parent; - parent = GC_AWARE_GET_PARENT(cx, obj); + parent = OBJ_GET_PARENT(cx, obj); /* Beware ref to dead object (we may be called from obj's finalizer). */ return parent && parent->map ? parent : NULL; @@ -3782,7 +3773,7 @@ JS_ClearScope(JSContext *cx, JSObject *obj) obj->map->ops->clear(cx, obj); /* Clear cached class objects on the global object. */ - if (JS_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) { + if (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) { int key; for (key = JSProto_Null; key < JSProto_LIMIT; key++) @@ -3870,7 +3861,7 @@ prop_iter_finalize(JSContext *cx, JSObject *obj) jsint i; JSIdArray *ida; - v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX); + v = obj->fslots[JSSLOT_ITER_INDEX]; if (JSVAL_IS_VOID(v)) return; @@ -3892,10 +3883,10 @@ prop_iter_trace(JSTracer *trc, JSObject *obj) JSIdArray *ida; jsid id; - v = GC_AWARE_GET_SLOT(trc->context, obj, JSSLOT_PRIVATE); + v = obj->fslots[JSSLOT_PRIVATE]; JS_ASSERT(!JSVAL_IS_VOID(v)); - i = JSVAL_TO_INT(OBJ_GET_SLOT(trc->context, obj, JSSLOT_ITER_INDEX)); + i = JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]); if (i < 0) { /* Native case: just mark the next property to visit. */ sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v); @@ -4653,6 +4644,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, const char *filename, uintN lineno) { JSFunction *fun; + JSTempValueRooter tvr; JSAtom *funAtom, *argAtom; uintN i; @@ -4663,12 +4655,15 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, funAtom = js_Atomize(cx, name, strlen(name), 0); if (!funAtom) { fun = NULL; - goto out; + goto out2; } } fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom); if (!fun) - goto out; + goto out2; + + /* From this point the control must flow through the label out. */ + JS_PUSH_TEMP_ROOT_FUNCTION(cx, fun, &tvr); for (i = 0; i < nargs; i++) { argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0); if (!argAtom) { @@ -4707,6 +4702,10 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, #endif out: + cx->weakRoots.newborn[JSTRACE_FUNCTION] = fun; + JS_POP_TEMP_ROOT(cx, &tvr); + + out2: LAST_FRAME_CHECKS(cx, fun); return fun; } @@ -5234,13 +5233,13 @@ JS_GetStringChars(JSString *str) if (s) { memcpy(s, JSSTRDEP_CHARS(str), n * sizeof *s); s[n] = 0; - JSSTRING_INIT(str, s, n); + JSFLATSTR_INIT(str, s, n); } else { s = JSSTRDEP_CHARS(str); } } else { - JSSTRING_CLEAR_MUTABLE(str); - s = str->u.chars; + JSFLATSTR_CLEAR_MUTABLE(str); + s = JSFLATSTR_CHARS(str); } return s; } @@ -5266,7 +5265,7 @@ JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length) str = js_NewString(cx, chars, length); if (!str) return str; - JSSTRING_SET_MUTABLE(str); + JSFLATSTR_SET_MUTABLE(str); return str; } diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index d4a3be7a4c6f..40e784b581dd 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1991,17 +1991,12 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp) if (!ok) break; - if (mode > MAP) { - if (*invokevp == JSVAL_NULL) { - cond = JS_FALSE; - } else if (JSVAL_IS_BOOLEAN(*invokevp)) { - cond = JSVAL_TO_BOOLEAN(*invokevp); - } else { - ok = js_ValueToBoolean(cx, *invokevp, &cond); - if (!ok) - goto out; - } - } + if (mode > MAP) + cond = js_ValueToBoolean(*invokevp); +#ifdef __GNUC__ /* quell GCC overwarning */ + else + cond = JS_FALSE; +#endif switch (mode) { case FOREACH: diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index e278365b1b4d..24d463088409 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -57,7 +57,7 @@ #include "jsscan.h" #include "jsstr.h" -JS_FRIEND_API(const char *) +const char * js_AtomToPrintableString(JSContext *cx, JSAtom *atom) { return js_ValueToPrintableString(cx, ATOM_KEY(atom)); @@ -621,16 +621,16 @@ js_AtomizeDouble(JSContext *cx, jsdouble d) JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { + jsval v; JSAtomState *state; JSDHashTable *table; JSAtomHashEntry *entry; JSString *key; uint32 gen; - jsval v; - JS_ASSERT((flags & - ~(ATOM_PINNED | ATOM_INTERNED | ATOM_TMPSTR | ATOM_NOCOPY)) - == 0); + JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY))); + JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR); + state = &cx->runtime->atomState; table = &state->stringAtoms; @@ -638,49 +638,66 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, str, JS_DHASH_ADD)); if (!entry) goto failed_hash_add; - if (entry->keyAndFlags == 0) { + if (entry->keyAndFlags != 0) { + key = (JSString *)ATOM_ENTRY_KEY(entry); + } else { + /* + * We created a new hashtable entry. Unless str is already allocated + * from the GC heap and flat, we have to release state->lock as + * string construction is a complex operation. For example, it can + * trigger GC which may rehash the table and make the entry invalid. + */ ++state->tablegen; - gen = state->tablegen; - JS_UNLOCK(&state->lock, cx); - - if (flags & ATOM_TMPSTR) { - if (flags & ATOM_NOCOPY) { - key = js_NewString(cx, str->u.chars, str->length); - if (!key) - return NULL; - - /* Transfer ownership of str->chars to GC-controlled string. */ - str->u.chars = NULL; - } else { - key = js_NewStringCopyN(cx, str->u.chars, str->length); - if (!key) - return NULL; - } - } else { - JS_ASSERT((flags & ATOM_NOCOPY) == 0); - if (!JS_MakeStringImmutable(cx, str)) - return NULL; + if (!(flags & ATOM_TMPSTR) && JSSTRING_IS_FLAT(str)) { + JSFLATSTR_CLEAR_MUTABLE(str); key = str; - } - - JS_LOCK(&state->lock, cx); - if (state->tablegen == gen) { - JS_ASSERT(entry->keyAndFlags == 0); } else { - entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key, - JS_DHASH_ADD)); - if (!entry) - goto failed_hash_add; - if (entry->keyAndFlags != 0) - goto finish; - ++state->tablegen; + gen = state->tablegen; + JS_UNLOCK(&state->lock, cx); + + if (flags & ATOM_TMPSTR) { + if (flags & ATOM_NOCOPY) { + key = js_NewString(cx, JSFLATSTR_CHARS(str), + JSFLATSTR_LENGTH(str)); + if (!key) + return NULL; + + /* Finish handing off chars to the GC'ed key string. */ + str->u.chars = NULL; + } else { + key = js_NewStringCopyN(cx, JSFLATSTR_CHARS(str), + JSFLATSTR_LENGTH(str)); + if (!key) + return NULL; + } + } else { + JS_ASSERT(JSSTRING_IS_DEPENDENT(str)); + if (!js_UndependString(cx, str)) + return NULL; + key = str; + } + + JS_LOCK(&state->lock, cx); + if (state->tablegen == gen) { + JS_ASSERT(entry->keyAndFlags == 0); + } else { + entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key, + JS_DHASH_ADD)); + if (!entry) + goto failed_hash_add; + if (entry->keyAndFlags != 0) + goto finish; + ++state->tablegen; + } } INIT_ATOM_ENTRY(entry, key); + JSFLATSTR_SET_ATOMIZED(key); } finish: ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED)); - v = STRING_TO_JSVAL((JSString *)ATOM_ENTRY_KEY(entry)); + JS_ASSERT(JSSTRING_IS_ATOMIZED(key)); + v = STRING_TO_JSVAL(key); cx->weakRoots.lastAtom = v; JS_UNLOCK(&state->lock, cx); return (JSAtom *)v; @@ -691,7 +708,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) return NULL; } -JS_FRIEND_API(JSAtom *) +JSAtom * js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags) { jschar *chars; @@ -721,19 +738,19 @@ js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags) flags |= ATOM_NOCOPY; } - JSSTRING_INIT(&str, (jschar *)chars, inflatedLength); + JSFLATSTR_INIT(&str, (jschar *)chars, inflatedLength); atom = js_AtomizeString(cx, &str, ATOM_TMPSTR | flags); if (chars != inflated && str.u.chars) JS_free(cx, chars); return atom; } -JS_FRIEND_API(JSAtom *) +JSAtom * js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags) { JSString str; - JSSTRING_INIT(&str, (jschar *)chars, length); + JSFLATSTR_INIT(&str, (jschar *)chars, length); return js_AtomizeString(cx, &str, ATOM_TMPSTR | flags); } @@ -744,7 +761,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length) JSAtomState *state; JSDHashEntryHdr *hdr; - JSSTRING_INIT(&str, (jschar *)chars, length); + JSFLATSTR_INIT(&str, (jschar *)chars, length); state = &cx->runtime->atomState; JS_LOCK(&state->lock, cx); @@ -779,15 +796,36 @@ js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp) return JS_TRUE; } -JSAtom * -js_ValueToStringAtom(JSContext *cx, jsval v) +JSBool +js_ValueToStringId(JSContext *cx, jsval v, jsid *idp) { JSString *str; + JSAtom *atom; - str = js_ValueToString(cx, v); - if (!str) - return NULL; - return js_AtomizeString(cx, str, 0); + /* + * Optimize for the common case where v is an already-atomized string. The + * comment in jsstr.h before the JSSTRING_SET_ATOMIZED macro's definition + * explains why this is thread-safe. The extra rooting via lastAtom (which + * would otherwise be done in js_js_AtomizeString) ensures the caller that + * the resulting id at is least weakly rooted. + */ + if (JSVAL_IS_STRING(v)) { + str = JSVAL_TO_STRING(v); + if (JSSTRING_IS_ATOMIZED(str)) { + cx->weakRoots.lastAtom = v; + *idp = ATOM_TO_JSID((JSAtom *) v); + return JS_TRUE; + } + } else { + str = js_ValueToString(cx, v); + if (!str) + return JS_FALSE; + } + atom = js_AtomizeString(cx, str, 0); + if (!atom) + return JS_FALSE; + *idp = ATOM_TO_JSID(atom); + return JS_TRUE; } #ifdef DEBUG @@ -971,7 +1009,7 @@ static jsrefcount js_atom_map_count; static jsrefcount js_atom_map_hash_table_count; #endif -JS_FRIEND_API(void) +void js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al) { JSAtom **vector; diff --git a/js/src/jsatom.h b/js/src/jsatom.h index 6cc4cc8aaa53..878dc7ab976f 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -85,7 +85,7 @@ JS_STATIC_ASSERT(sizeof(JSAtom *) == JS_BYTES_PER_WORD); * The lifetime of the result extends at least until the next GC activation, * longer if cx's string newborn root is not overwritten. */ -extern JS_FRIEND_API(const char *) +extern const char * js_AtomToPrintableString(JSContext *cx, JSAtom *atom); struct JSAtomListElement { @@ -396,10 +396,10 @@ js_AtomizeDouble(JSContext *cx, jsdouble d); extern JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags); -extern JS_FRIEND_API(JSAtom *) +extern JSAtom * js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags); -extern JS_FRIEND_API(JSAtom *) +extern JSAtom * js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags); /* @@ -416,10 +416,10 @@ JSBool js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp); /* - * Convert v to an atomized string. + * Convert v to an atomized string and wrap it as an id. */ -extern JSAtom * -js_ValueToStringAtom(JSContext *cx, jsval v); +extern JSBool +js_ValueToStringId(JSContext *cx, jsval v, jsid *idp); #ifdef DEBUG @@ -439,7 +439,7 @@ js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al); * to its address. map->length must already be set to the number of atoms in * the list and map->vector must point to pre-allocated memory. */ -extern JS_FRIEND_API(void) +extern void js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al); JS_END_EXTERN_C diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp index e196364bcc8b..f207a79d376e 100644 --- a/js/src/jsbool.cpp +++ b/js/src/jsbool.cpp @@ -122,16 +122,11 @@ static JSFunctionSpec boolean_methods[] = { static JSBool Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - JSBool b; jsval bval; - if (argc != 0) { - if (!js_ValueToBoolean(cx, argv[0], &b)) - return JS_FALSE; - bval = BOOLEAN_TO_JSVAL(b); - } else { - bval = JSVAL_FALSE; - } + bval = (argc != 0) + ? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0])) + : JSVAL_FALSE; if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { *rval = bval; return JS_TRUE; @@ -160,27 +155,22 @@ js_BooleanToString(JSContext *cx, JSBool b) } JSBool -js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp) +js_ValueToBoolean(jsval v) { - JSBool b; - jsdouble d; + if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) + return JS_FALSE; + if (JSVAL_IS_OBJECT(v)) + return JS_TRUE; + if (JSVAL_IS_STRING(v)) + return JSSTRING_LENGTH(JSVAL_TO_STRING(v)) != 0; + if (JSVAL_IS_INT(v)) + return JSVAL_TO_INT(v) != 0; + if (JSVAL_IS_DOUBLE(v)) { + jsdouble d; - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - b = JS_FALSE; - } else if (JSVAL_IS_OBJECT(v)) { - b = JS_TRUE; - } else if (JSVAL_IS_STRING(v)) { - b = JSSTRING_LENGTH(JSVAL_TO_STRING(v)) ? JS_TRUE : JS_FALSE; - } else if (JSVAL_IS_INT(v)) { - b = JSVAL_TO_INT(v) ? JS_TRUE : JS_FALSE; - } else if (JSVAL_IS_DOUBLE(v)) { d = *JSVAL_TO_DOUBLE(v); - b = (!JSDOUBLE_IS_NaN(d) && d != 0) ? JS_TRUE : JS_FALSE; - } else { - JS_ASSERT(JSVAL_IS_BOOLEAN(v)); - b = JSVAL_TO_BOOLEAN(v); + return !JSDOUBLE_IS_NaN(d) && d != 0; } - - *bp = b; - return JS_TRUE; + JS_ASSERT(JSVAL_IS_BOOLEAN(v)); + return JSVAL_TO_BOOLEAN(v); } diff --git a/js/src/jsbool.h b/js/src/jsbool.h index 9a963e649723..fadf5b1f4f0b 100644 --- a/js/src/jsbool.h +++ b/js/src/jsbool.h @@ -66,7 +66,7 @@ extern JSString * js_BooleanToString(JSContext *cx, JSBool b); extern JSBool -js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp); +js_ValueToBoolean(jsval v); JS_END_EXTERN_C diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 6f794cfb6ef8..bea884226ea8 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -514,141 +514,92 @@ typedef struct JSLocalRootStack { * a C function across several layers of other functions, use the * js_LeaveLocalRootScopeWithResult internal API (see further below) instead. * - * JSTempValueRooter.count defines the type of the rooted value referenced by - * JSTempValueRooter.u union of type JSTempValueUnion according to the - * following table: + * The macros also provide a simple way to get a single rooted pointer via + * JS_PUSH_TEMP_ROOT_(cx, NULL, &tvr). Then &tvr.u. gives the + * necessary pointer. * - * count description - * JSTVU_SINGLE u.value contains the single value or GC-thing to root. - * JSTVU_TRACE u.trace holds a trace hook called to trace the values. - * JSTVU_SPROP u.sprop points to the property tree node to mark. - * JSTVU_WEAK_ROOTS u.weakRoots points to saved weak roots. - * JSTVU_PARSE_CONTEXT u.parseContext roots things generated during parsing. - * JSTVU_SCRIPT u.script roots a pointer to JSScript. - * >= 0 u.array points to a stack-allocated vector of jsvals. + * JSTempValueRooter.count defines the type of the rooted value referenced by + * JSTempValueRooter.u union of type JSTempValueUnion. When count is positive + * or zero, u.array points to a vector of jsvals. Otherwise it must be one of + * the following constants: */ -#define JSTVU_SINGLE (-1) -#define JSTVU_TRACE (-2) -#define JSTVU_SPROP (-3) -#define JSTVU_WEAK_ROOTS (-4) -#define JSTVU_PARSE_CONTEXT (-5) -#define JSTVU_SCRIPT (-6) +#define JSTVU_SINGLE (-1) /* u.value or u. is single jsval + or GC-thing */ +#define JSTVU_TRACE (-2) /* u.trace is a hook to trace a custom + * structure */ +#define JSTVU_SPROP (-3) /* u.sprop roots property tree node */ +#define JSTVU_WEAK_ROOTS (-4) /* u.weakRoots points to saved weak roots */ +#define JSTVU_PARSE_CONTEXT (-5) /* u.parseContext roots JSParseContext* */ +#define JSTVU_SCRIPT (-6) /* u.script roots JSScript* */ /* - * To root a single GC-thing pointer, which need not be tagged and stored as a - * jsval, use JS_PUSH_TEMP_ROOT_GCTHING. The macro reinterprets an arbitrary - * GC-thing as jsval. It works because a GC-thing is aligned on a 0 mod 8 - * boundary, and object has the 0 jsval tag. So any GC-thing may be tagged as - * if it were an object and untagged, if it's then used only as an opaque - * pointer until discriminated by other means than tag bits (this is how the - * GC mark function uses its |thing| parameter -- it consults GC-thing flags - * stored separately from the thing to decide the type of thing). - * - * JS_PUSH_TEMP_ROOT_OBJECT and JS_PUSH_TEMP_ROOT_STRING are type-safe - * alternatives to JS_PUSH_TEMP_ROOT_GCTHING for JSObject and JSString. They - * also provide a simple way to get a single pointer to rooted JSObject or - * JSString via JS_PUSH_TEMP_ROOT_(OBJECT|STRTING)(cx, NULL, &tvr). Then - * &tvr.u.object or tvr.u.string gives the necessary pointer, which puns - * tvr.u.value safely because JSObject * and JSString * are GC-things and, as - * such, their tag bits are all zeroes. + * Here single JSTVU_SINGLE covers both jsval and pointers to any GC-thing via + * reinterpreting the thing as JSVAL_OBJECT. It works because the GC-thing is + * aligned on a 0 mod 8 boundary, and object has the 0 jsval tag. So any + * GC-thing may be tagged as if it were an object and untagged, if it's then + * used only as an opaque pointer until discriminated by other means than tag + * bits. This is how, for example, js_GetGCThingTraceKind uses its |thing| + * parameter -- it consults GC-thing flags stored separately from the thing to + * decide the kind of thing. * * The following checks that this type-punning is possible. */ JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(jsval)); -JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(JSObject *)); +JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(void *)); -#define JS_PUSH_TEMP_ROOT_COMMON(cx,tvr) \ +#define JS_PUSH_TEMP_ROOT_COMMON(cx,x,tvr,cnt,kind) \ JS_BEGIN_MACRO \ JS_ASSERT((cx)->tempValueRooters != (tvr)); \ + (tvr)->count = (cnt); \ + (tvr)->u.kind = (x); \ (tvr)->down = (cx)->tempValueRooters; \ (cx)->tempValueRooters = (tvr); \ JS_END_MACRO -#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.value = val; \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT((int)(cnt) >= 0); \ - (tvr)->count = (ptrdiff_t)(cnt); \ - (tvr)->u.array = (arr); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_TRACE; \ - (tvr)->u.trace = (trace_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.object = (obj); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.string = (str); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_GCTHING(cx,thing,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT(JSVAL_IS_OBJECT((jsval)thing)); \ - (tvr)->count = JSTVU_SINGLE; \ - (tvr)->u.gcthing = (thing); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO - #define JS_POP_TEMP_ROOT(cx,tvr) \ JS_BEGIN_MACRO \ JS_ASSERT((cx)->tempValueRooters == (tvr)); \ (cx)->tempValueRooters = (tvr)->down; \ JS_END_MACRO -#define JS_TEMP_ROOT_EVAL(cx,cnt,val,expr) \ +#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ JS_BEGIN_MACRO \ - JSTempValueRooter tvr; \ - JS_PUSH_TEMP_ROOT(cx, cnt, val, &tvr); \ - (expr); \ - JS_POP_TEMP_ROOT(cx, &tvr); \ + JS_ASSERT((int)(cnt) >= 0); \ + JS_PUSH_TEMP_ROOT_COMMON(cx, arr, tvr, (ptrdiff_t) (cnt), array); \ JS_END_MACRO +#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, val, tvr, JSTVU_SINGLE, value) + +#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, obj, tvr, JSTVU_SINGLE, object) + +#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, str, tvr, JSTVU_SINGLE, string) + +#define JS_PUSH_TEMP_ROOT_FUNCTION(cx,fun,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, fun, tvr, JSTVU_SINGLE, function) + +#define JS_PUSH_TEMP_ROOT_QNAME(cx,qn,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, qn, tvr, JSTVU_SINGLE, qname) + +#define JS_PUSH_TEMP_ROOT_XML(cx,xml_,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, xml_, tvr, JSTVU_SINGLE, xml) + +#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \ + JS_PUSH_TEMP_ROOT_COMMON(cx, trace_, tvr, JSTVU_TRACE, trace) + #define JS_PUSH_TEMP_ROOT_SPROP(cx,sprop_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SPROP; \ - (tvr)->u.sprop = (sprop_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, sprop_, tvr, JSTVU_SPROP, sprop) #define JS_PUSH_TEMP_ROOT_WEAK_COPY(cx,weakRoots_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_WEAK_ROOTS; \ - (tvr)->u.weakRoots = (weakRoots_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, weakRoots_, tvr, JSTVU_WEAK_ROOTS, weakRoots) #define JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx,pc,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_PARSE_CONTEXT; \ - (tvr)->u.parseContext = (pc); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, pc, tvr, JSTVU_PARSE_CONTEXT, parseContext) #define JS_PUSH_TEMP_ROOT_SCRIPT(cx,script_,tvr) \ - JS_BEGIN_MACRO \ - (tvr)->count = JSTVU_SCRIPT; \ - (tvr)->u.script = (script_); \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_END_MACRO + JS_PUSH_TEMP_ROOT_COMMON(cx, script_, tvr, JSTVU_SCRIPT, script) struct JSContext { /* JSRuntime contextList linkage. */ diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 9b5730fc650b..7ca7a2287ade 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -675,9 +675,9 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) if (JSID_IS_ATOM(id)) { atom = JSID_TO_ATOM(id); } else if (JSID_IS_INT(id)) { - atom = js_ValueToStringAtom(cx, INT_JSID_TO_JSVAL(id)); - if (!atom) + if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id)) return NULL; + atom = JSID_TO_ATOM(id); } else { atom = NULL; } @@ -690,10 +690,9 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) } JS_PUBLIC_API(JSBool) -JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, +JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, JSWatchPointHandler handler, void *closure) { - JSAtom *atom; jsid propid; JSObject *pobj; JSProperty *prop; @@ -709,15 +708,10 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, return JS_FALSE; } - if (JSVAL_IS_INT(id)) { - propid = INT_JSVAL_TO_JSID(id); - atom = NULL; - } else { - atom = js_ValueToStringAtom(cx, id); - if (!atom) - return JS_FALSE; - propid = ATOM_TO_JSID(atom); - } + if (JSVAL_IS_INT(idval)) + propid = INT_JSVAL_TO_JSID(idval); + else if (!js_ValueToStringId(cx, idval, &propid)) + return JS_FALSE; if (!js_LookupProperty(cx, obj, propid, &pobj, &prop)) return JS_FALSE; @@ -752,8 +746,8 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, flags = sprop->flags; shortid = sprop->shortid; } else { - if (!OBJ_GET_PROPERTY(cx, pobj, id, &value) || - !OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs)) { + if (!OBJ_GET_PROPERTY(cx, pobj, propid, &value) || + !OBJ_GET_ATTRIBUTES(cx, pobj, propid, prop, &attrs)) { OBJ_DROP_PROPERTY(cx, pobj, prop); return JS_FALSE; } @@ -1522,7 +1516,7 @@ GetAtomTotalSize(JSContext *cx, JSAtom *atom) nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub); if (ATOM_IS_STRING(atom)) { nbytes += sizeof(JSString); - nbytes += (ATOM_TO_STRING(atom)->length + 1) * sizeof(jschar); + nbytes += (JSFLATSTR_LENGTH(ATOM_TO_STRING(atom)) + 1) * sizeof(jschar); } else if (ATOM_IS_DOUBLE(atom)) { nbytes += sizeof(jsdouble); } @@ -1676,8 +1670,8 @@ JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks) #ifdef MOZ_SHARK -JS_FRIEND_API(JSBool) -js_StartChudRemote() +JS_PUBLIC_API(JSBool) +JS_StartChudRemote() { if (chudIsRemoteAccessAcquired() && (chudStartRemotePerfMonitor("Mozilla") == chudSuccess)) { @@ -1687,8 +1681,8 @@ js_StartChudRemote() return JS_FALSE; } -JS_FRIEND_API(JSBool) -js_StopChudRemote() +JS_PUBLIC_API(JSBool) +JS_StopChudRemote() { if (chudIsRemoteAccessAcquired() && (chudStopRemotePerfMonitor() == chudSuccess)) { @@ -1698,8 +1692,8 @@ js_StopChudRemote() return JS_FALSE; } -JS_FRIEND_API(JSBool) -js_ConnectShark() +JS_PUBLIC_API(JSBool) +JS_ConnectShark() { if (!chudIsInitialized() && (chudInitialize() != chudSuccess)) return JS_FALSE; @@ -1710,8 +1704,8 @@ js_ConnectShark() return JS_TRUE; } -JS_FRIEND_API(JSBool) -js_DisconnectShark() +JS_PUBLIC_API(JSBool) +JS_DisconnectShark() { if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess)) return JS_FALSE; @@ -1720,10 +1714,10 @@ js_DisconnectShark() } JS_FRIEND_API(JSBool) -StartShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval) +js_StartShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *rval) { - if (!js_StartChudRemote()) { + if (!JS_StartChudRemote()) { JS_ReportError(cx, "Error starting CHUD."); } @@ -1731,10 +1725,10 @@ StartShark(JSContext *cx, JSObject *obj, } JS_FRIEND_API(JSBool) -StopShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval) +js_StopShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *rval) { - if (!js_StopChudRemote()) { + if (!JS_StopChudRemote()) { JS_ReportError(cx, "Error stopping CHUD."); } @@ -1742,10 +1736,10 @@ StopShark(JSContext *cx, JSObject *obj, } JS_FRIEND_API(JSBool) -ConnectShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval) +js_ConnectShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *rval) { - if (!js_ConnectShark()) { + if (!JS_ConnectShark()) { JS_ReportError(cx, "Error connecting to Shark."); } @@ -1753,10 +1747,10 @@ ConnectShark(JSContext *cx, JSObject *obj, } JS_FRIEND_API(JSBool) -DisconnectShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval) +js_DisconnectShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *rval) { - if (!js_DisconnectShark()) { + if (!JS_DisconnectShark()) { JS_ReportError(cx, "Error disconnecting from Shark."); } diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index 6c59e3fd87d1..1dd699457cc2 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -422,24 +422,24 @@ extern JS_PUBLIC_API(JSDebugHooks *) JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks); #ifdef MOZ_SHARK -extern JS_FRIEND_API(JSBool) js_StartChudRemote(); -extern JS_FRIEND_API(JSBool) js_StopChudRemote(); -extern JS_FRIEND_API(JSBool) js_ConnectShark(); -extern JS_FRIEND_API(JSBool) js_DisconnectShark(); +extern JS_PUBLIC_API(JSBool) JS_StartChudRemote(); +extern JS_PUBLIC_API(JSBool) JS_StopChudRemote(); +extern JS_PUBLIC_API(JSBool) JS_ConnectShark(); +extern JS_PUBLIC_API(JSBool) JS_DisconnectShark(); -extern JS_FRIEND_API(JSBool) StopShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval); +extern JS_FRIEND_API(JSBool) js_StopShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *rval); -extern JS_FRIEND_API(JSBool) StartShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval); +extern JS_FRIEND_API(JSBool) js_StartShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *rval); -extern JS_FRIEND_API(JSBool) ConnectShark(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, - jsval *rval); - -extern JS_FRIEND_API(JSBool) DisconnectShark(JSContext *cx, JSObject *obj, +extern JS_FRIEND_API(JSBool) js_ConnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); + +extern JS_FRIEND_API(JSBool) js_DisconnectShark(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, + jsval *rval); #endif /* MOZ_SHARK */ JS_END_EXTERN_C diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index 2a95e04d9811..2978dd42e8c9 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -3928,6 +3928,14 @@ GettableNoteForNextOp(JSCodeGenerator *cg) } #endif +/* Top-level named functions need a nop for decompilation. */ +static JSBool +EmitFunctionDefNop(JSContext *cx, JSCodeGenerator *cg, uintN index) +{ + return js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)index) >= 0 && + js_Emit1(cx, cg, JSOP_NOP) >= 0; +} + JSBool js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) { @@ -3962,9 +3970,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) switch (pn->pn_type) { case TOK_FUNCTION: { + JSFunction *fun; void *cg2mark; JSCodeGenerator *cg2; - JSFunction *fun; uintN slot; #if JS_HAS_XML_SUPPORT @@ -3975,6 +3983,21 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } #endif + fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object); + if (fun->u.i.script) { + /* + * This second pass is needed to emit JSOP_NOP with a source note + * for the already-emitted function. See comments in the TOK_LC + * case. + */ + JS_ASSERT(pn->pn_op == JSOP_NOP); + JS_ASSERT(cg->treeContext.flags & TCF_IN_FUNCTION); + JS_ASSERT(pn->pn_index != (uint32) -1); + if (!EmitFunctionDefNop(cx, cg, pn->pn_index)) + return JS_FALSE; + break; + } + /* Generate code for the function's body. */ cg2mark = JS_ARENA_MARK(&cx->tempPool); JS_ARENA_ALLOCATE_TYPE(cg2, JSCodeGenerator, &cx->tempPool); @@ -3987,7 +4010,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) pn->pn_pos.begin.lineno); cg2->treeContext.flags = (uint16) (pn->pn_flags | TCF_IN_FUNCTION); cg2->treeContext.maxScopeDepth = pn->pn_sclen; - fun = GET_FUNCTION_PRIVATE(cx, pn->pn_funpob->object); cg2->treeContext.fun = fun; cg2->parent = cg; if (!js_EmitFunctionScript(cx, cg2, pn->pn_body)) { @@ -4023,52 +4045,41 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) break; } - /* Top-level named functions need a nop for decompilation. */ - noteIndex = js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)index); - if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - /* - * Top-levels also need a prolog op to predefine their names in the - * variable object, or if local, to fill their stack slots. + * For a script we emit the code as we parse. Thus the bytecode for + * top-level functions should go in the prolog to predefine their + * names in the variable object before the already-generated main code + * is executed. This extra work for top-level scripts is not necessary + * when we emit the code for a function. It is fully parsed prior to + * invocation of the emitter and calls to js_EmitTree for function + * definitions can be scheduled before generating the rest of code. */ - CG_SWITCH_TO_PROLOG(cg); - if (!(cg->treeContext.flags & TCF_IN_FUNCTION)) { + CG_SWITCH_TO_PROLOG(cg); + /* - * Emit JSOP_CLOSURE for eval code to do less checks when + * Emit JSOP_CLOSURE for eval code to do fewer checks when * instantiating top-level functions in the non-eval case. */ JS_ASSERT(!cg->treeContext.topStmt); op = (cx->fp->flags & JSFRAME_EVAL) ? JSOP_CLOSURE : JSOP_DEFFUN; EMIT_INDEX_OP(op, index); + CG_SWITCH_TO_MAIN(cg); + + /* Emit NOP for the decompiler. */ + if (!EmitFunctionDefNop(cx, cg, index)) + return JS_FALSE; } else { #ifdef DEBUG JSLocalKind localKind = #endif js_LookupLocal(cx, cg->treeContext.fun, fun->atom, &slot); JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST); - - /* - * If this local function is declared in a body block induced - * by let declarations, reparent fun->object to the compiler- - * created body block object, so that JSOP_DEFLOCALFUN clones - * that block into the runtime scope chain. - */ - stmt = cg->treeContext.topStmt; - if (stmt && stmt->type == STMT_BLOCK && - stmt->down && stmt->down->type == STMT_BLOCK && - (stmt->down->flags & SIF_SCOPE)) { - JS_ASSERT(STOBJ_GET_CLASS(stmt->down->u.blockObj) == - &js_BlockClass); - OBJ_SET_PARENT(cx, fun->object, stmt->down->u.blockObj); - } + JS_ASSERT(pn->pn_index == (uint32) -1); + pn->pn_index = index; if (!EmitSlotIndexOp(cx, JSOP_DEFLOCALFUN, slot, index, cg)) return JS_FALSE; } - CG_SWITCH_TO_MAIN(cg); break; } @@ -4526,13 +4537,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } } else { op = JSOP_POP; - if (!pn2->pn_kid1) { + pn3 = pn2->pn_kid1; + if (!pn3) { /* No initializer: emit an annotated nop for the decompiler. */ op = JSOP_NOP; } else { cg->treeContext.flags |= TCF_IN_FOR_INIT; #if JS_HAS_DESTRUCTURING - pn3 = pn2->pn_kid1; if (pn3->pn_type == TOK_ASSIGN && !MaybeEmitGroupAssignment(cx, cg, op, pn3, &op)) { return JS_FALSE; @@ -5158,6 +5169,27 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } js_PushStatement(&cg->treeContext, &stmtInfo, STMT_BLOCK, top); + if (pn->pn_extra & PNX_FUNCDEFS) { + /* + * This block contains top-level function definitions. To ensure + * that we emit the bytecode defining them prior the rest of code + * in the block we use a separate pass over functions. During the + * main pass later the emitter will add JSOP_NOP with source notes + * for the function to preserve the original functions position + * when decompiling. + * + * Currently this is used only for functions, as compile-as-we go + * mode for scripts does not allow separate emitter passes. + */ + JS_ASSERT(cg->treeContext.flags & TCF_IN_FUNCTION); + for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { + if (pn2->pn_type == TOK_FUNCTION) { + JS_ASSERT(pn2->pn_op == JSOP_NOP); + if (!js_EmitTree(cx, cg, pn2)) + return JS_FALSE; + } + } + } for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { if (!js_EmitTree(cx, cg, pn2)) return JS_FALSE; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index b654780155d3..c12d43e81804 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -807,12 +807,11 @@ call_enumerate(JSContext *cx, JSObject *obj) } static JSBool -call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, +call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, JSObject **objp) { JSStackFrame *fp; - JSString *str; - JSAtom *atom; + jsid id; JSLocalKind localKind; JSPropertyOp getter, setter; uintN slot, attrs; @@ -824,15 +823,13 @@ call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JS_ASSERT(fp->fun); JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fp->fun); - if (!JSVAL_IS_STRING(id)) + if (!JSVAL_IS_STRING(idval)) return JS_TRUE; - str = JSVAL_TO_STRING(id); - atom = js_AtomizeString(cx, str, 0); - if (!atom) + if (!js_ValueToStringId(cx, idval, &id)) return JS_FALSE; - localKind = js_LookupLocal(cx, fp->fun, atom, &slot); + localKind = js_LookupLocal(cx, fp->fun, JSID_TO_ATOM(id), &slot); if (localKind != JSLOCAL_NONE) { if (localKind == JSLOCAL_ARG) { JS_ASSERT(slot < fp->fun->nargs); @@ -850,9 +847,9 @@ call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, ? JSPROP_PERMANENT | JSPROP_READONLY : JSPROP_PERMANENT; } - if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), vp[slot], - getter, setter, attrs, - SPROP_HAS_SHORTID, (int) slot, NULL)) { + if (!js_DefineNativeProperty(cx, obj, id, vp[slot], getter, setter, + attrs, SPROP_HAS_SHORTID, (int) slot, + NULL)) { return JS_FALSE; } *objp = obj; @@ -863,10 +860,8 @@ call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, * Resolve arguments so that we never store a particular Call object's * arguments object reference in a Call prototype's |arguments| slot. */ - atom = cx->runtime->atomState.argumentsAtom; - if (id == ATOM_KEY(atom)) { - if (!js_DefineNativeProperty(cx, obj, - ATOM_TO_JSID(atom), JSVAL_VOID, + if (id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) { + if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID, NULL, NULL, JSPROP_PERMANENT, SPROP_HAS_SHORTID, CALL_ARGUMENTS, NULL)) { @@ -1726,9 +1721,14 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JS_ASSERT(!fp->script && fp->fun && fp->fun->u.n.native == Function); caller = JS_GetScriptedCaller(cx, fp); if (caller) { - filename = caller->script->filename; - lineno = js_PCToLineNumber(cx, caller->script, caller->pc); principals = JS_EvalFramePrincipals(cx, fp, caller); + if (principals == caller->script->principals) { + filename = caller->script->filename; + lineno = js_PCToLineNumber(cx, caller->script, caller->pc); + } else { + filename = principals->codebase; + lineno = 0; + } } else { filename = NULL; lineno = 0; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index ed7c9d6f18a2..fabf71dc488a 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2597,40 +2597,46 @@ restart: *flagp &= ~GCF_MARK; allClear = JS_FALSE; METER(++arenaList->stats.nthings); - } else if (!(flags & GCF_FINAL)) { - /* Call the finalizer with GCF_FINAL ORed into flags. */ + } else { thing = FLAGP_TO_THING(flagp, thingSize); - *flagp = (uint8)(flags | GCF_FINAL); - type = flags & GCF_TYPEMASK; - switch (type) { - case GCX_OBJECT: - js_FinalizeObject(cx, (JSObject *) thing); - break; - case GCX_DOUBLE: - /* Do nothing. */ - break; - case GCX_FUNCTION: - js_FinalizeFunction(cx, (JSFunction *) thing); - break; + if (!(flags & GCF_FINAL)) { + /* + * Call the finalizer with GCF_FINAL ORed into flags. + */ + *flagp = (uint8)(flags | GCF_FINAL); + type = flags & GCF_TYPEMASK; + switch (type) { + case GCX_OBJECT: + js_FinalizeObject(cx, (JSObject *) thing); + break; + case GCX_DOUBLE: + /* Do nothing. */ + break; + case GCX_FUNCTION: + js_FinalizeFunction(cx, (JSFunction *) thing); + break; #if JS_HAS_XML_SUPPORT - case GCX_NAMESPACE: - js_FinalizeXMLNamespace(cx, (JSXMLNamespace *) thing); - break; - case GCX_QNAME: - js_FinalizeXMLQName(cx, (JSXMLQName *) thing); - break; - case GCX_XML: - js_FinalizeXML(cx, (JSXML *) thing); - break; + case GCX_NAMESPACE: + js_FinalizeXMLNamespace(cx, + (JSXMLNamespace *) thing); + break; + case GCX_QNAME: + js_FinalizeXMLQName(cx, (JSXMLQName *) thing); + break; + case GCX_XML: + js_FinalizeXML(cx, (JSXML *) thing); + break; #endif - default: - JS_ASSERT(type == GCX_STRING || - type - GCX_EXTERNAL_STRING < - GCX_NTYPES - GCX_EXTERNAL_STRING); - js_FinalizeStringRT(rt, (JSString *) thing, - (intN) (type - GCX_EXTERNAL_STRING), - cx); - break; + default: + JS_ASSERT(type == GCX_STRING || + type - GCX_EXTERNAL_STRING < + GCX_NTYPES - GCX_EXTERNAL_STRING); + js_FinalizeStringRT(rt, (JSString *) thing, + (intN) (type - + GCX_EXTERNAL_STRING), + cx); + break; + } } thing->flagp = flagp; thing->next = freeList; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 1dabda97270e..b4dcd7b3567c 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -222,10 +222,7 @@ } else if (JSVAL_IS_BOOLEAN(v)) { \ b = JSVAL_TO_BOOLEAN(v); \ } else { \ - SAVE_SP_AND_PC(fp); \ - ok = js_ValueToBoolean(cx, v, &b); \ - if (!ok) \ - goto out; \ + b = js_ValueToBoolean(v); \ } \ sp--; \ JS_END_MACRO @@ -410,7 +407,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) */ if (fp->fun && !fp->callobj) { JS_ASSERT(OBJ_GET_CLASS(cx, fp->scopeChain) != &js_BlockClass || - JS_GetPrivate(cx, fp->scopeChain) != fp); + OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp); if (!js_GetCallObject(cx, fp, fp->scopeChain)) return NULL; } @@ -482,7 +479,7 @@ PutBlockObjects(JSContext *cx, JSStackFrame *fp) ok = JS_TRUE; for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) { if (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) { - if (JS_GetPrivate(cx, obj) != fp) + if (OBJ_GET_PRIVATE(cx, obj) != fp) break; ok &= js_PutBlockObject(cx, obj); } @@ -1007,7 +1004,7 @@ have_fun: native, JSVAL_IS_OBJECT(vp[1]) ? ((OBJ_GET_CLASS(cx, frame.thisp) == &js_FunctionClass) - ? JS_GetFunctionName(JS_GetPrivate(cx, frame.thisp)) + ? JS_GetFunctionName(OBJ_GET_PRIVATE(cx, frame.thisp)) : OBJ_GET_CLASS(cx, frame.thisp)->name) : JSVAL_IS_BOOLEAN(vp[1]) ? js_BooleanClass.name @@ -1632,8 +1629,6 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc) static JSBool InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp) { - JSAtom *atom; - JS_ASSERT(!JSVAL_IS_INT(idval)); #if JS_HAS_XML_SUPPORT @@ -1649,11 +1644,7 @@ InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp) } #endif - atom = js_ValueToStringAtom(cx, idval); - if (!atom) - return JS_FALSE; - *idp = ATOM_TO_JSID(atom); - return JS_TRUE; + return js_ValueToStringId(cx, idval, idp); } /* @@ -2186,7 +2177,7 @@ interrupt: clasp = OBJ_GET_CLASS(cx, obj); if (clasp != &js_BlockClass && clasp != &js_WithClass) continue; - if (JS_GetPrivate(cx, obj) != fp) + if (OBJ_GET_PRIVATE(cx, obj) != fp) break; JS_ASSERT(fp->spbase + OBJ_BLOCK_DEPTH(cx, obj) + ((clasp == &js_BlockClass) @@ -4720,51 +4711,17 @@ interrupt: */ slot = GET_VARNO(pc); - JS_ASSERT(!fp->blockChain); - if (!(fp->flags & JSFRAME_POP_BLOCKS)) { - /* - * If the compiler-created function object (obj) is scoped by a - * let-induced body block, temporarily update fp->blockChain so - * that js_GetScopeChain will clone the block into the runtime - * scope needed to parent the function object's clone. - */ - parent = OBJ_GET_PARENT(cx, obj); - if (parent && OBJ_GET_CLASS(cx, parent) == &js_BlockClass) - fp->blockChain = parent; - parent = js_GetScopeChain(cx, fp); - } else { - /* - * We have already emulated JSOP_ENTERBLOCK for the enclosing - * body block, for a prior JSOP_DEFLOCALFUN in the prolog, so - * we just load fp->scopeChain into parent. - * - * In typical execution scenarios, the prolog bytecodes that - * include this JSOP_DEFLOCALFUN run, then come main bytecodes - * including JSOP_ENTERBLOCK for the outermost (body) block. - * JSOP_ENTERBLOCK will detect that it need not do anything if - * the body block was entered above due to a local function. - * Finally the matching JSOP_LEAVEBLOCK runs. - * - * If the matching JSOP_LEAVEBLOCK for the body block does not - * run for some reason, the body block will be properly "put" - * (via js_PutBlockObject) by the PutBlockObjects call at the - * bottom of js_Interpret. - */ - parent = fp->scopeChain; - JS_ASSERT(OBJ_GET_CLASS(cx, parent) == &js_BlockClass); - JS_ASSERT(OBJ_GET_PROTO(cx, parent) == OBJ_GET_PARENT(cx, obj)); - JS_ASSERT(OBJ_GET_CLASS(cx, OBJ_GET_PARENT(cx, parent)) - == &js_CallClass); + parent = js_GetScopeChain(cx, fp); + if (!parent) { + ok = JS_FALSE; + goto out; } - /* If re-parenting, store a clone of the function object. */ - if (OBJ_GET_PARENT(cx, obj) != parent) { - SAVE_SP_AND_PC(fp); - obj = js_CloneFunctionObject(cx, obj, parent); - if (!obj) { - ok = JS_FALSE; - goto out; - } + SAVE_SP_AND_PC(fp); + obj = js_CloneFunctionObject(cx, obj, parent); + if (!obj) { + ok = JS_FALSE; + goto out; } fp->vars[slot] = OBJECT_TO_JSVAL(obj); @@ -5550,23 +5507,12 @@ interrupt: */ if (fp->flags & JSFRAME_POP_BLOCKS) { JS_ASSERT(!fp->blockChain); - - /* - * Check whether JSOP_DEFLOCALFUN emulated JSOP_ENTERBLOCK for - * the body block in order to correctly scope the local cloned - * function object it creates. - */ - parent = fp->scopeChain; - if (OBJ_GET_PROTO(cx, parent) == obj) { - JS_ASSERT(OBJ_GET_CLASS(cx, parent) == &js_BlockClass); - } else { - obj = js_CloneBlockObject(cx, obj, parent, fp); - if (!obj) { - ok = JS_FALSE; - goto out; - } - fp->scopeChain = obj; + obj = js_CloneBlockObject(cx, obj, fp->scopeChain, fp); + if (!obj) { + ok = JS_FALSE; + goto out; } + fp->scopeChain = obj; } else { JS_ASSERT(!fp->blockChain || OBJ_GET_PARENT(cx, obj) == fp->blockChain); @@ -5957,7 +5903,7 @@ out: clasp = OBJ_GET_CLASS(cx, obj); if (clasp != &js_WithClass && clasp != &js_BlockClass) break; - if (JS_GetPrivate(cx, obj) != fp || + if (OBJ_GET_PRIVATE(cx, obj) != fp || OBJ_BLOCK_DEPTH(cx, obj) < i) { break; } diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 93be2ab1efc3..05b8b4460b4b 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -174,9 +174,7 @@ Iterator(JSContext *cx, JSObject *iterobj, uintN argc, jsval *argv, jsval *rval) uintN flags; JSObject *obj; - keyonly = JS_FALSE; - if (!js_ValueToBoolean(cx, argv[1], &keyonly)) - return JS_FALSE; + keyonly = js_ValueToBoolean(argv[1]); flags = keyonly ? 0 : JSITER_FOREACH; if (cx->fp->flags & JSFRAME_CONSTRUCTING) { diff --git a/js/src/jslock.cpp b/js/src/jslock.cpp index e9447be56da5..ff6f72ae2056 100644 --- a/js/src/jslock.cpp +++ b/js/src/jslock.cpp @@ -85,18 +85,21 @@ js_UnlockGlobal(void *id) /* Exclude Alpha NT. */ #if defined(_WIN32) && defined(_M_IX86) #pragma warning( disable : 4035 ) +#pragma intrinsic(_InterlockedCompareExchange) + +static JS_INLINE int +js_CompareAndSwapHelper(jsword *w, jsword ov, jsword nv) +{ + _InterlockedCompareExchange(w, nv, ov); + __asm { + sete al + } +} static JS_INLINE int js_CompareAndSwap(jsword *w, jsword ov, jsword nv) { - __asm { - mov eax, ov - mov ecx, nv - mov ebx, w - lock cmpxchg [ebx], ecx - sete al - and eax, 1h - } + return (js_CompareAndSwapHelper(w, ov, nv) & 1); } #elif defined(XP_MACOSX) || defined(DARWIN) @@ -606,10 +609,10 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot) JS_ASSERT(slot < obj->map->freeslot); /* - * Avoid locking if called from the GC (see GC_AWARE_GET_SLOT in jsobj.h). - * Also avoid locking an object owning a sealed scope. If neither of those - * special cases applies, try to claim scope's flyweight lock from whatever - * context may have had it in an earlier request. + * Avoid locking if called from the GC. Also avoid locking an object + * owning a sealed scope. If neither of those special cases applies, try + * to claim scope's flyweight lock from whatever context may have had it in + * an earlier request. */ if (CX_THREAD_IS_RUNNING_GC(cx) || (SCOPE_IS_SEALED(scope) && scope->object == obj) || @@ -699,10 +702,10 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v) JS_ASSERT(slot < obj->map->freeslot); /* - * Avoid locking if called from the GC (see GC_AWARE_GET_SLOT in jsobj.h). - * Also avoid locking an object owning a sealed scope. If neither of those - * special cases applies, try to claim scope's flyweight lock from whatever - * context may have had it in an earlier request. + * Avoid locking if called from the GC. Also avoid locking an object + * owning a sealed scope. If neither of those special cases applies, try + * to claim scope's flyweight lock from whatever context may have had it in + * an earlier request. */ if (CX_THREAD_IS_RUNNING_GC(cx) || (SCOPE_IS_SEALED(scope) && scope->object == obj) || diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 09962c5bad9b..828f37602c1d 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1994,6 +1994,7 @@ JSObject * js_NewBlockObject(JSContext *cx) { JSObject *obj; + JSBool ok; /* * Null obj's proto slot so that Object.prototype.* does not pollute block @@ -2001,7 +2002,12 @@ js_NewBlockObject(JSContext *cx) * not affect OBJ_SCOPE(obj). */ obj = js_NewObject(cx, &js_BlockClass, NULL, NULL); - if (!obj || !js_GetMutableScope(cx, obj)) + if (!obj) + return NULL; + JS_LOCK_OBJ(cx, obj); + ok = js_GetMutableScope(cx, obj) != NULL; + JS_UNLOCK_OBJ(cx, obj); + if (!ok) return NULL; OBJ_SET_PROTO(cx, obj, NULL); return obj; @@ -2874,7 +2880,7 @@ js_FinalizeObject(JSContext *cx, JSObject *obj) } /* Finalize obj first, in case it needs map and slots. */ - GC_AWARE_GET_CLASS(cx, obj)->finalize(cx, obj); + STOBJ_GET_CLASS(obj)->finalize(cx, obj); #ifdef INCLUDE_MOZILLA_DTRACE if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED()) @@ -2937,11 +2943,11 @@ js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot) if (JSID_IS_ATOM(id)) { \ JSAtom *atom_ = JSID_TO_ATOM(id); \ JSString *str_ = ATOM_TO_STRING(atom_); \ - const jschar *cp_ = str_->u.chars; \ + const jschar *cp_ = JSFLATSTR_CHARS(str_); \ JSBool negative_ = (*cp_ == '-'); \ if (negative_) cp_++; \ if (JS7_ISDEC(*cp_)) { \ - size_t n_ = str_->length - negative_; \ + size_t n_ = JSFLATSTR_LENGTH(str_) - negative_; \ if (n_ <= sizeof(JSVAL_INT_MAX_STRING) - 1) \ id = CheckForStringIndex(id, cp_, cp_ + n_, negative_); \ } \ @@ -4427,8 +4433,10 @@ js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) return JS_FALSE; } if (VALUE_IS_FUNCTION(cx, fval)) { - return js_InternalCall(cx, obj, fval, 1, &v, &rval) && - js_ValueToBoolean(cx, rval, bp); + if (!js_InternalCall(cx, obj, fval, 1, &v, &rval)) + return JS_FALSE; + *bp = js_ValueToBoolean(rval); + return JS_TRUE; } } #endif diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 7445254e64a6..f27744a6a0c8 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -242,41 +242,28 @@ struct JSObject { #define CX_THREAD_IS_RUNNING_GC(cx) \ THREAD_IS_RUNNING_GC((cx)->runtime, (cx)->thread) -#define GC_AWARE_GET_SLOT(cx, obj, slot) \ - ((OBJ_IS_NATIVE(obj) && CX_THREAD_IS_RUNNING_GC(cx)) \ - ? STOBJ_GET_SLOT(obj, slot) \ - : OBJ_GET_SLOT(cx, obj, slot)) - #else /* !JS_THREADSAFE */ #define OBJ_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot) #define OBJ_SET_SLOT(cx,obj,slot,value) LOCKED_OBJ_SET_SLOT(obj,slot,value) -#define GC_AWARE_GET_SLOT(cx,obj,slot) STOBJ_GET_SLOT(obj,slot) #endif /* !JS_THREADSAFE */ -#define GC_AWARE_GET_PROTO(cx, obj) \ - JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO)) - -#define GC_AWARE_GET_PARENT(cx, obj) \ - JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT)) - /* Thread-safe proto, parent, and class access macros. */ #define OBJ_GET_PROTO(cx,obj) \ - JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj, JSSLOT_PROTO)) + STOBJ_GET_PROTO(obj) #define OBJ_SET_PROTO(cx,obj,proto) \ OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto)) #define OBJ_GET_PARENT(cx,obj) \ - JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj, JSSLOT_PARENT)) + STOBJ_GET_PARENT(obj) #define OBJ_SET_PARENT(cx,obj,parent) \ OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent)) /* - * Class is invariant and comes from the fixed JSCLASS_SLOT. Thus no locking + * Class is invariant and comes from the fixed JSSLOT_CLASS. Thus no locking * is necessary to read it. Same for the private slot. */ -#define GC_AWARE_GET_CLASS(cx, obj) STOBJ_GET_CLASS(obj) #define OBJ_GET_CLASS(cx,obj) STOBJ_GET_CLASS(obj) #define OBJ_GET_PRIVATE(cx,obj) STOBJ_GET_PRIVATE(obj) diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index ffbc7c0149c9..48ffa2f692ba 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -84,6 +84,14 @@ #include "jsdhash.h" #endif +/* + * Asserts to verify assumptions behind pn_ macros. + */ +JS_STATIC_ASSERT(offsetof(JSParseNode, pn_u.name.atom) == + offsetof(JSParseNode, pn_u.apair.atom)); +JS_STATIC_ASSERT(offsetof(JSParseNode, pn_u.name.slot) == + offsetof(JSParseNode, pn_u.lexical.slot)); + /* * JS parsers, from lowest to highest precedence. * @@ -1106,6 +1114,9 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, pn = NewParseNode(cx, ts, PN_FUNC, tc); if (!pn) return NULL; +#ifdef DEBUG + pn->pn_index = (uint32) -1; +#endif /* Scan the optional function name into funAtom. */ ts->flags |= TSF_KEYWORD_IS_NAME; @@ -1453,8 +1464,11 @@ Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) ts->flags |= TSF_OPERAND; tt = js_PeekToken(cx, ts); ts->flags &= ~TSF_OPERAND; - if (tt <= TOK_EOF || tt == TOK_RC) + if (tt <= TOK_EOF || tt == TOK_RC) { + if (tt == TOK_ERROR) + return NULL; break; + } pn2 = Statement(cx, ts, tc); if (!pn2) { if (ts->flags & TSF_EOF) @@ -1462,10 +1476,21 @@ Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) return NULL; } - /* Detect a function statement for the TOK_LC case in Statement. */ - if (pn2->pn_type == TOK_FUNCTION && !AT_TOP_LEVEL(tc)) - tc->flags |= TCF_HAS_FUNCTION_STMT; - + if (pn2->pn_type == TOK_FUNCTION) { + /* + * PNX_FUNCDEFS notifies the emitter that the block contains top- + * level function definitions that should be processed before the + * rest of nodes. + * + * TCF_HAS_FUNCTION_STMT is for the TOK_LC case in Statement. It + * is relevant only for function definitions not at top-level, + * which we call function statements. + */ + if (AT_TOP_LEVEL(tc)) + pn->pn_extra |= PNX_FUNCDEFS; + else + tc->flags |= TCF_HAS_FUNCTION_STMT; + } PN_APPEND(pn, pn2); } @@ -1478,10 +1503,6 @@ Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) pn = tc->blockNode; tc->blockNode = saveBlock; - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_ERROR) - return NULL; - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; return pn; } @@ -6406,7 +6427,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) /* XXX fold only if all operands convert to string */ if (pn2->pn_type != TOK_STRING) return JS_TRUE; - length += ATOM_TO_STRING(pn2->pn_atom)->length; + length += JSFLATSTR_LENGTH(ATOM_TO_STRING(pn2->pn_atom)); } /* Allocate a new buffer and string descriptor for the result. */ @@ -6422,8 +6443,8 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) /* Fill the buffer, advancing chars and recycling kids as we go. */ for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) { str2 = ATOM_TO_STRING(pn2->pn_atom); - length2 = str2->length; - js_strncpy(chars, str2->u.chars, length2); + length2 = JSFLATSTR_LENGTH(str2); + js_strncpy(chars, JSFLATSTR_CHARS(str2), length2); chars += length2; } *chars = 0; diff --git a/js/src/jsparse.h b/js/src/jsparse.h index 3fefa9b3e8c2..f45293904d53 100644 --- a/js/src/jsparse.h +++ b/js/src/jsparse.h @@ -282,6 +282,7 @@ struct JSParseNode { JSParseNode *body; /* TOK_LC list of statements */ uint16 flags; /* accumulated tree context flags */ uint16 sclen; /* maximum scope chain length */ + uint32 index; /* emitter's index */ } func; struct { /* list of next-linked nodes */ JSParseNode *head; /* first node in list */ @@ -331,6 +332,7 @@ struct JSParseNode { #define pn_body pn_u.func.body #define pn_flags pn_u.func.flags #define pn_sclen pn_u.func.sclen +#define pn_index pn_u.func.index #define pn_head pn_u.list.head #define pn_tail pn_u.list.tail #define pn_count pn_u.list.count @@ -362,7 +364,8 @@ struct JSParseNode { #define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */ #define PNX_GROUPINIT 0x40 /* var [a, b] = [c, d]; unit list */ #define PNX_NEEDBRACES 0x80 /* braces necessary due to closure */ - +#define PNX_FUNCDEFS 0x100 /* contains top-level function + statements */ /* * Move pn2 into pn, preserving pn->pn_pos and pn->pn_offset and handing off * any kids in pn2->pn_u, by clearing pn2. diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 82c0407ec88e..80fb29f33122 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -234,7 +234,9 @@ typedef union JSTempValueUnion { jsval value; JSObject *object; JSString *string; - void *gcthing; + JSFunction *function; + JSXML *xml; + JSXMLQName *qname; JSTempValueTrace trace; JSScopeProperty *sprop; JSWeakRoots *weakRoots; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 9b39be257e58..cc8df1ceafa6 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -109,9 +109,8 @@ js_GetDependentStringChars(JSString *str) JSString *base; start = js_MinimizeDependentStrings(str, 0, &base); - JS_ASSERT(!JSSTRING_IS_DEPENDENT(base)); - JS_ASSERT(start < (base->length & ~JSSTRFLAG_MUTABLE)); - return base->u.chars + start; + JS_ASSERT(start < JSFLATSTR_LENGTH(base)); + return JSFLATSTR_CHARS(base) + start; } const jschar * @@ -119,8 +118,7 @@ js_GetStringChars(JSContext *cx, JSString *str) { if (!js_MakeStringImmutable(cx, str)) return NULL; - JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)); - return str->u.chars; + return JSFLATSTR_CHARS(str); } JSString * @@ -148,7 +146,7 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) ldep = NULL; } else { /* We can realloc left's space and make it depend on our result. */ - JS_ASSERT(!JSSTRING_IS_DEPENDENT(left)); + JS_ASSERT(JSSTRING_IS_FLAT(left)); s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar)); if (!s) return NULL; @@ -175,7 +173,7 @@ js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) left->u.chars = s; } } else { - JSSTRING_SET_MUTABLE(str); + JSFLATSTR_SET_MUTABLE(str); /* Morph left into a dependent prefix if we realloc'd its buffer. */ if (ldep) { @@ -211,7 +209,7 @@ js_UndependString(JSContext *cx, JSString *str) js_strncpy(s, JSSTRDEP_CHARS(str), n); s[n] = 0; - JSSTRING_INIT(str, s, n); + JSFLATSTR_INIT(str, s, n); #ifdef DEBUG { @@ -225,7 +223,7 @@ js_UndependString(JSContext *cx, JSString *str) #endif } - return str->u.chars; + return JSFLATSTR_CHARS(str); } JSBool @@ -235,7 +233,7 @@ js_MakeStringImmutable(JSContext *cx, JSString *str) JS_RUNTIME_METER(cx->runtime, badUndependStrings); return JS_FALSE; } - JSSTRING_CLEAR_MUTABLE(str); + JSFLATSTR_CLEAR_MUTABLE(str); return JS_TRUE; } @@ -2486,7 +2484,7 @@ js_NewString(JSContext *cx, jschar *chars, size_t length) str = (JSString *) js_NewGCThing(cx, GCX_STRING, sizeof(JSString)); if (!str) return NULL; - JSSTRING_INIT(str, chars, length); + JSFLATSTR_INIT(str, chars, length); #ifdef DEBUG { JSRuntime *rt = cx->runtime; @@ -2645,6 +2643,7 @@ js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop, void js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx) { + jschar *chars; JSBool valid; JSStringFinalizeOp finalizer; @@ -2657,14 +2656,15 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx) valid = JS_TRUE; } else { /* A stillborn string has null chars, so is not valid. */ - valid = (str->u.chars != NULL); + chars = JSFLATSTR_CHARS(str); + valid = (chars != NULL); if (valid) { - if (IN_UNIT_STRING_SPACE_RT(rt, str->u.chars)) { - JS_ASSERT(rt->unitStrings[*str->u.chars] == str); + if (IN_UNIT_STRING_SPACE_RT(rt, chars)) { + JS_ASSERT(rt->unitStrings[*chars] == str); JS_ASSERT(type < 0); - rt->unitStrings[*str->u.chars] = NULL; + rt->unitStrings[*chars] = NULL; } else if (type < 0) { - free(str->u.chars); + free(chars); } else { JS_ASSERT((uintN) type < JS_ARRAY_LENGTH(str_finalizers)); finalizer = str_finalizers[type]; diff --git a/js/src/jsstr.h b/js/src/jsstr.h index 9179c1a3d3a0..dca86d1bfd35 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -70,6 +70,10 @@ JS_BEGIN_EXTERN_C * such string but extreme care must be taken to ensure that no other code * relies on the original length of the string. * + * A flat string with JSSTRFLAG_ATOMIZED set means that the string is hashed + * as an atom. This flag is used to avoid re-hashing of the already-atomized + * string. + * * When JSSTRFLAG_DEPENDENT is set, the string depends on characters of * another string strongly referenced by the u.base field. The base member may * point to another dependent string if JSSTRING_CHARS has not been called @@ -99,59 +103,98 @@ struct JSString { * Definitions for flags stored in the high order bits of JSString.length. * JSSTRFLAG_PREFIX and JSSTRFLAG_MUTABLE are two aliases for the same value. * JSSTRFLAG_PREFIX should be used only if JSSTRFLAG_DEPENDENT is set and - * JSSTRFLAG_MUTABLE should be used only if JSSTRFLAG_DEPENDENT is unset. + * JSSTRFLAG_MUTABLE should be used only if the string is flat. + * JSSTRFLAG_ATOMIZED is used only with the flat immutable strings. */ -#define JSSTRFLAG_BITS 2 -#define JSSTRFLAG_SHIFT(flg) ((size_t)(flg) << JSSTRING_LENGTH_BITS) -#define JSSTRFLAG_MASK JSSTRFLAG_SHIFT(JS_BITMASK(JSSTRFLAG_BITS)) -#define JSSTRFLAG_DEPENDENT JSSTRFLAG_SHIFT(1) -#define JSSTRFLAG_PREFIX JSSTRFLAG_SHIFT(2) -#define JSSTRFLAG_MUTABLE JSSTRFLAG_SHIFT(2) +#define JSSTRFLAG_DEPENDENT JSSTRING_BIT(JS_BITS_PER_WORD - 1) +#define JSSTRFLAG_PREFIX JSSTRING_BIT(JS_BITS_PER_WORD - 2) +#define JSSTRFLAG_MUTABLE JSSTRFLAG_PREFIX +#define JSSTRFLAG_ATOMIZED JSSTRING_BIT(JS_BITS_PER_WORD - 3) + +#define JSSTRING_LENGTH_BITS (JS_BITS_PER_WORD - 3) +#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS) /* Universal JSString type inquiry and accessor macros. */ #define JSSTRING_BIT(n) ((size_t)1 << (n)) #define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1) #define JSSTRING_HAS_FLAG(str,flg) ((str)->length & (flg)) #define JSSTRING_IS_DEPENDENT(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_DEPENDENT) -#define JSSTRING_IS_MUTABLE(str) (((str)->length & JSSTRFLAG_MASK) == \ +#define JSSTRING_IS_FLAT(str) (!JSSTRING_IS_DEPENDENT(str)) +#define JSSTRING_IS_MUTABLE(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \ + JSSTRFLAG_MUTABLE)) == \ JSSTRFLAG_MUTABLE) +#define JSSTRING_IS_ATOMIZED(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \ + JSSTRFLAG_ATOMIZED)) ==\ + JSSTRFLAG_ATOMIZED) #define JSSTRING_CHARS(str) (JSSTRING_IS_DEPENDENT(str) \ ? JSSTRDEP_CHARS(str) \ - : (str)->u.chars) + : JSFLATSTR_CHARS(str)) #define JSSTRING_LENGTH(str) (JSSTRING_IS_DEPENDENT(str) \ ? JSSTRDEP_LENGTH(str) \ - : ((str)->length & ~JSSTRFLAG_MUTABLE)) + : JSFLATSTR_LENGTH(str)) #define JSSTRING_CHARS_AND_LENGTH(str, chars_, length_) \ ((void)(JSSTRING_IS_DEPENDENT(str) \ ? ((length_) = JSSTRDEP_LENGTH(str), \ (chars_) = JSSTRDEP_CHARS(str)) \ - : ((length_) = (str)->length & ~JSSTRFLAG_MUTABLE, \ - (chars_) = (str)->u.chars))) + : ((length_) = JSFLATSTR_LENGTH(str), \ + (chars_) = JSFLATSTR_CHARS(str)))) #define JSSTRING_CHARS_AND_END(str, chars_, end) \ ((void)((end) = JSSTRING_IS_DEPENDENT(str) \ ? JSSTRDEP_LENGTH(str) + ((chars_) = JSSTRDEP_CHARS(str)) \ - : ((str)->length & ~JSSTRFLAG_MUTABLE) + \ - ((chars_) = (str)->u.chars))) + : JSFLATSTR_LENGTH(str) + ((chars_) = JSFLATSTR_CHARS(str)))) -#define JSSTRING_LENGTH_BITS (sizeof(size_t) * JS_BITS_PER_BYTE \ - - JSSTRFLAG_BITS) -#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS) - -#define JSSTRING_INIT(str, chars_, length_) \ - ((void)(JS_ASSERT(((length_) & JSSTRFLAG_MASK) == 0), \ +/* Specific flat string initializer and accessor macros. */ +#define JSFLATSTR_INIT(str, chars_, length_) \ + ((void)(JS_ASSERT(((length_) & ~JSSTRING_LENGTH_MASK) == 0), \ (str)->length = (length_), (str)->u.chars = (chars_))) -/* Specific mutable string manipulation macros. */ -#define JSSTRING_SET_MUTABLE(str) \ - ((void)(JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), \ +#define JSFLATSTR_LENGTH(str) \ + (JS_ASSERT(JSSTRING_IS_FLAT(str)), (str)->length & JSSTRING_LENGTH_MASK) + +#define JSFLATSTR_CHARS(str) \ + (JS_ASSERT(JSSTRING_IS_FLAT(str)), (str)->u.chars) + +/* + * Macros to manipulate atomized and mutable flags of flat strings. It is safe + * to use these without extra locking due to the following properties: + * + * * We do not have a macro like JSFLATSTR_CLEAR_ATOMIZED as a string + * remains atomized until the GC collects it. + * + * * A thread may call JSFLATSTR_SET_MUTABLE only when it is the only thread + * accessing the string until a later call to JSFLATSTR_CLEAR_MUTABLE. + * + * * Multiple threads can call JSFLATSTR_CLEAR_MUTABLE but the macro + * actually clears the mutable flag only when the flag is set -- in which + * case only one thread can access the string (see previous property). + * + * Thus, when multiple threads access the string, JSFLATSTR_SET_ATOMIZED is + * the only macro that can update the length field of the string by changing + * the mutable bit from 0 to 1. We call the macro only after the string has + * been hashed. When some threads in js_ValueToStringId see that the flag is + * set, it knows that the string was atomized. + * + * On the other hand, if the thread sees that the flag is unset, it could be + * seeing a stale value when another thread has just atomized the string and + * set the flag. But this can lead only to an extra call to js_AtomizeString. + * This function would find that the string was already hashed and return it + * with the atomized bit set. + */ +#define JSFLATSTR_SET_ATOMIZED(str) \ + ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_MUTABLE(str)), \ + (str)->length |= JSSTRFLAG_ATOMIZED)) + +#define JSFLATSTR_SET_MUTABLE(str) \ + ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_ATOMIZED(str)), \ (str)->length |= JSSTRFLAG_MUTABLE)) -#define JSSTRING_CLEAR_MUTABLE(str) \ - ((void)(JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), \ - (str)->length &= ~JSSTRFLAG_MUTABLE)) +#define JSFLATSTR_CLEAR_MUTABLE(str) \ + ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str)), \ + JSSTRING_HAS_FLAG(str, JSSTRFLAG_MUTABLE) && \ + ((str)->length &= ~JSSTRFLAG_MUTABLE))) /* Specific dependent string shift/mask accessor and mutator macros. */ #define JSSTRDEP_START_BITS (JSSTRING_LENGTH_BITS-JSSTRDEP_LENGTH_BITS) @@ -188,7 +231,7 @@ struct JSString { #define JSSTRDEP_CHARS(str) \ (JSSTRING_IS_DEPENDENT(JSSTRDEP_BASE(str)) \ ? js_GetDependentStringChars(str) \ - : JSSTRDEP_BASE(str)->u.chars + JSSTRDEP_START(str)) + : JSFLATSTR_CHARS(JSSTRDEP_BASE(str)) + JSSTRDEP_START(str)) extern size_t js_MinimizeDependentStrings(JSString *str, int level, JSString **basep); diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 15ab24ee2711..4c58904cf861 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 17) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 18) /* * Library-private functions. diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index e7bc328ce213..c0db5daff00d 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -1314,15 +1314,12 @@ xml_setting_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) static JSBool xml_setting_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { - JSBool b; uint8 flag; JS_ASSERT(JSVAL_IS_INT(id)); - if (!js_ValueToBoolean(cx, *vp, &b)) - return JS_FALSE; flag = JS_BIT(JSVAL_TO_INT(id)); - if (b) + if (js_ValueToBoolean(*vp)) cx->xmlSettingFlags |= flag; else cx->xmlSettingFlags &= ~flag; @@ -1894,14 +1891,13 @@ FillSettingsCache(JSContext *cx) int i; const char *name; jsval v; - JSBool isSet; /* Note: XML_PRETTY_INDENT is not a boolean setting. */ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) { name = xml_static_props[i].name; - if (!GetXMLSetting(cx, name, &v) || !js_ValueToBoolean(cx, v, &isSet)) + if (!GetXMLSetting(cx, name, &v)) return JS_FALSE; - if (isSet) + if (js_ValueToBoolean(v)) cx->xmlSettingFlags |= JS_BIT(i); else cx->xmlSettingFlags &= ~JS_BIT(i); @@ -3121,7 +3117,7 @@ ToAttributeName(JSContext *cx, jsval v) if (!qn) return NULL; - JS_PUSH_TEMP_ROOT_GCTHING(cx, qn, &tvr); + JS_PUSH_TEMP_ROOT_QNAME(cx, qn, &tvr); obj = js_GetAttributeNameObject(cx, qn); JS_POP_TEMP_ROOT(cx, &tvr); if (!obj) @@ -7559,7 +7555,7 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class) xml = js_NewXML(cx, xml_class); if (!xml) return NULL; - JS_PUSH_TEMP_ROOT_GCTHING(cx, xml, &tvr); + JS_PUSH_TEMP_ROOT_XML(cx, xml, &tvr); obj = js_GetXMLObject(cx, xml); JS_POP_TEMP_ROOT(cx, &tvr); return obj; @@ -7896,7 +7892,7 @@ js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2) str = js_NewStringCopyN(cx, chars, len); if (!str) return NULL; - chars = str->u.chars; + chars = JSFLATSTR_CHARS(str); } else { /* * Reallocating str (because we know it has no other references) @@ -7911,7 +7907,7 @@ js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2) if (!chars) return NULL; - JSSTRING_INIT(str, chars, newlen); + JSFLATSTR_INIT(str, chars, newlen); chars += len; if (isName) { *chars++ = ' '; @@ -8191,7 +8187,7 @@ js_DeleteXMLListElements(JSContext *cx, JSObject *listobj) JSBool js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp) { - JSBool ok, match; + JSBool ok; JSStackFrame *fp; uint32 flags; JSObject *scobj, *listobj, *resobj, *withobj, *kidobj; @@ -8244,8 +8240,8 @@ js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp) if (!kidobj) break; OBJ_SET_PROTO(cx, withobj, kidobj); - ok = js_Interpret(cx, pc, vp) && js_ValueToBoolean(cx, *vp, &match); - if (ok && match) + ok = js_Interpret(cx, pc, vp); + if (ok && js_ValueToBoolean(*vp)) ok = Append(cx, result, kid); if (!ok) break; diff --git a/js/src/win32.order b/js/src/win32.order index cf4e8c41ce5d..663a6125d4fb 100644 --- a/js/src/win32.order +++ b/js/src/win32.order @@ -9,11 +9,9 @@ js_MatchToken ; 980277 js_CompareStrings ; 662772 js_Lock ; 628184 js_Unlock ; 628184 -js_AtomizeString ; 611102 js_HashString ; 611102 js_DropScopeProperty ; 546476 JS_malloc ; 484350 -js_Atomize ; 464433 js_InflateStringToBuffer ; 460739 js_HoldScopeProperty ; 442612 JS_free ; 382991 @@ -46,7 +44,6 @@ JS_GetFrameFunctionObject ; 120567 js_AllocGCThing ; 119828 js_DestroyScopeProperty ; 115989 js_Emit3 ; 109135 -js_AtomizeChars ; 108038 JS_HashTableLookup ; 107154 JS_InstanceOf ; 103905 js_DefineProperty ; 99514 @@ -166,7 +163,6 @@ js_NewScript ; 4941 js_InitCodeGenerator ; 4810 js_FinishTakingSrcNotes ; 4810 js_NewScriptFromParams ; 4810 -js_InitAtomMap ; 4810 js_FinishTakingTryNotes ; 4810 js_NewScriptFromCG ; 4810 js_FinishCodeGenerator ; 4810 @@ -360,7 +356,6 @@ js_InitScriptClass ; 19 js_obj_toString ; 15 js_GetArgsValue ; 14 js_GetArgsObject ; 14 -js_AtomizeDouble ; 12 JS_DestroyIdArray ; 11 js_NewIdArray ; 11 JS_GetElement ; 11 diff --git a/js/src/xpconnect/loader/mozJSComponentLoader.cpp b/js/src/xpconnect/loader/mozJSComponentLoader.cpp index 7afbb0d42d4f..f132b5f87d06 100644 --- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp @@ -83,6 +83,10 @@ #include "prmem.h" #include "plbase64.h" +#ifdef MOZ_SHARK +#include "jsdbgapi.h" +#endif + static const char kJSRuntimeServiceContractID[] = "@mozilla.org/js/xpc/RuntimeService;1"; static const char kXPConnectServiceContractID[] = "@mozilla.org/js/xpc/XPConnect;1"; static const char kObserverServiceContractID[] = "@mozilla.org/observer-service;1"; @@ -272,7 +276,12 @@ static JSFunctionSpec gGlobalFun[] = { {"debug", Debug, 1,0,0}, {"atob", Atob, 1,0,0}, {"btoa", Btoa, 1,0,0}, - +#ifdef MOZ_SHARK + {"startShark", js_StartShark, 0,0,0}, + {"stopShark", js_StopShark, 0,0,0}, + {"connectShark", js_ConnectShark, 0,0,0}, + {"disconnectShark", js_DisconnectShark,0,0,0}, +#endif {nsnull,nsnull,0,0,0} }; diff --git a/js/src/xpconnect/sample/xpcsample1.cpp b/js/src/xpconnect/sample/xpcsample1.cpp index 4ec1c77fc725..d0374047f792 100644 --- a/js/src/xpconnect/sample/xpcsample1.cpp +++ b/js/src/xpconnect/sample/xpcsample1.cpp @@ -244,8 +244,8 @@ nsXPCSample_HookerUpper::CreateSampleObjectAtGlobalScope(const char *name, PRInt return NS_ERROR_FAILURE; // get the xpconnect native call context - nsCOMPtr callContext; - xpc->GetCurrentNativeCallContext(getter_AddRefs(callContext)); + nsAXPCNativeCallContext *callContext = nsnull; + xpc->GetCurrentNativeCallContext(&callContext); if(!callContext) return NS_ERROR_FAILURE; diff --git a/js/src/xpconnect/shell/xpcshell.cpp b/js/src/xpconnect/shell/xpcshell.cpp index 7a761876c329..2f01617d3499 100644 --- a/js/src/xpconnect/shell/xpcshell.cpp +++ b/js/src/xpconnect/shell/xpcshell.cpp @@ -431,10 +431,10 @@ static JSFunctionSpec glob_functions[] = { {"dumpHeap", DumpHeap, 5,0,0}, #endif #ifdef MOZ_SHARK - {"startShark", StartShark, 0,0,0}, - {"stopShark", StopShark, 0,0,0}, - {"connectShark", ConnectShark, 0,0,0}, - {"disconnectShark", DisconnectShark,0,0,0}, + {"startShark", js_StartShark, 0,0,0}, + {"stopShark", js_StopShark, 0,0,0}, + {"connectShark", js_ConnectShark, 0,0,0}, + {"disconnectShark", js_DisconnectShark, 0,0,0}, #endif {nsnull,nsnull,0,0,0} }; @@ -896,7 +896,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc) break; #ifdef MOZ_SHARK case 'k': - js_ConnectShark(); + JS_ConnectShark(); break; #endif default: diff --git a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp index 7c7c9981121e..1ad188b914fa 100644 --- a/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp +++ b/js/src/xpconnect/src/XPCCrossOriginWrapper.cpp @@ -835,11 +835,17 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JS_STATIC_DLL_CALLBACK(JSBool) XPC_XOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) { + // Don't do any work to convert to object. + if (type == JSTYPE_OBJECT) { + *vp = OBJECT_TO_JSVAL(obj); + return JS_TRUE; + } + JSObject *wrappedObj = GetWrappedObject(cx, obj); if (!wrappedObj) { // Converting the prototype to something. - if (type == JSTYPE_STRING) { + if (type == JSTYPE_STRING || type == JSTYPE_VOID) { return XPC_XOW_toString(cx, obj, 0, nsnull, vp); } @@ -859,8 +865,13 @@ XPC_XOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) return JS_FALSE; } - // TODO wrap return value? - return JS_GET_CLASS(cx, wrappedObj)->convert(cx, wrappedObj, type, vp); + if (!JS_GET_CLASS(cx, wrappedObj)->convert(cx, wrappedObj, type, vp)) { + return JS_FALSE; + } + + return NS_SUCCEEDED(rv) + ? WrapSameOriginProp(cx, obj, vp) + : XPC_XOW_RewrapIfNeeded(cx, obj, vp); } JS_STATIC_DLL_CALLBACK(void) diff --git a/js/src/xpconnect/src/XPCWrapper.cpp b/js/src/xpconnect/src/XPCWrapper.cpp index c219c77ba409..6fe51e718e64 100644 --- a/js/src/xpconnect/src/XPCWrapper.cpp +++ b/js/src/xpconnect/src/XPCWrapper.cpp @@ -448,26 +448,20 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj, return MaybePreserveWrapper(cx, wn, flags); } - // Get (and perhaps lazily create) the member's value (commonly a - // cloneable function). - jsval memberval; - if (!member->GetValue(ccx, iface, &memberval)) { - return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx); - } - - // Make sure memberval doesn't go away while we mess with it. - AUTO_MARK_JSVAL(ccx, memberval); - JSString *str = JSVAL_TO_STRING(id); if (!str) { return ThrowException(NS_ERROR_UNEXPECTED, cx); } + // Get (and perhaps lazily create) the member's value (commonly a + // cloneable function). jsval v; uintN attrs = JSPROP_ENUMERATE; if (member->IsConstant()) { - v = memberval; + if (!member->GetConstantValue(ccx, iface, &v)) { + return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx); + } } else if (member->IsAttribute()) { // An attribute is being resolved. Define the property, the value // will be dealt with in the get/set hooks. Use JSPROP_SHARED to @@ -481,24 +475,28 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj, // use for this object. NB: cx's newborn roots will protect funobj // and funWrapper and its object from GC. - JSObject* funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(memberval), - wrapper->GetFlatJSObject()); - if (!funobj) { - return JS_FALSE; + jsval funval; + if (!member->NewFunctionObject(ccx, iface, wrapper->GetFlatJSObject(), + &funval)) { + return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx); } - AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(funobj)); + AUTO_MARK_JSVAL(ccx, funval); #ifdef DEBUG_XPCNativeWrapper printf("Wrapping function object for %s\n", ::JS_GetStringBytes(JSVAL_TO_STRING(id))); #endif - if (!WrapFunction(cx, wrapperObj, funobj, &v, isNativeWrapper)) { + if (!WrapFunction(cx, wrapperObj, JSVAL_TO_OBJECT(funval), &v, + isNativeWrapper)) { return JS_FALSE; } } + // Make sure v doesn't go away while we mess with it. + AUTO_MARK_JSVAL(ccx, v); + // XPCNativeWrapper doesn't need to do this. jsval oldFlags; if (!isNativeWrapper && @@ -604,14 +602,12 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj, return JS_TRUE; } - // Get (and perhaps lazily create) the member's value (commonly a - // cloneable function). - jsval memberval; - if (!member->GetValue(ccx, iface, &memberval)) { - return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx); - } - if (member->IsConstant()) { + jsval memberval; + if (!member->GetConstantValue(ccx, iface, &memberval)) { + return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx); + } + // Getting the value of constants is easy, just return the // value. Setting is not supported (obviously). if (aIsSet) { @@ -630,17 +626,14 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj, return JS_TRUE; } - // Make sure the function we're cloning doesn't go away while - // we're cloning it. - AUTO_MARK_JSVAL(ccx, memberval); - - // clone a function we can use for this object - JSObject* funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(memberval), - wrapper->GetFlatJSObject()); - if (!funobj) { - return JS_FALSE; + jsval funval; + if (!member->NewFunctionObject(ccx, iface, wrapper->GetFlatJSObject(), + &funval)) { + return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx); } + AUTO_MARK_JSVAL(ccx, funval); + jsval *argv = nsnull; uintN argc = 0; @@ -666,8 +659,8 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj, // Call the getter jsval v; - if (!::JS_CallFunctionValue(cx, wrapper->GetFlatJSObject(), - OBJECT_TO_JSVAL(funobj), argc, argv, &v)) { + if (!::JS_CallFunctionValue(cx, wrapper->GetFlatJSObject(), funval, argc, + argv, &v)) { return JS_FALSE; } @@ -711,34 +704,22 @@ XPCWrapper::NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative, XPCNativeInterface *iface = ccx.GetInterface(); XPCNativeMember *member = ccx.GetMember(); - JSBool overridden = JS_FALSE; - jsval toStringVal; + JSString* str = nsnull; // First, try to see if the object declares a toString in its IDL. If it does, // then we need to defer to that. - if (iface && member) { - if (!member->GetValue(ccx, iface, &toStringVal)) { + if (iface && member && member->IsMethod()) { + jsval toStringVal; + if (!member->NewFunctionObject(ccx, iface, wn_obj, &toStringVal)) { return JS_FALSE; } - overridden = member->IsMethod(); - } - - JSString* str = nsnull; - if (overridden) { // Defer to the IDL-declared toString. AUTO_MARK_JSVAL(ccx, toStringVal); - JSObject *funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(toStringVal), - wn_obj); - if (!funobj) { - return JS_FALSE; - } - jsval v; - if (!::JS_CallFunctionValue(cx, wn_obj, OBJECT_TO_JSVAL(funobj), argc, argv, - &v)) { + if (!::JS_CallFunctionValue(cx, wn_obj, toStringVal, argc, argv, &v)) { return JS_FALSE; } diff --git a/js/src/xpconnect/src/XPCWrapper.h b/js/src/xpconnect/src/XPCWrapper.h index 42771ac8c3ff..9b76bf9b7224 100644 --- a/js/src/xpconnect/src/XPCWrapper.h +++ b/js/src/xpconnect/src/XPCWrapper.h @@ -87,7 +87,6 @@ XPC_XOW_ClassNeedsXOW(const char *name) // TODO Make a perfect hash of these and use that? return !strcmp(name, "Window") || !strcmp(name, "Location") || - !strcmp(name, "HTMLDocument") || !strcmp(name, "HTMLIFrameElement") || !strcmp(name, "HTMLFrameElement"); } diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index c165a6bcda3d..aba51c313e64 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -1613,7 +1613,7 @@ nsXPConnect::GetCurrentNativeCallContext(nsAXPCNativeCallContext * *aCurrentNati { NS_ASSERTION(aCurrentNativeCallContext, "bad param"); - XPCPerThreadData* data = XPCPerThreadData::GetData(); + XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull); if(data) { *aCurrentNativeCallContext = data->GetCallContext(); @@ -1630,7 +1630,7 @@ nsXPConnect::GetPendingException(nsIException * *aPendingException) { NS_ASSERTION(aPendingException, "bad param"); - XPCPerThreadData* data = XPCPerThreadData::GetData(); + XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull); if(!data) { *aPendingException = nsnull; @@ -1643,7 +1643,7 @@ nsXPConnect::GetPendingException(nsIException * *aPendingException) NS_IMETHODIMP nsXPConnect::SetPendingException(nsIException * aPendingException) { - XPCPerThreadData* data = XPCPerThreadData::GetData(); + XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull); if(!data) return UnexpectedFailure(NS_ERROR_FAILURE); @@ -1993,7 +1993,7 @@ NS_IMETHODIMP nsXPConnect::ReleaseJSContext(JSContext * aJSContext, PRBool noGC) { NS_ASSERTION(aJSContext, "bad param"); - XPCPerThreadData* tls = XPCPerThreadData::GetData(); + XPCPerThreadData* tls = XPCPerThreadData::GetData(aJSContext); if(tls) { XPCCallContext* ccx = nsnull; diff --git a/js/src/xpconnect/src/xpccallcontext.cpp b/js/src/xpconnect/src/xpccallcontext.cpp index b43cd2a5fa70..46004c04a869 100644 --- a/js/src/xpconnect/src/xpccallcontext.cpp +++ b/js/src/xpconnect/src/xpccallcontext.cpp @@ -77,7 +77,9 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage, NS_ADDREF(mXPC); - if(!(mThreadData = XPCPerThreadData::GetData())) + mThreadData = XPCPerThreadData::GetData(mJSContext); + + if(!mThreadData) return; XPCJSContextStack* stack = mThreadData->GetJSContextStack(); @@ -357,7 +359,7 @@ XPCCallContext::~XPCCallContext() // Don't clear newborns if JS frames (compilation or execution) // are active! Doing so violates ancient invariants in the JS // engine, and it's not necessary to fix JS component leaks. - if (!mJSContext->fp) + if(!mJSContext->fp) JS_ClearNewbornRoots(mJSContext); } } @@ -389,7 +391,8 @@ XPCCallContext::NewStringWrapper(PRUnichar *str, PRUint32 len) { StringWrapperEntry& ent = se[i]; - if (!ent.mInUse) { + if(!ent.mInUse) + { ent.mInUse = PR_TRUE; // Construct the string using placement new. @@ -413,7 +416,7 @@ XPCCallContext::DeleteString(nsAString *string) for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) { StringWrapperEntry& ent = se[i]; - if (string == &ent.mString) + if(string == &ent.mString) { // One of our internal strings is no longer in use, mark // it as such and destroy the string. diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index 82545728723b..145ca8b8c5ec 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -2825,23 +2825,14 @@ nsXPCComponents_Utils::LookupMethod() if(!iface) return NS_ERROR_XPC_BAD_CONVERT_JS; - // get (and perhaps lazily create) the member's cloneable function + // get (and perhaps lazily create) the member's cloned function jsval funval; - if(!member->GetValue(inner_cc, iface, &funval)) - return NS_ERROR_XPC_BAD_CONVERT_JS; - - // Make sure the function we're cloning doesn't go away while - // we're cloning it. - AUTO_MARK_JSVAL(inner_cc, funval); - - // clone a function we can use for this object - JSObject* funobj = xpc_CloneJSFunction(inner_cc, JSVAL_TO_OBJECT(funval), - wrapper->GetFlatJSObject()); - if(!funobj) + if(!member->NewFunctionObject(inner_cc, iface, wrapper->GetFlatJSObject(), + &funval)) return NS_ERROR_XPC_BAD_CONVERT_JS; // return the function and let xpconnect know we did so - *retval = OBJECT_TO_JSVAL(funobj); + *retval = funval; cc->SetReturnValueWasSet(PR_TRUE); return NS_OK; @@ -3515,7 +3506,7 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, return NS_ERROR_OUT_OF_MEMORY; } - XPCPerThreadData *data = XPCPerThreadData::GetData(); + XPCPerThreadData *data = XPCPerThreadData::GetData(cx); XPCJSContextStack *stack = nsnull; if (data && (stack = data->GetJSContextStack())) { if (NS_FAILED(stack->Push(sandcx->GetJSContext()))) { diff --git a/js/src/xpconnect/src/xpcjsid.cpp b/js/src/xpconnect/src/xpcjsid.cpp index 174426583d92..adadfd1be683 100644 --- a/js/src/xpconnect/src/xpcjsid.cpp +++ b/js/src/xpconnect/src/xpcjsid.cpp @@ -508,7 +508,7 @@ nsJSIID::NewResolve(nsIXPConnectWrappedNative *wrapper, if(member && member->IsConstant()) { jsval val; - if(!member->GetValue(ccx, iface, &val)) + if(!member->GetConstantValue(ccx, iface, &val)) return NS_ERROR_OUT_OF_MEMORY; jsid idid; diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index 2dedd54b137a..c083b5169f73 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -238,7 +238,7 @@ ContextCallback(JSContext *cx, uintN operation) { if (operation == JSCONTEXT_NEW) { - XPCPerThreadData* tls = XPCPerThreadData::GetData(); + XPCPerThreadData* tls = XPCPerThreadData::GetData(cx); if(tls) { JS_SetThreadStackLimit(cx, tls->GetStackLimit()); @@ -1201,7 +1201,7 @@ XPCJSRuntime::SyncXPCContextList(JSContext* cx /* = nsnull */) // get rid of any XPCContexts that represent dead JSContexts mContextMap->Enumerate(SweepContextsCB, 0); - XPCPerThreadData* tls = XPCPerThreadData::GetData(); + XPCPerThreadData* tls = XPCPerThreadData::GetData(cx); if(tls) { if(found) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index df397e0697eb..fa919eea71ef 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -1169,6 +1169,7 @@ extern JSClass XPC_WN_NoMods_NoCall_Proto_JSClass; extern JSClass XPC_WN_ModsAllowed_WithCall_Proto_JSClass; extern JSClass XPC_WN_ModsAllowed_NoCall_Proto_JSClass; extern JSClass XPC_WN_Tearoff_JSClass; +extern JSClass XPC_WN_NoHelper_Proto_JSClass; extern JSObjectOps * JS_DLL_CALLBACK XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz); @@ -1176,6 +1177,9 @@ XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz); extern JSObjectOps * JS_DLL_CALLBACK XPC_WN_GetObjectOpsWithCall(JSContext *cx, JSClass *clazz); +extern JSObjectOps * JS_DLL_CALLBACK +XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz); + extern JSBool JS_DLL_CALLBACK XPC_WN_CallMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp); @@ -1233,6 +1237,11 @@ public: JSObject* GetPrototypeJSObject() const {return mPrototypeJSObject;} + // Getter for the prototype that we use for wrappers that have no + // helper. + JSObject* + GetPrototypeNoHelper(XPCCallContext& ccx); + #ifndef XPCONNECT_STANDALONE nsIPrincipal* GetPrincipal() const @@ -1329,8 +1338,14 @@ private: // unless a PreCreate hook overrides it. Note that this _may_ be null (see // constructor). JSObject* mGlobalJSObject; + + // Cached value of Object.prototype JSObject* mPrototypeJSObject; + // Cached value of Function.prototype JSObject* mPrototypeJSFunction; + // Prototype to use for wrappers with no helper. + JSObject* mPrototypeNoHelper; + XPCContext* mContext; #ifndef XPCONNECT_STANDALONE @@ -1343,6 +1358,9 @@ private: #endif }; +JSObject* xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj, + JSObject *parent); + /***************************************************************************/ // XPCNativeMember represents a single idl declared method, attribute or // constant. @@ -1361,10 +1379,23 @@ public: PRUint16 GetIndex() const {return mIndex;} - JSBool GetValue(XPCCallContext& ccx, XPCNativeInterface* iface, jsval* pval) - {if(!IsResolved() && !Resolve(ccx, iface)) return JS_FALSE; + JSBool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface, + jsval* pval) + {NS_ASSERTION(IsConstant(), + "Only call this if you're sure this is a constant!"); + if(!IsResolved() && !Resolve(ccx, iface)) return JS_FALSE; *pval = mVal; return JS_TRUE;} + JSBool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface, + JSObject *parent, jsval* pval) + {NS_ASSERTION(!IsConstant(), + "Only call this if you're sure this is not a constant!"); + if(!IsResolved() && !Resolve(ccx, iface)) return JS_FALSE; + JSObject* funobj = + xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(mVal), parent); + if(!funobj) return JS_FALSE; + *pval = OBJECT_TO_JSVAL(funobj); return JS_TRUE;} + JSBool IsMethod() const {return 0 != (mFlags & METHOD);} @@ -3010,7 +3041,19 @@ class XPCPerThreadData { public: // Get the instance of this object for the current thread - static XPCPerThreadData* GetData(); + static inline XPCPerThreadData* GetData(JSContext *cx) + { + if(cx) + { + NS_ASSERTION(cx->thread, "Uh, JS context w/o a thread?"); + + if(cx->thread == sMainJSThread) + return sMainThreadData; + } + + return GetDataImpl(cx); + } + static void CleanupAllThreads(); ~XPCPerThreadData(); @@ -3112,8 +3155,12 @@ public: {mWrappedNativeThreadsafetyReportDepth = 0;} #endif + static void ShutDown() + {sMainJSThread = nsnull; sMainThreadData = nsnull;} + private: XPCPerThreadData(); + static XPCPerThreadData* GetDataImpl(JSContext *cx); private: XPCJSContextStack* mJSContextStack; @@ -3140,6 +3187,13 @@ private: static PRLock* gLock; static XPCPerThreadData* gThreads; static PRUintn gTLSIndex; + + // Cached value of cx->thread on the main thread. + static void *sMainJSThread; + + // Cached per thread data for the main thread. Only safe to access + // if cx->thread == sMainJSThread. + static XPCPerThreadData *sMainThreadData; }; /**************************************************************/ @@ -3168,8 +3222,8 @@ public: virtual ~nsXPCThreadJSContextStackImpl(); private: - XPCJSContextStack* GetStackForCurrentThread() - {XPCPerThreadData* data = XPCPerThreadData::GetData(); + XPCJSContextStack* GetStackForCurrentThread(JSContext *cx = nsnull) + {XPCPerThreadData* data = XPCPerThreadData::GetData(cx); return data ? data->GetJSContextStack() : nsnull;} static nsXPCThreadJSContextStackImpl* gXPCThreadJSContextStack; @@ -3852,9 +3906,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(PrincipalHolder, PRINCIPALHOLDER_IID) JSBool xpc_IsReportableErrorCode(nsresult code); -JSObject* xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj, - JSObject *parent); - #ifndef XPCONNECT_STANDALONE // Helper for creating a sandbox object to use for evaluating diff --git a/js/src/xpconnect/src/xpcruntimesvc.cpp b/js/src/xpconnect/src/xpcruntimesvc.cpp index 1400cf734db1..64d8af3a8595 100644 --- a/js/src/xpconnect/src/xpcruntimesvc.cpp +++ b/js/src/xpconnect/src/xpcruntimesvc.cpp @@ -201,6 +201,8 @@ nsJSRuntimeServiceImpl::~nsJSRuntimeServiceImpl() { fprintf(stderr, "nJRSI: destroyed runtime %p\n", (void *)mRuntime); #endif } + + XPCPerThreadData::ShutDown(); } NS_IMPL_THREADSAFE_ISUPPORTS2(nsJSRuntimeServiceImpl, @@ -257,7 +259,7 @@ nsJSRuntimeServiceImpl::GetRuntime(JSRuntime **runtime) // // We rely on the implementation of NSPR that calls destructors at // the same order of calling PR_NewThreadPrivateIndex. - XPCPerThreadData::GetData(); + XPCPerThreadData::GetData(nsnull); mRuntime = JS_NewRuntime(gGCSize); if(!mRuntime) diff --git a/js/src/xpconnect/src/xpcthreadcontext.cpp b/js/src/xpconnect/src/xpcthreadcontext.cpp index 9069c62ac0f4..464304adace9 100644 --- a/js/src/xpconnect/src/xpcthreadcontext.cpp +++ b/js/src/xpconnect/src/xpcthreadcontext.cpp @@ -384,7 +384,7 @@ nsXPCThreadJSContextStackImpl::Pop(JSContext * *_retval) NS_IMETHODIMP nsXPCThreadJSContextStackImpl::Push(JSContext * cx) { - XPCJSContextStack* myStack = GetStackForCurrentThread(); + XPCJSContextStack* myStack = GetStackForCurrentThread(cx); if(!myStack) return NS_ERROR_FAILURE; @@ -413,7 +413,7 @@ nsXPCThreadJSContextStackImpl::GetSafeJSContext(JSContext * *aSafeJSContext) NS_IMETHODIMP nsXPCThreadJSContextStackImpl::SetSafeJSContext(JSContext * aSafeJSContext) { - XPCJSContextStack* myStack = GetStackForCurrentThread(); + XPCJSContextStack* myStack = GetStackForCurrentThread(aSafeJSContext); if(!myStack) return NS_ERROR_FAILURE; @@ -423,9 +423,11 @@ nsXPCThreadJSContextStackImpl::SetSafeJSContext(JSContext * aSafeJSContext) /***************************************************************************/ -PRUintn XPCPerThreadData::gTLSIndex = BAD_TLS_INDEX; -PRLock* XPCPerThreadData::gLock = nsnull; -XPCPerThreadData* XPCPerThreadData::gThreads = nsnull; +PRUintn XPCPerThreadData::gTLSIndex = BAD_TLS_INDEX; +PRLock* XPCPerThreadData::gLock = nsnull; +XPCPerThreadData* XPCPerThreadData::gThreads = nsnull; +XPCPerThreadData *XPCPerThreadData::sMainThreadData = nsnull; +void * XPCPerThreadData::sMainJSThread = nsnull; static jsuword GetThreadStackLimit() @@ -559,7 +561,7 @@ void XPCPerThreadData::MarkAutoRootsAfterJSFinalize() // static XPCPerThreadData* -XPCPerThreadData::GetData() +XPCPerThreadData::GetDataImpl(JSContext *cx) { XPCPerThreadData* data; @@ -604,6 +606,14 @@ XPCPerThreadData::GetData() return nsnull; } } + + if(cx && !sMainJSThread && NS_IsMainThread()) + { + sMainJSThread = cx->thread; + + sMainThreadData = data; + } + return data; } diff --git a/js/src/xpconnect/src/xpcthrower.cpp b/js/src/xpconnect/src/xpcthrower.cpp index ff49042ab0dd..1e211714d4ec 100644 --- a/js/src/xpconnect/src/xpcthrower.cpp +++ b/js/src/xpconnect/src/xpcthrower.cpp @@ -229,7 +229,7 @@ XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz) nsCOMPtr finalException; nsCOMPtr defaultException; nsXPCException::NewException(sz, rv, nsnull, nsnull, getter_AddRefs(defaultException)); - XPCPerThreadData* tls = XPCPerThreadData::GetData(); + XPCPerThreadData* tls = XPCPerThreadData::GetData(cx); if(tls) { nsIExceptionManager * exceptionManager = tls->GetExceptionManager(); diff --git a/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/js/src/xpconnect/src/xpcwrappedjsclass.cpp index 5f44138d0a2e..811f113eae42 100644 --- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -503,6 +503,12 @@ nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr) static JSContext * GetContextFromObject(JSObject *obj) { + // Don't stomp over running code. + nsAXPCNativeCallContext *cc = nsnull; + nsXPConnect::GetXPConnect()->GetCurrentNativeCallContext(&cc); + if(cc) + return nsnull; + // In order to get a context, we need a context. XPCCallContext ccx(NATIVE_CALLER); XPCWrappedNativeScope* scope = diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 16e4bcc068c6..be42b1c665ee 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -868,7 +868,11 @@ XPCWrappedNative::Init(XPCCallContext& ccx, JSObject* parent, JSBool isGlobal, JSObject* protoJSObject = HasProto() ? GetProto()->GetJSProtoObject() : - GetScope()->GetPrototypeJSObject(); + GetScope()->GetPrototypeNoHelper(ccx); + + if (!protoJSObject) { + return JS_FALSE; + } mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, jsclazz, protoJSObject, parent); @@ -1862,20 +1866,13 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx, nsXPTCVariant paramBuffer[PARAM_BUFFER_COUNT]; - // Number of nsAutoStrings to construct on the stack for use with method - // calls that use 'out' AStrings (aka [domstring]). These can save us from - // a new/delete of an nsString. But the cost is that the ctor/dtor code - // is run for each nsAutoString in the array for each call - whether or not - // a specific call actually uses *any* AStrings. Also, we have these - // large-ish nsAutoString objects using up stack space. - // - // Set this to zero to disable use of these auto strings. -#define PARAM_AUTOSTRING_COUNT 1 - -#if PARAM_AUTOSTRING_COUNT - nsVoidableString autoStrings[PARAM_AUTOSTRING_COUNT]; - int autoStringIndex = 0; -#endif + // Reserve space on the stack for one nsAutoString. We don't want + // the string itself to be declared on the stack as that would + // make the ctor and dtors run for each pass through this code, + // and they're only needed in a fraction of all the calls that + // come through here. + char autoString[sizeof(nsAutoString)]; + PRBool autoStringUsed = PR_FALSE; JSBool retval = JS_FALSE; @@ -2114,19 +2111,24 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx, // now and then continue in order to skip the call to // JSData2Native - // If autoStrings array support is enabld, then use - // one of them if they are not already used up. -#if PARAM_AUTOSTRING_COUNT - if(autoStringIndex < PARAM_AUTOSTRING_COUNT) + if(!autoStringUsed) { + // Our stack space for an nsAutoString is + // still available, initialize the string + // object (using placement new) and use + // it. + nsAutoString *s = (nsAutoString*)&autoString; + new (s) nsAutoString(); + autoStringUsed = PR_TRUE; + // Don't call SetValIsDOMString because we don't // want to delete this pointer. - dp->val.p = &autoStrings[autoStringIndex++]; + dp->val.p = s; continue; } -#endif + dp->SetValIsDOMString(); - if(!(dp->val.p = new nsVoidableString())) + if(!(dp->val.p = new nsAutoString())) { JS_ReportOutOfMemory(ccx); goto done; @@ -2526,6 +2528,14 @@ done: } } + if (autoStringUsed) { + // Our stack based nsAutoString was used, clean it up. + + nsAutoString *s = (nsAutoString*)&autoString; + + s->~nsAutoString(); + } + if(dispatchParams && dispatchParams != paramBuffer) delete [] dispatchParams; @@ -2840,7 +2850,9 @@ XPCWrappedNative::HandlePossibleNameCaseError(XPCCallContext& ccx, (JSBool)NS_PTR_TO_INT32(iface->FindMember(STRING_TO_JSVAL(newJSStr))))) { // found it! - const char* ifaceName = localIface->GetNameString(); + const char* ifaceName = set ? + localIface->GetNameString() : + iface->GetNameString(); const char* goodName = JS_GetStringBytes(newJSStr); const char* badName = JS_GetStringBytes(oldJSStr); char* locationStr = nsnull; diff --git a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp index e2b7fde114f5..57da14424019 100644 --- a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp +++ b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp @@ -193,6 +193,9 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface) AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(funobj)); + STOBJ_SET_PARENT(funobj, nsnull); + STOBJ_SET_PROTO(funobj, nsnull); + if(!JS_SetReservedSlot(ccx, funobj, 0, PRIVATE_TO_JSVAL(iface))|| !JS_SetReservedSlot(ccx, funobj, 1, PRIVATE_TO_JSVAL(this))) return JS_FALSE; diff --git a/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/js/src/xpconnect/src/xpcwrappednativejsops.cpp index 17dc86748c96..5b9e345ec833 100644 --- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -427,7 +427,7 @@ DefinePropertyIfFound(XPCCallContext& ccx, AutoResolveName arn(ccx, idval); if(resolved) *resolved = JS_TRUE; - return member->GetValue(ccx, iface, &val) && + return member->GetConstantValue(ccx, iface, &val) && JS_ValueToId(ccx, idval, &id) && OBJ_DEFINE_PROPERTY(ccx, obj, id, val, nsnull, nsnull, propFlags, nsnull); @@ -440,24 +440,12 @@ DefinePropertyIfFound(XPCCallContext& ccx, idval == rt->GetStringJSVal(XPCJSRuntime::IDX_QUERY_INTERFACE))) propFlags &= ~JSPROP_ENUMERATE; - JSObject* funobj; - - { - // scoped gc protection of funval - jsval funval; - - if(!member->GetValue(ccx, iface, &funval)) - return JS_FALSE; - - AUTO_MARK_JSVAL(ccx, funval); - - funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(funval), obj); - if(!funobj) - return JS_FALSE; - } + jsval funval; + if(!member->NewFunctionObject(ccx, iface, obj, &funval)) + return JS_FALSE; // protect funobj until it is actually attached - AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(funobj)); + AUTO_MARK_JSVAL(ccx, funval); #ifdef off_DEBUG_jband { @@ -473,8 +461,8 @@ DefinePropertyIfFound(XPCCallContext& ccx, if(resolved) *resolved = JS_TRUE; return JS_ValueToId(ccx, idval, &id) && - OBJ_DEFINE_PROPERTY(ccx, obj, id, OBJECT_TO_JSVAL(funobj), - nsnull, nsnull, propFlags, nsnull); + OBJ_DEFINE_PROPERTY(ccx, obj, id, funval, nsnull, nsnull, + propFlags, nsnull); } // else... @@ -491,6 +479,8 @@ DefinePropertyIfFound(XPCCallContext& ccx, AutoResolveName arn(ccx, idval); if(resolved) *resolved = JS_TRUE; + + JSObject* funobj = JSVAL_TO_OBJECT(funval); return JS_ValueToId(ccx, idval, &id) && OBJ_DEFINE_PROPERTY(ccx, obj, id, JSVAL_VOID, (JSPropertyOp) funobj, @@ -899,7 +889,7 @@ JSExtendedClass XPC_WN_NoHelper_JSClass = { XPC_WN_NoHelper_Finalize, // finalize; /* Optionally non-null members start here. */ - nsnull, // getObjectOps; + XPC_WN_GetObjectOpsNoCall, // getObjectOps; nsnull, // checkAccess; nsnull, // call; nsnull, // construct; @@ -1186,9 +1176,11 @@ JS_STATIC_DLL_CALLBACK(JSBool) XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, jsval *statep, jsid *idp) { - if(!IS_WRAPPER_CLASS(JS_GET_CLASS(cx, obj))) + JSClass *clazz = JS_GET_CLASS(cx, obj); + if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) { - // obj must be a prototype object. Short circuit this call to + // obj must be a prototype object or a wrapper w/o a + // helper. Short circuit this call to // js_ObjectOps.enumerate(). return js_ObjectOps.enumerate(cx, obj, enum_op, statep, idp); @@ -1633,7 +1625,8 @@ XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz) return &XPC_WN_WithCall_JSOps; NS_ASSERTION(clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass || - clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass, + clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass || + clazz == &XPC_WN_NoHelper_Proto_JSClass, "bad proto"); return &XPC_WN_NoCall_JSOps; diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index e9641cb7cc45..b5e93d4f1751 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -119,11 +119,12 @@ XPCWrappedNativeScope::GetNewOrUsed(XPCCallContext& ccx, JSObject* aGlobal) scope = new XPCWrappedNativeScope(ccx, aGlobal); else { - // We need to call SetGlobal in order to refresh our cached - // mPrototypeJSObject and mPrototypeJSFunction in the case where - // the global object is being reused (JS_ClearScope has been - // called). - // NOTE: We are only called by nsXPConnect::InitClasses. + // We need to call SetGlobal in order to refresh our cached + // mPrototypeJSObject and mPrototypeJSFunction and to clear + // mPrototypeNoHelper (so we get a new one if requested in the + // new scope) in the case where the global object is being + // reused (JS_ClearScope has been called). NOTE: We are only + // called by nsXPConnect::InitClasses. scope->SetGlobal(ccx, aGlobal); } return scope; @@ -139,7 +140,8 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx, mNext(nsnull), mGlobalJSObject(nsnull), mPrototypeJSObject(nsnull), - mPrototypeJSFunction(nsnull) + mPrototypeJSFunction(nsnull), + mPrototypeNoHelper(nsnull) { // add ourselves to the scopes list { // scoped lock @@ -187,6 +189,41 @@ XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents) mComponents = aComponents; } +// Dummy JS class to let wrappers w/o an xpc prototype share +// scopes. By doing this we avoid allocating a new scope for every +// wrapper on creation of the wrapper, and most wrappers won't need +// their own scope at all for the lifetime of the wrapper. +// JSCLASS_HAS_PRIVATE is key here (even though there's never anything +// in the private data slot in these prototypes), as the number of +// reserved slots in this class needs to match that of the wrappers +// for the JS engine to share scopes. + +JSClass XPC_WN_NoHelper_Proto_JSClass = { + "XPC_WN_NoHelper_Proto_JSClass",// name; + JSCLASS_HAS_PRIVATE, // flags; + + /* Mandatory non-null function pointer members. */ + JS_PropertyStub, // addProperty; + JS_PropertyStub, // delProperty; + JS_PropertyStub, // getProperty; + JS_PropertyStub, // setProperty; + JS_EnumerateStub, // enumerate; + JS_ResolveStub, // resolve; + JS_ConvertStub, // convert; + JS_FinalizeStub, // finalize; + + /* Optionally non-null members start here. */ + XPC_WN_Proto_GetObjectOps, // getObjectOps; + nsnull, // checkAccess; + nsnull, // call; + nsnull, // construct; + nsnull, // xdrObject; + nsnull, // hasInstance; + nsnull, // mark/trace; + nsnull // spare; +}; + + void XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal) { @@ -197,25 +234,24 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal) #ifndef XPCONNECT_STANDALONE mScriptObjectPrincipal = nsnull; // Now init our script object principal, if the new global has one - if (aGlobal) + + JSContext* cx = ccx.GetJSContext(); + const JSClass* jsClass = JS_GetClass(cx, aGlobal); + if(!(~jsClass->flags & (JSCLASS_HAS_PRIVATE | + JSCLASS_PRIVATE_IS_NSISUPPORTS))) { - JSContext* cx = ccx.GetJSContext(); - const JSClass* jsClass = JS_GetClass(cx, aGlobal); - if (jsClass && !(~jsClass->flags & (JSCLASS_HAS_PRIVATE | - JSCLASS_PRIVATE_IS_NSISUPPORTS))) + // Our global has an nsISupports native pointer. Let's + // see whether it's what we want. + nsISupports* priv = (nsISupports*)JS_GetPrivate(cx, aGlobal); + nsCOMPtr native = + do_QueryInterface(priv); + if(native) { - // Our global has an nsISupports native pointer. Let's - // see whether it's what we want. - nsISupports* priv = (nsISupports*)JS_GetPrivate(cx, aGlobal); - nsCOMPtr native = - do_QueryInterface(priv); - if (native) - { - mScriptObjectPrincipal = do_QueryWrappedNative(native); - } - if (!mScriptObjectPrincipal) { - mScriptObjectPrincipal = do_QueryInterface(priv); - } + mScriptObjectPrincipal = do_QueryWrappedNative(native); + } + if(!mScriptObjectPrincipal) + { + mScriptObjectPrincipal = do_QueryInterface(priv); } } #endif @@ -253,6 +289,10 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal) NS_ERROR("Can't get globalObject.Function.prototype"); } } + + // Clear the no helper wrapper prototype object so that a new one + // gets created if needed. + mPrototypeNoHelper = nsnull; } XPCWrappedNativeScope::~XPCWrappedNativeScope() @@ -288,6 +328,25 @@ XPCWrappedNativeScope::~XPCWrappedNativeScope() NS_IF_RELEASE(mComponents); } +JSObject * +XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx) +{ + // We could create this prototype in SetGlobal(), but all scopes + // don't need one, so we save ourselves a bit of space if we + // create these when they're needed. + if(!mPrototypeNoHelper) + { + mPrototypeNoHelper = + xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_NoHelper_Proto_JSClass, + mPrototypeJSObject, + mGlobalJSObject); + + NS_ASSERTION(mPrototypeNoHelper, + "Failed to create prototype for wrappers w/o a helper"); + } + + return mPrototypeNoHelper; +} JS_STATIC_DLL_CALLBACK(JSDHashOperator) WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr, @@ -416,6 +475,11 @@ XPCWrappedNativeScope::FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt) { cur->mPrototypeJSFunction = nsnull; } + if(cur->mPrototypeNoHelper && + JS_IsAboutToBeFinalized(cx, cur->mPrototypeNoHelper)) + { + cur->mPrototypeNoHelper = nsnull; + } } if(cur) prev = cur; @@ -646,11 +710,12 @@ GetScopeOfObject(JSContext* cx, JSObject* obj) { #ifdef DEBUG { - if(clazz->flags & JSCLASS_HAS_PRIVATE && - clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) + if(!(~clazz->flags & (JSCLASS_HAS_PRIVATE | + JSCLASS_PRIVATE_IS_NSISUPPORTS)) && + (supports = (nsISupports*) JS_GetPrivate(cx, obj))) { nsCOMPtr iface = - do_QueryInterface((nsISupports*) JS_GetPrivate(cx, obj)); + do_QueryInterface(supports); NS_ASSERTION(!iface, "Uh, how'd this happen?"); } @@ -870,6 +935,7 @@ XPCWrappedNativeScope::DebugDump(PRInt16 depth) XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject)); XPC_LOG_ALWAYS(("mPrototypeJSObject @ %x", mPrototypeJSObject)); XPC_LOG_ALWAYS(("mPrototypeJSFunction @ %x", mPrototypeJSFunction)); + XPC_LOG_ALWAYS(("mPrototypeNoHelper @ %x", mPrototypeNoHelper)); XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)", \ mWrappedNativeMap, \ diff --git a/js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp b/js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp index 824764d972a1..1912a401bdea 100644 --- a/js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp +++ b/js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp @@ -93,8 +93,8 @@ NS_IMETHODIMP nsXPCToolsCompiler::CompileFile(nsILocalFile *aFile, PRBool strict return NS_ERROR_FAILURE; // get the xpconnect native call context - nsCOMPtr callContext; - xpc->GetCurrentNativeCallContext(getter_AddRefs(callContext)); + nsAXPCNativeCallContext *callContext = nsnull; + xpc->GetCurrentNativeCallContext(&callContext); if(!callContext) return NS_ERROR_FAILURE; diff --git a/layout/base/crashtests/409461-1.xhtml b/layout/base/crashtests/409461-1.xhtml new file mode 100644 index 000000000000..1abb421489cb --- /dev/null +++ b/layout/base/crashtests/409461-1.xhtml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/layout/base/crashtests/411870-1.html b/layout/base/crashtests/411870-1.html new file mode 100644 index 000000000000..7b14952505a2 --- /dev/null +++ b/layout/base/crashtests/411870-1.html @@ -0,0 +1,18 @@ + + + + + +
+ + +
+ + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 4e9cba92bf3e..db2dd1f50d1c 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -89,3 +89,6 @@ load 405184-1.xhtml load 405186-1.xhtml load 408292.html load 408299.html +load 409461-1.xhtml +# load 411870-1.html + diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index d51d4ad74a2b..1649cc70c8ae 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -825,8 +825,10 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, else aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_RIGHT_MOST); } - nsMargin margin; - aFrame->GetMargin(margin); + // This method is called from nsBlockFrame::PlaceLine via the call to + // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines + // have been reflowed, which is required for GetUsedMargin/Border/Padding + nsMargin margin = aFrame->GetUsedMargin(); if (isLeftMost) aLeft += margin.left; @@ -835,8 +837,7 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, if (!IsBidiLeaf(aFrame)) { nscoord x = 0; - nsMargin borderPadding; - aFrame->GetBorderAndPadding(borderPadding); + nsMargin borderPadding = aFrame->GetUsedBorderAndPadding(); if (isLeftMost) { x += borderPadding.left; } @@ -905,12 +906,14 @@ nsBidiPresUtils::InitContinuationStates(nsIFrame* aFrame, void nsBidiPresUtils::RepositionInlineFrames(nsIFrame* aFirstChild) const { - nsMargin margin; const nsStyleVisibility* vis = aFirstChild->GetStyleVisibility(); PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); nscoord leftSpace = 0; - aFirstChild->GetMargin(margin); + // This method is called from nsBlockFrame::PlaceLine via the call to + // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines + // have been reflowed, which is required for GetUsedMargin/Border/Padding + nsMargin margin = aFirstChild->GetUsedMargin(); if (!aFirstChild->GetPrevContinuation()) leftSpace = isLTR ? margin.left : margin.right; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 77eef8001e9d..3b814039a6c2 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -6234,8 +6234,11 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState, aContent->Tag()->ToString(parentTag); badKid->Tag()->ToString(kidTag); const PRUnichar* params[] = { parentTag.get(), kidTag.get() }; + const char *message = + (display->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX) + ? "NeededToWrapXULInlineBox" : "NeededToWrapXUL"; nsContentUtils::ReportToConsole(nsContentUtils::eXUL_PROPERTIES, - "NeededToWrapXUL", + message, params, NS_ARRAY_LENGTH(params), mDocument->GetDocumentURI(), EmptyString(), 0, 0, // not useful @@ -8008,7 +8011,9 @@ nsCSSFrameConstructor::AppendFrames(nsFrameConstructorState& aState, if (IsFrameSpecial(aParentFrame) && !IsInlineFrame(aParentFrame) && IsInlineOutside(aFrameList.lastChild)) { - NS_ASSERTION(!aParentFrame->GetNextContinuation(), "Shouldn't happen"); + NS_ASSERTION(!aParentFrame->GetNextContinuation() || + !aParentFrame->GetNextContinuation()->GetFirstChild(nsnull), + "Shouldn't happen"); // We want to put some of the frames into the following inline frame. nsIFrame* lastBlock = FindLastBlock(aFrameList.childList); @@ -8352,11 +8357,7 @@ nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent, // The frame may have a continuation. If so, we want the last // non-overflow-container continuation as our previous sibling. - sibling = sibling->GetLastContinuation(); - while (sibling->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) { - sibling = sibling->GetPrevInFlow(); - NS_ASSERTION(sibling, "first-in-flow can't be overflow container"); - } + sibling = sibling->GetTailContinuation(); } if (aTargetContent && @@ -8670,8 +8671,8 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, parentFrame = GetLastSpecialSibling(parentFrame); } - // Get the parent frame's last continuation - parentFrame = parentFrame->GetLastContinuation(); + // Get continuation that parents the last child + parentFrame = nsLayoutUtils::GetLastContinuationWithChild(parentFrame); nsIAtom* frameType = parentFrame->GetType(); // Deal with fieldsets @@ -9118,7 +9119,7 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, nsLayoutUtils::IsGeneratedContentFor(aContainer, firstChild, nsCSSPseudoElements::before)) { // Insert the new frames after the last continuation of the :before - prevSibling = firstChild->GetLastContinuation(); + prevSibling = firstChild->GetTailContinuation(); parentFrame = prevSibling->GetParent(); // We perhaps could leave this true and take the AppendFrames path // below, but we'd have to update appendAfterFrame and it seems safer @@ -9776,7 +9777,7 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext, // XXX this needs to detect the need for a view due to an opacity change and deal with it... - viewManager->BeginUpdateViewBatch(); + nsIViewManager::UpdateViewBatch batch(viewManager); #ifdef DEBUG gInApplyRenderingChangeToTree = PR_TRUE; @@ -9787,7 +9788,7 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext, gInApplyRenderingChangeToTree = PR_FALSE; #endif - viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); + batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); } /** @@ -9847,11 +9848,10 @@ InvalidateCanvasIfNeeded(nsIFrame* aFrame) // Wrap this in a DEFERRED view update batch so we don't try to // flush out layout here - nsIViewManager* viewManager = presContext->GetViewManager(); - viewManager->BeginUpdateViewBatch(); + nsIViewManager::UpdateViewBatch batch(presContext->GetViewManager()); ApplyRenderingChangeToTree(presContext, ancestor, nsChangeHint_RepaintFrame); - viewManager->EndUpdateViewBatch(NS_VMREFRESH_DEFERRED); + batch.EndUpdateViewBatch(NS_VMREFRESH_DEFERRED); } } @@ -11172,7 +11172,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForIBSplitterFrame(nsIFrame* aFrame // Not a kid of the third part of the IB split GetSpecialSibling(parent) || !IsInlineOutside(parent) || // Or not the only child - aFrame->GetLastContinuation()->GetNextSibling() || + aFrame->GetTailContinuation()->GetNextSibling() || aFrame != parent->GetFirstContinuation()->GetFirstChild(nsnull) )) { return PR_FALSE; @@ -13273,6 +13273,11 @@ nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint, nsChangeHint aMinChangeHint) { + if (NS_UNLIKELY(mIsDestroyingFrameTree)) { + NS_NOTREACHED("PostRestyleEvent after the shell is destroyed (bug 279505)"); + return; + } + if (aRestyleHint == 0 && !aMinChangeHint) { // Nothing to do here return; diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index f26fed5c9dbe..671537e1c166 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -723,14 +723,16 @@ private: nsIFrame* GetFrameFor(nsIContent* aContent); /** - * These functions are used when we start frame creation from a non-root + * These two functions are used when we start frame creation from a non-root * element. They should recreate the same state that we would have * arrived at if we had built frames from the root frame to aFrame. * Therefore, any calls to PushFloatContainingBlock and * PushAbsoluteContainingBlock during frame construction should get * corresponding logic in these functions. */ +public: nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame); +private: nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame); nsIContent* PropagateScrollToViewport(); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index d047c1792eb6..bb02eaac1bb1 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1505,10 +1505,7 @@ DocumentViewerImpl::Destroy() mPreviousViewer = nsnull; } - if (mDeviceContext) { - mDeviceContext->FlushFontCache(); - mDeviceContext = nsnull; - } + mDeviceContext = nsnull; if (mPresShell) { // Break circular reference (or something) @@ -1917,7 +1914,8 @@ DocumentViewerImpl::Show(void) if (mPresContext) { Hide(); - rv = InitPresentationStuff(PR_TRUE, PR_TRUE); + rv = InitPresentationStuff(mDocument->MayStartLayout(), + mDocument->MayStartLayout()); } // If we get here the document load has already started and the @@ -1958,10 +1956,6 @@ DocumentViewerImpl::Hide(void) return NS_OK; } - if (mDeviceContext) { - mDeviceContext->FlushFontCache(); - } - // Break circular reference (or something) mPresShell->EndObservingDocument(); nsCOMPtr selection; @@ -2670,10 +2664,8 @@ DocumentViewerImpl::SetTextZoom(float aTextZoom) if (!GetIsPrintPreview()) { mTextZoom = aTextZoom; } - nsCOMPtr vm = GetViewManager(); - if (vm) { - vm->BeginUpdateViewBatch(); - } + + nsIViewManager::UpdateViewBatch batch(GetViewManager()); // Set the text zoom on all children of mContainer (even if our zoom didn't // change, our children's zoom may be different, though it would be unusual). @@ -2688,9 +2680,7 @@ DocumentViewerImpl::SetTextZoom(float aTextZoom) pc->SetTextZoom(aTextZoom); } - if (vm) { - vm->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); - } + batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); return NS_OK; } @@ -2711,10 +2701,7 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom) mPageZoom = aFullZoom; } - nsCOMPtr vm = GetViewManager(); - if (vm) { - vm->BeginUpdateViewBatch(); - } + nsIViewManager::UpdateViewBatch batch(GetViewManager()); struct ZoomInfo ZoomInfo = { aFullZoom }; CallChildren(SetChildFullZoom, &ZoomInfo); @@ -2724,9 +2711,7 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom) pc->SetFullZoom(aFullZoom); } - if (vm) { - vm->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); - } + batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); return NS_OK; } @@ -3437,6 +3422,11 @@ DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, } #endif + if (!mContainer) { + PR_PL(("Container was destroyed yet we are still trying to use it!")); + return NS_ERROR_FAILURE; + } + nsCOMPtr docShell(do_QueryReferent(mContainer)); NS_ASSERTION(docShell, "This has to be a docshell"); @@ -3531,6 +3521,11 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, } #endif + if (!mContainer) { + PR_PL(("Container was destroyed yet we are still trying to use it!")); + return NS_ERROR_FAILURE; + } + nsCOMPtr docShell(do_QueryReferent(mContainer)); NS_ASSERTION(docShell, "This has to be a docshell"); nsCOMPtr presShell; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 1771672e5080..54513bb4d981 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -341,7 +341,7 @@ public: * Returns a layout object associated with the primary frame for the content object. * * @param aContent the content object for which we seek a layout object - * @param aResult the resulting layout object as an nsISupports, if found. Refcounted. + * @param aResult the resulting layout object as an nsISupports, if found. */ NS_IMETHOD GetLayoutObjectFor(nsIContent* aContent, nsISupports** aResult) const = 0; @@ -645,6 +645,8 @@ public: */ static PRInt32 GetVerifyReflowFlags(); + virtual nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame); + #ifdef MOZ_REFLOW_PERF NS_IMETHOD DumpReflows() = 0; NS_IMETHOD CountReflows(const char * aName, nsIFrame * aFrame) = 0; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index c229411f28d2..a125b8f581fe 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -80,6 +80,19 @@ * A namespace class for static layout utilities. */ + +nsIFrame* +nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + aFrame = aFrame->GetLastContinuation(); + while (!aFrame->GetFirstChild(nsnull) && + aFrame->GetPrevContinuation()) { + aFrame = aFrame->GetPrevContinuation(); + } + return aFrame; +} + /** * GetFirstChildFrame returns the first "real" child frame of a * given frame. It will descend down into pseudo-frames (unless the @@ -121,11 +134,11 @@ GetLastChildFrame(nsIFrame* aFrame, { NS_PRECONDITION(aFrame, "NULL frame pointer"); - // Get the last continuation frame - nsIFrame* lastContinuation = aFrame->GetLastContinuation(); + // Get the last continuation frame that's a parent + nsIFrame* lastParentContinuation = nsLayoutUtils::GetLastContinuationWithChild(aFrame); // Get the last child frame - nsIFrame* firstChildFrame = lastContinuation->GetFirstChild(nsnull); + nsIFrame* firstChildFrame = lastParentContinuation->GetFirstChild(nsnull); if (firstChildFrame) { nsFrameList frameList(firstChildFrame); nsIFrame* lastChildFrame = frameList.LastChild(); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 82457644febc..15a46ab8a602 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -200,6 +200,12 @@ public: PRInt32 aIf2Ancestor, nsIFrame* aCommonAncestor = nsnull); + /** + * GetLastContinuationWithChild gets the last continuation in aFrame's chain + * that has a child, or the first continuation if the frame has no children. + */ + static nsIFrame* GetLastContinuationWithChild(nsIFrame* aFrame); + /** * GetLastSibling simply finds the last sibling of aFrame, or returns nsnull if * aFrame is null. diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index b9ed7f0b7040..854ec0ee2a3c 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1108,7 +1108,8 @@ protected: nsresult DoFlushPendingNotifications(mozFlushType aType, PRBool aInterruptibleReflow); - nsICSSStyleSheet* mPrefStyleSheet; // mStyleSet owns it but we maintain a ref, may be null + nsCOMPtr mPrefStyleSheet; // mStyleSet owns it but we + // maintain a ref, may be null #ifdef DEBUG PRUint32 mUpdateCount; #endif @@ -1845,7 +1846,7 @@ nsresult PresShell::ClearPreferenceStyleRules(void) printf("PrefStyleSheet removed\n"); #endif // clear the sheet pointer: it is strictly historical now - NS_RELEASE(mPrefStyleSheet); + mPrefStyleSheet = nsnull; } } return result; @@ -1854,7 +1855,8 @@ nsresult PresShell::ClearPreferenceStyleRules(void) nsresult PresShell::CreatePreferenceStyleSheet(void) { NS_ASSERTION(!mPrefStyleSheet, "prefStyleSheet already exists"); - nsresult result = CallCreateInstance(kCSSStyleSheetCID, &mPrefStyleSheet); + nsresult result; + mPrefStyleSheet = do_CreateInstance(kCSSStyleSheetCID, &result); if (NS_SUCCEEDED(result)) { NS_ASSERTION(mPrefStyleSheet, "null but no error"); nsCOMPtr uri; @@ -1864,24 +1866,25 @@ nsresult PresShell::CreatePreferenceStyleSheet(void) result = mPrefStyleSheet->SetURIs(uri, nsnull, uri); if (NS_SUCCEEDED(result)) { mPrefStyleSheet->SetComplete(); - nsCOMPtr sheet(do_QueryInterface(mPrefStyleSheet)); - if (sheet) { - PRUint32 index; - result = sheet->InsertRule(NS_LITERAL_STRING("@namespace url(http://www.w3.org/1999/xhtml);"), - 0, &index); - NS_ENSURE_SUCCESS(result, result); + PRUint32 index; + result = + mPrefStyleSheet->InsertRuleInternal(NS_LITERAL_STRING("@namespace url(http://www.w3.org/1999/xhtml);"), + 0, &index); + if (NS_SUCCEEDED(result)) { + mStyleSet->AppendStyleSheet(nsStyleSet::eUserSheet, mPrefStyleSheet); } - mStyleSet->AppendStyleSheet(nsStyleSet::eUserSheet, mPrefStyleSheet); } } - } else { - result = NS_ERROR_OUT_OF_MEMORY; } #ifdef DEBUG_attinasi printf("CreatePrefStyleSheet completed: error=%ld\n",(long)result); #endif + if (NS_FAILED(result)) { + mPrefStyleSheet = nsnull; + } + return result; } @@ -1908,12 +1911,11 @@ PresShell::SetPrefNoScriptRule() rv = CreatePreferenceStyleSheet(); NS_ENSURE_SUCCESS(rv, rv); } - // get the DOM interface to the stylesheet - nsCOMPtr sheet(do_QueryInterface(mPrefStyleSheet, &rv)); - NS_ENSURE_SUCCESS(rv, rv); + PRUint32 index = 0; - rv = sheet->InsertRule(NS_LITERAL_STRING("noscript{display:none!important}"), - sInsertPrefSheetRulesAt, &index); + mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("noscript{display:none!important}"), + sInsertPrefSheetRulesAt, &index); } return rv; @@ -1935,10 +1937,6 @@ nsresult PresShell::SetPrefNoFramesRule(void) NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null"); - // get the DOM interface to the stylesheet - nsCOMPtr sheet(do_QueryInterface(mPrefStyleSheet, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - PRBool allowSubframes = PR_TRUE; nsCOMPtr container = mPresContext->GetContainer(); nsCOMPtr docShell(do_QueryInterface(container)); @@ -1947,11 +1945,13 @@ nsresult PresShell::SetPrefNoFramesRule(void) } if (!allowSubframes) { PRUint32 index = 0; - rv = sheet->InsertRule(NS_LITERAL_STRING("noframes{display:block}"), - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("noframes{display:block}"), + sInsertPrefSheetRulesAt, &index); NS_ENSURE_SUCCESS(rv, rv); - rv = sheet->InsertRule(NS_LITERAL_STRING("frame, frameset, iframe {display:none!important}"), - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("frame, frameset, iframe {display:none!important}"), + sInsertPrefSheetRulesAt, &index); } return rv; } @@ -1972,10 +1972,6 @@ nsresult PresShell::SetPrefLinkRules(void) NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null"); - // get the DOM interface to the stylesheet - nsCOMPtr sheet(do_QueryInterface(mPrefStyleSheet, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - // support default link colors: // this means the link colors need to be overridable, // which they are if we put them in the agent stylesheet, @@ -1992,23 +1988,26 @@ nsresult PresShell::SetPrefLinkRules(void) // insert a rule to color links: '*|*:link {color: #RRGGBB [!important];}' ColorToString(linkColor, strColor); - rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:link{color:") + - strColor + ruleClose, - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("*|*:link{color:") + + strColor + ruleClose, + sInsertPrefSheetRulesAt, &index); NS_ENSURE_SUCCESS(rv, rv); // - visited links: '*|*:visited {color: #RRGGBB [!important];}' ColorToString(visitedColor, strColor); - rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:visited{color:") + - strColor + ruleClose, - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("*|*:visited{color:") + + strColor + ruleClose, + sInsertPrefSheetRulesAt, &index); NS_ENSURE_SUCCESS(rv, rv); // - active links: '*|*:-moz-any-link:active {color: #RRGGBB [!important];}' ColorToString(activeColor, strColor); - rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:-moz-any-link:active{color:") + - strColor + ruleClose, - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("*|*:-moz-any-link:active{color:") + + strColor + ruleClose, + sInsertPrefSheetRulesAt, &index); NS_ENSURE_SUCCESS(rv, rv); PRBool underlineLinks = @@ -2020,11 +2019,13 @@ nsresult PresShell::SetPrefLinkRules(void) // no need for important, we want these to be overridable // NOTE: these must go in the agent stylesheet or they cannot be // overridden by authors - rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:underline}"), - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:underline}"), + sInsertPrefSheetRulesAt, &index); } else { - rv = sheet->InsertRule(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:none}"), - sInsertPrefSheetRulesAt, &index); + rv = mPrefStyleSheet-> + InsertRuleInternal(NS_LITERAL_STRING("*|*:-moz-any-link{text-decoration:none}"), + sInsertPrefSheetRulesAt, &index); } return rv; @@ -2044,58 +2045,58 @@ nsresult PresShell::SetPrefFocusRules(void) if (NS_SUCCEEDED(result)) { NS_ASSERTION(mPrefStyleSheet, "prefstylesheet should not be null"); - // get the DOM interface to the stylesheet - nsCOMPtr sheet(do_QueryInterface(mPrefStyleSheet,&result)); - if (NS_SUCCEEDED(result)) { - if (mPresContext->GetUseFocusColors()) { - nscolor focusBackground(mPresContext->FocusBackgroundColor()); - nscolor focusText(mPresContext->FocusTextColor()); + if (mPresContext->GetUseFocusColors()) { + nscolor focusBackground(mPresContext->FocusBackgroundColor()); + nscolor focusText(mPresContext->FocusTextColor()); - // insert a rule to make focus the preferred color - PRUint32 index = 0; - nsAutoString strRule, strColor; + // insert a rule to make focus the preferred color + PRUint32 index = 0; + nsAutoString strRule, strColor; - /////////////////////////////////////////////////////////////// - // - focus: '*:focus - ColorToString(focusText,strColor); - strRule.AppendLiteral("*:focus,*:focus>font {color: "); - strRule.Append(strColor); - strRule.AppendLiteral(" !important; background-color: "); - ColorToString(focusBackground,strColor); - strRule.Append(strColor); - strRule.AppendLiteral(" !important; } "); - // insert the rules - result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index); - } - PRUint8 focusRingWidth = mPresContext->FocusRingWidth(); - PRBool focusRingOnAnything = mPresContext->GetFocusRingOnAnything(); + /////////////////////////////////////////////////////////////// + // - focus: '*:focus + ColorToString(focusText,strColor); + strRule.AppendLiteral("*:focus,*:focus>font {color: "); + strRule.Append(strColor); + strRule.AppendLiteral(" !important; background-color: "); + ColorToString(focusBackground,strColor); + strRule.Append(strColor); + strRule.AppendLiteral(" !important; } "); + // insert the rules + result = mPrefStyleSheet-> + InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index); + } + PRUint8 focusRingWidth = mPresContext->FocusRingWidth(); + PRBool focusRingOnAnything = mPresContext->GetFocusRingOnAnything(); - if ((NS_SUCCEEDED(result) && focusRingWidth != 1 && focusRingWidth <= 4 ) || focusRingOnAnything) { - PRUint32 index = 0; - nsAutoString strRule; - if (!focusRingOnAnything) - strRule.AppendLiteral("*|*:link:focus, *|*:visited"); // If we only want focus rings on the normal things like links - strRule.AppendLiteral(":focus {outline: "); // For example 3px dotted WindowText (maximum 4) + if ((NS_SUCCEEDED(result) && focusRingWidth != 1 && focusRingWidth <= 4 ) || focusRingOnAnything) { + PRUint32 index = 0; + nsAutoString strRule; + if (!focusRingOnAnything) + strRule.AppendLiteral("*|*:link:focus, *|*:visited"); // If we only want focus rings on the normal things like links + strRule.AppendLiteral(":focus {outline: "); // For example 3px dotted WindowText (maximum 4) + strRule.AppendInt(focusRingWidth); + strRule.AppendLiteral("px dotted WindowText !important; } "); // For example 3px dotted WindowText + // insert the rules + result = mPrefStyleSheet-> + InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index); + NS_ENSURE_SUCCESS(result, result); + if (focusRingWidth != 1) { + // If the focus ring width is different from the default, fix buttons with rings + strRule.AssignLiteral("button::-moz-focus-inner, input[type=\"reset\"]::-moz-focus-inner,"); + strRule.AppendLiteral("input[type=\"button\"]::-moz-focus-inner, "); + strRule.AppendLiteral("input[type=\"submit\"]::-moz-focus-inner { padding: 1px 2px 1px 2px; border: "); strRule.AppendInt(focusRingWidth); - strRule.AppendLiteral("px dotted WindowText !important; } "); // For example 3px dotted WindowText - // insert the rules - result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index); + strRule.AppendLiteral("px dotted transparent !important; } "); + result = mPrefStyleSheet-> + InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index); NS_ENSURE_SUCCESS(result, result); - if (focusRingWidth != 1) { - // If the focus ring width is different from the default, fix buttons with rings - strRule.AssignLiteral("button::-moz-focus-inner, input[type=\"reset\"]::-moz-focus-inner,"); - strRule.AppendLiteral("input[type=\"button\"]::-moz-focus-inner, "); - strRule.AppendLiteral("input[type=\"submit\"]::-moz-focus-inner { padding: 1px 2px 1px 2px; border: "); - strRule.AppendInt(focusRingWidth); - strRule.AppendLiteral("px dotted transparent !important; } "); - result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index); - NS_ENSURE_SUCCESS(result, result); - strRule.AssignLiteral("button:focus::-moz-focus-inner, input[type=\"reset\"]:focus::-moz-focus-inner,"); - strRule.AppendLiteral("input[type=\"button\"]:focus::-moz-focus-inner, input[type=\"submit\"]:focus::-moz-focus-inner {"); - strRule.AppendLiteral("border-color: ButtonText !important; }"); - result = sheet->InsertRule(strRule, sInsertPrefSheetRulesAt, &index); - } + strRule.AssignLiteral("button:focus::-moz-focus-inner, input[type=\"reset\"]:focus::-moz-focus-inner,"); + strRule.AppendLiteral("input[type=\"button\"]:focus::-moz-focus-inner, input[type=\"submit\"]:focus::-moz-focus-inner {"); + strRule.AppendLiteral("border-color: ButtonText !important; }"); + result = mPrefStyleSheet-> + InsertRuleInternal(strRule, sInsertPrefSheetRulesAt, &index); } } } @@ -2501,8 +2502,8 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) return NS_OK; NS_ASSERTION(mViewManager, "Must have view manager"); - nsCOMPtr viewManager = mViewManager; - viewManager->BeginUpdateViewBatch(); + nsCOMPtr viewManagerDeathGrip = mViewManager; + nsIViewManager::UpdateViewBatch batch(mViewManager); // Take this ref after viewManager so it'll make sure to go away first nsCOMPtr kungFuDeathGrip(this); @@ -2530,7 +2531,7 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) DidDoReflow(); } - viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); + batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); if (!mIsDestroying) { CreateResizeEventTimer(); @@ -3339,7 +3340,7 @@ PresShell::RecreateFramesFor(nsIContent* aContent) // to keep the number of entrypoints down. NS_ASSERTION(mViewManager, "Should have view manager"); - mViewManager->BeginUpdateViewBatch(); + nsIViewManager::UpdateViewBatch batch(mViewManager); // Have to make sure that the content notifications are flushed before we // start messing with the frame model; otherwise we can get content doubling. @@ -3353,7 +3354,7 @@ PresShell::RecreateFramesFor(nsIContent* aContent) nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList); --mChangeNestCount; - mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); + batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); #ifdef ACCESSIBILITY InvalidateAccessibleSubtree(aContent); #endif @@ -4455,10 +4456,8 @@ PresShell::DoFlushPendingNotifications(mozFlushType aType, NS_ASSERTION(!isSafeToFlush || mViewManager, "Must have view manager"); // Make sure the view manager stays alive while batching view updates. - // XXX FIXME: If viewmanager hierarchy is modified while we're in update - // batch... We need to address that somehow. See bug 369165. - nsCOMPtr viewManager = mViewManager; - if (isSafeToFlush && viewManager) { + nsCOMPtr viewManagerDeathGrip = mViewManager; + if (isSafeToFlush && mViewManager) { // Processing pending notifications can kill us, and some callers only // hold weak refs when calling FlushPendingNotifications(). :( nsCOMPtr kungFuDeathGrip(this); @@ -4466,7 +4465,7 @@ PresShell::DoFlushPendingNotifications(mozFlushType aType, // Style reresolves not in conjunction with reflows can't cause // painting or geometry changes, so don't bother with view update // batching if we only have style reresolve - viewManager->BeginUpdateViewBatch(); + nsIViewManager::UpdateViewBatch batch(mViewManager); // Force flushing of any pending content notifications that might have // queued up while our event was pending. That will ensure that we don't @@ -4518,7 +4517,7 @@ PresShell::DoFlushPendingNotifications(mozFlushType aType, // at the end of this view batch. updateFlags = NS_VMREFRESH_DEFERRED; } - viewManager->EndUpdateViewBatch(updateFlags); + batch.EndUpdateViewBatch(updateFlags); } return NS_OK; @@ -6419,7 +6418,7 @@ PresShell::Observe(nsISupports* aSubject, // at interesting times during startup. if (rootFrame) { NS_ASSERTION(mViewManager, "View manager must exist"); - mViewManager->BeginUpdateViewBatch(); + nsIViewManager::UpdateViewBatch batch(mViewManager); WalkFramesThroughPlaceholders(mPresContext, rootFrame, &ReResolveMenusAndTrees, nsnull); @@ -6435,7 +6434,7 @@ PresShell::Observe(nsISupports* aSubject, mFrameConstructor->ProcessRestyledFrames(changeList); --mChangeNestCount; - mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); + batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); #ifdef ACCESSIBILITY InvalidateAccessibleSubtree(nsnull); #endif @@ -7661,3 +7660,8 @@ void ColorToString(nscolor aColor, nsAutoString &aString) NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor)); CopyASCIItoUTF16(buf, aString); } + +nsIFrame* nsIPresShell::GetAbsoluteContainingBlock(nsIFrame *aFrame) +{ + return FrameConstructor()->GetAbsoluteContainingBlock(aFrame); +} diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index cda21116ab2d..9cf311fab60c 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -324,6 +324,7 @@ #define NS_STYLE_CURSOR_NWSE_RESIZE 33 #define NS_STYLE_CURSOR_NS_RESIZE 34 #define NS_STYLE_CURSOR_EW_RESIZE 35 +#define NS_STYLE_CURSOR_NONE 36 // See nsStyleDisplay #define NS_STYLE_DIRECTION_LTR 0 diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index f0a49745fc49..43ac1df73493 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -288,6 +288,7 @@ nsLayoutStatics::Shutdown() nsAttrValue::Shutdown(); nsContentUtils::Shutdown(); + nsNodeInfo::ClearCache(); nsLayoutStylesheetCache::Shutdown(); NS_NameSpaceManagerShutdown(); nsStyleSet::FreeGlobals(); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 848127c26297..d6fb83b45f55 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1348,7 +1348,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, // Don't carry out a bottom margin when our height is fixed. aMetrics.mCarriedOutBottomMargin.Zero(); } - else { + else if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) { nscoord autoHeight = aState.mY + nonCarriedOutVerticalMargin; // Shrink wrap our height around our contents. @@ -1383,6 +1383,11 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, autoHeight += borderPadding.top + borderPadding.bottom; aMetrics.height = autoHeight; } + else { + NS_ASSERTION(aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE, + "Shouldn't be incomplete if availableHeight is UNCONSTRAINED."); + aMetrics.height = PR_MAX(aState.mY, aReflowState.availableHeight); + } if (IS_TRUE_OVERFLOW_CONTAINER(this) && NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) { diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index 8f30364e6913..906357302292 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -203,7 +203,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame, aResult.y = mY; aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT) ? NS_UNCONSTRAINEDSIZE - : PR_MAX(0, mBottomEdge - mY); + : PR_MAX(0, mReflowState.availableHeight - mY); // mY might be greater than mBottomEdge if the block's top margin pushes // it off the page/column. Negative available height can confuse other code // and is nonsense in principle. diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 4cd51240fa99..814603ef7427 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -3291,6 +3291,22 @@ NS_IMETHODIMP nsFrame::SetNextInFlow(nsIFrame*) return NS_ERROR_NOT_IMPLEMENTED; } +nsIFrame* nsIFrame::GetTailContinuation() +{ + nsIFrame* frame = this; + while (frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) { + frame = frame->GetPrevContinuation(); + NS_ASSERTION(frame, "first continuation can't be overflow container"); + } + for (nsIFrame* next = frame->GetNextContinuation(); + next && !(next->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER); + next = frame->GetNextContinuation()) { + frame = next; + } + NS_POSTCONDITION(frame, "illegal state in continuation chain."); + return frame; +} + nsIView* nsIFrame::GetParentViewForChildFrame(nsIFrame* aFrame) const { diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 28a5bbd40097..ef54dcb68070 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -304,7 +304,7 @@ public: * override ComputeSize to enforce their width/height invariants. * * Implementations may optimize by returning a garbage width if - * GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto, and + * GetStylePosition()->mWidth.GetUnit() != eStyleUnit_Auto, and * likewise for height, since in such cases the result is guaranteed * to be unused. */ diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index cc6df7f1cfc6..3c010c19c7e6 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -486,8 +486,8 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext, if (IsInline()) { // XUL + + + + + + diff --git a/layout/reftests/bugs/412679-1.html b/layout/reftests/bugs/412679-1.html new file mode 100644 index 000000000000..eb0892321a76 --- /dev/null +++ b/layout/reftests/bugs/412679-1.html @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + diff --git a/layout/reftests/bugs/412679-2-ref.html b/layout/reftests/bugs/412679-2-ref.html new file mode 100644 index 000000000000..f054f6992f71 --- /dev/null +++ b/layout/reftests/bugs/412679-2-ref.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + diff --git a/layout/reftests/bugs/412679-2.html b/layout/reftests/bugs/412679-2.html new file mode 100644 index 000000000000..655bba9b9cd2 --- /dev/null +++ b/layout/reftests/bugs/412679-2.html @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + diff --git a/layout/reftests/bugs/413292-1-ref.html b/layout/reftests/bugs/413292-1-ref.html new file mode 100644 index 000000000000..65d7f3315a97 --- /dev/null +++ b/layout/reftests/bugs/413292-1-ref.html @@ -0,0 +1,6 @@ + + + + Done + + diff --git a/layout/reftests/bugs/413292-1.html b/layout/reftests/bugs/413292-1.html new file mode 100644 index 000000000000..9486175d4f47 --- /dev/null +++ b/layout/reftests/bugs/413292-1.html @@ -0,0 +1,43 @@ + + + + + + + + +
+ diff --git a/layout/reftests/bugs/413361-1-ref.html b/layout/reftests/bugs/413361-1-ref.html new file mode 100644 index 000000000000..463d45f2a8a4 --- /dev/null +++ b/layout/reftests/bugs/413361-1-ref.html @@ -0,0 +1,13 @@ + + +testcase + + + + + + diff --git a/layout/reftests/bugs/413361-1.html b/layout/reftests/bugs/413361-1.html new file mode 100644 index 000000000000..a38daa53da84 --- /dev/null +++ b/layout/reftests/bugs/413361-1.html @@ -0,0 +1,15 @@ + + +testcase + + + + + + diff --git a/layout/reftests/bugs/414123-ref.xhtml b/layout/reftests/bugs/414123-ref.xhtml new file mode 100644 index 000000000000..edfbf1c91903 --- /dev/null +++ b/layout/reftests/bugs/414123-ref.xhtml @@ -0,0 +1,34 @@ + + + + + + Testcase for bug 414123 + + + + + + M + 2 + + + + + + M + 2 + + + + + + M + 2 + + + + + + diff --git a/layout/reftests/bugs/414123.xhtml b/layout/reftests/bugs/414123.xhtml new file mode 100644 index 000000000000..f41d4a716151 --- /dev/null +++ b/layout/reftests/bugs/414123.xhtml @@ -0,0 +1,42 @@ + + + + + Testcase for bug 414123 + + + + + + + + 2 + + + + + + M + 2 + + + + + + + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 6ef143947c36..e449fd293d19 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -103,6 +103,25 @@ fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 28811-2a.html 28811-2-ref.html # bug 38 == 214077-1a.html 214077-1-ref.html == 214077-1b.html 214077-1-ref.html == 218473-1.html 218473-1-ref.html +== 234686-1.html 234686-ref.html +== 234686-2.html 234686-ref.html +== 234686-3.html 234686-ref.html +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-4.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-5.html 234686-ref.html # bug 371316 or other image scaling issue +== 234686-6.html 234686-ref.html +== 234686-7.html 234686-ref.html +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-8.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-9.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-10.html 234686-ref.html # bug 371316 or other image scaling issue +== 234686-11.html 234686-ref.html +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-12.html 234686-ref.html # bug 371316 or other image scaling issue +== 234686-13.html 234686-ref.html +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-14.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-15.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-16.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-17.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-18.html 234686-ref.html # bug 371316 or other image scaling issue +fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 234686-19.html 234686-ref.html # bug 371316 or other image scaling issue == 234964-1.html 234964-1-ref.html == 234964-2.html 234964-2-ref.html == 235593-1.html 235593-1-ref.html @@ -123,6 +142,7 @@ fails-if(MOZ_WIDGET_TOOLKIT!="cocoa") HTTP == 289480.html#top 289480-ref.html # == 290129-1.html 290129-1-ref.html == 291078-1.html 291078-1-ref.html == 291078-2.html 291078-2-ref.html +== 291262-1.html 291262-1-ref.html == 296904-1.html 296904-1-ref.html == 300691-1a.html 300691-1-ref.html == 300691-1b.html 300691-1-ref.html @@ -372,7 +392,7 @@ fails == 352980-1h.html 352980-1-ref.html == 367612-1e.html 367612-1-ref.html == 367612-1f.html 367612-1-ref.html != 367612-1g.html 367612-1-ref.html -fails == 368020-1.html 368020-1-ref.html # bug 368079 +== 368020-1.html 368020-1-ref.html random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 368020-2.html 368020-2-ref.html # bug 368157 (gtk) fails == 368020-3.html 368020-3-ref.html # bug 368085 fails == 368020-4.html 368020-4-ref.html # bug 368085 @@ -383,12 +403,13 @@ random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 368020-5.html 368020-5-ref.html # bug 3 # is too exact # == 368247-1.html 368247-1-ref.html == 368247-2.html 368247-2-ref.html -fails == 368504-1.html 368504-1-ref.html -fails == 368504-2.html 368504-2-ref.html -fails == 368504-3a.html 368504-3-ref.html -fails == 368504-3b.html 368504-3-ref.html -fails == 368504-4.html 368504-4-ref.html -fails == 368504-5.html 368504-5-ref.html +== 368504-1.html 368504-1-ref.html +== 368504-2.html 368504-2-ref.html +== 368504-3a.html 368504-3-ref.html +== 368504-3b.html 368504-3-ref.html +== 368504-4.html 368504-4-ref.html +== 368504-5.html 368504-5-ref.html +== 368504-6.html 368504-6-ref.html == 368622-1.html 368622-1-ref.html == 368622-1.html 368622-1-ref.html == 368651-1.html 368651-1-ref.html @@ -539,6 +560,8 @@ skip-if(MOZ_WIDGET_TOOLKIT!="windows") == 391045.html 391045-ref.html # windows- == 393671-1.html 393671-1-ref.html == 393671-2.html 393671-2-ref.html == 393671-3.html 393671-3-ref.html +== 393760-1.xml 393760-1-ref.xml +== 393760-2.xml 393760-2-ref.xml == 394111-1.html about:blank # Really an assertion test rather than a rendering test == 394534-1.html 394534-1-ref.html == 394676-1.xhtml 394676-1-ref.xhtml @@ -639,4 +662,10 @@ random == 403134-1.html 403134-1-ref.html # bug 405377 != 409659-1b.html 409659-1-ref.html != 409659-1c.html 409659-1-ref.html == 409659-1d.html 409659-1-ref.html +== 412679-1.html 412679-1-ref.html +== 412679-2.html 412679-2-ref.html == 411334-1.xml 411334-1-ref.xml +== 411792-1.html 411792-1-ref.html +== 413292-1.html 413292-1-ref.html +== 413361-1.html 413361-1-ref.html +== 414123.xhtml 414123-ref.xhtml diff --git a/layout/reftests/pagination/content-inserted-000.ref.xhtml b/layout/reftests/pagination/content-inserted-000.ref.xhtml new file mode 100644 index 000000000000..7bef4dfef1ec --- /dev/null +++ b/layout/reftests/pagination/content-inserted-000.ref.xhtml @@ -0,0 +1,40 @@ + + + + Content Appended in {ib} Pagination with Overflow Containers + + + + + + +
This must be in the last column, below the orange line. +
This must be in the first column, below the blue line.
+ + + + diff --git a/layout/reftests/pagination/content-inserted-000.xhtml b/layout/reftests/pagination/content-inserted-000.xhtml new file mode 100644 index 000000000000..d266a775fd2c --- /dev/null +++ b/layout/reftests/pagination/content-inserted-000.xhtml @@ -0,0 +1,40 @@ + + + + Content Appended in {ib} Pagination with Overflow Containers + + + + + + +
This must be in the last column, below the orange line. +
+ + + + diff --git a/layout/reftests/pagination/content-inserted-001.ref.xhtml b/layout/reftests/pagination/content-inserted-001.ref.xhtml new file mode 100644 index 000000000000..078ca74b7cb5 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-001.ref.xhtml @@ -0,0 +1,29 @@ + + + + Content Appended in Paginated Element + + + + + + +
+
This must be in the first column.
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-001.xhtml b/layout/reftests/pagination/content-inserted-001.xhtml new file mode 100644 index 000000000000..2fdbb4a62ab0 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-001.xhtml @@ -0,0 +1,29 @@ + + + + Content Appended in Paginated Element + + + + + + +
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-002.ref.xhtml b/layout/reftests/pagination/content-inserted-002.ref.xhtml new file mode 100644 index 000000000000..37bded68a1b4 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-002.ref.xhtml @@ -0,0 +1,37 @@ + + + + Content Appended in Pagination + + + + + + +
+
+
+
This must be in the second column between two 4px blue lines.
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-002.xhtml b/layout/reftests/pagination/content-inserted-002.xhtml new file mode 100644 index 000000000000..26ece6d1f198 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-002.xhtml @@ -0,0 +1,42 @@ + + + + Content Appended in Pagination before ::after + + + + + + +
+
+
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-003.xhtml b/layout/reftests/pagination/content-inserted-003.xhtml new file mode 100644 index 000000000000..636a67971a06 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-003.xhtml @@ -0,0 +1,43 @@ + + + + Content Appended in Pagination before ::after (alternate) + + + + + + +
+
+
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-004.xhtml b/layout/reftests/pagination/content-inserted-004.xhtml new file mode 100644 index 000000000000..aaf797a30e9f --- /dev/null +++ b/layout/reftests/pagination/content-inserted-004.xhtml @@ -0,0 +1,41 @@ + + + + Content Inserted in Pagination after ::before + + + + + + +
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-005.xhtml b/layout/reftests/pagination/content-inserted-005.xhtml new file mode 100644 index 000000000000..de0c6532e349 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-005.xhtml @@ -0,0 +1,37 @@ + + + + Content Appended in Pagination after ::before + + + + + + +
+
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-006.xhtml b/layout/reftests/pagination/content-inserted-006.xhtml new file mode 100644 index 000000000000..834e69746804 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-006.xhtml @@ -0,0 +1,49 @@ + + + + Content Appended in Pagination before ::after (alternate) + + + + + + +
+
+
+
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-007.xhtml b/layout/reftests/pagination/content-inserted-007.xhtml new file mode 100644 index 000000000000..c6ee648251a6 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-007.xhtml @@ -0,0 +1,48 @@ + + + + Content Inserted in Pagination after ::before + + + + + + +
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-008.xhtml b/layout/reftests/pagination/content-inserted-008.xhtml new file mode 100644 index 000000000000..854e5faa3f69 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-008.xhtml @@ -0,0 +1,36 @@ + + + + Content Appended in Pagination before ::after + + + + + + +
+
+
+
+
+
+ + + + diff --git a/layout/reftests/pagination/content-inserted-009.xhtml b/layout/reftests/pagination/content-inserted-009.xhtml new file mode 100644 index 000000000000..cc343bb01184 --- /dev/null +++ b/layout/reftests/pagination/content-inserted-009.xhtml @@ -0,0 +1,44 @@ + + + + Content Appended in Pagination before ::after + + + + + + +
+ +
+
+
This must be in the second column between two 4px blue lines.
+ + + + diff --git a/layout/reftests/pagination/reftest.list b/layout/reftests/pagination/reftest.list index cb8ebe9f058a..f26a584c9431 100644 --- a/layout/reftests/pagination/reftest.list +++ b/layout/reftests/pagination/reftest.list @@ -5,3 +5,18 @@ == abspos-overflow-01.xhtml abspos-overflow-01.ref.xhtml == abspos-overflow-01-cols.xhtml abspos-overflow-01-cols.ref.xhtml == dynamic-abspos-overflow-01-cols.xhtml dynamic-abspos-overflow-01-cols.ref.xhtml +== border-breaking-000-cols.xhtml border-breaking-000-cols.ref.xhtml +== border-breaking-001-cols.xhtml border-breaking-001-cols.ref.xhtml +== border-breaking-002-cols.xhtml border-breaking-002-cols.ref.xhtml +== border-breaking-003-cols.xhtml border-breaking-003-cols.ref.xhtml +== border-breaking-004-cols.xhtml border-breaking-002-cols.ref.xhtml +== content-inserted-000.xhtml content-inserted-000.ref.xhtml +== content-inserted-001.xhtml content-inserted-001.ref.xhtml +== content-inserted-002.xhtml content-inserted-002.ref.xhtml +== content-inserted-003.xhtml content-inserted-002.ref.xhtml +== content-inserted-004.xhtml content-inserted-002.ref.xhtml +== content-inserted-005.xhtml content-inserted-002.ref.xhtml +== content-inserted-006.xhtml content-inserted-002.ref.xhtml +== content-inserted-007.xhtml content-inserted-002.ref.xhtml +== content-inserted-008.xhtml content-inserted-001.ref.xhtml +== content-inserted-009.xhtml content-inserted-002.ref.xhtml diff --git a/layout/reftests/printing/403669-1-ref.html b/layout/reftests/printing/403669-1-ref.html new file mode 100644 index 000000000000..5d14e048a082 --- /dev/null +++ b/layout/reftests/printing/403669-1-ref.html @@ -0,0 +1,12 @@ + + + + +
+ a a a a a a a a a a a a a a + a a a a a a a a a a a a a a +
+ Ending Text + + diff --git a/layout/reftests/printing/403669-1.html b/layout/reftests/printing/403669-1.html new file mode 100644 index 000000000000..8958ef982747 --- /dev/null +++ b/layout/reftests/printing/403669-1.html @@ -0,0 +1,13 @@ + + + + +
+ a a a a a a a a a a a a a a + a a a a a a a a a a a a a a +
+ Ending Text + + diff --git a/layout/reftests/printing/reftest.list b/layout/reftests/printing/reftest.list index 3ef8637ffd34..5d4d61039307 100644 --- a/layout/reftests/printing/reftest.list +++ b/layout/reftests/printing/reftest.list @@ -3,3 +3,4 @@ # Bugs == 272830-1.html 272830-1-ref.html +== 403669-1.html 403669-1-ref.html diff --git a/layout/style/crashtests/386939-1.html b/layout/style/crashtests/386939-1.html new file mode 100644 index 000000000000..679d2b27e00e --- /dev/null +++ b/layout/style/crashtests/386939-1.html @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/layout/style/crashtests/404470-1.html b/layout/style/crashtests/404470-1.html new file mode 100644 index 000000000000..481ba4233b01 --- /dev/null +++ b/layout/style/crashtests/404470-1.html @@ -0,0 +1,15 @@ + + + + + + + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index 4a83b823aaa6..b7aec11808f8 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -4,7 +4,9 @@ load 330998-1.html load 379788-1.html load 383979-1.xhtml load 383979-2.html +load 386939-1.html load 391034-1.xhtml load 397022-1.html load 399289-1.svg +load 404470-1.html load 411603-1.html diff --git a/layout/style/forms.css b/layout/style/forms.css index 6a487e85bc09..6f6344f7ddab 100644 --- a/layout/style/forms.css +++ b/layout/style/forms.css @@ -251,8 +251,8 @@ select > option { } option:checked { - background-color: -moz-cellhighlight !important; - color: -moz-cellhighlighttext !important; + background-color: -moz-html-cellhighlight !important; + color: -moz-html-cellhighlighttext !important; } select:focus > option:checked, @@ -488,12 +488,22 @@ button { display: block; } +button:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +input[type="submit"]:hover { + background-color: -moz-buttonhoverface; + color: -moz-buttonhovertext; +} + button:active:hover, input[type="reset"]:active:hover, input[type="button"]:active:hover, input[type="submit"]:active:hover { padding: 0px 5px 0px 7px; border-style: inset; + background-color: ButtonFace; + color: ButtonText; } button::-moz-focus-inner, diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 6de292d41401..82b314978190 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -116,6 +116,8 @@ CSS_KEY(-moz-hangul-consonant, _moz_hangul_consonant) CSS_KEY(-moz-hidden-unscrollable, _moz_hidden_unscrollable) CSS_KEY(-moz-hangul, _moz_hangul) CSS_KEY(-moz-hyperlinktext, _moz_hyperlinktext) +CSS_KEY(-moz-html-cellhighlight, _moz_html_cellhighlight) +CSS_KEY(-moz-html-cellhighlighttext, _moz_html_cellhighlighttext) CSS_KEY(-moz-info, _moz_info) CSS_KEY(-moz-initial, _moz_initial) CSS_KEY(-moz-inline-box, _moz_inline_box) diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 6ccfe331ead4..869bca123513 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -435,6 +435,8 @@ const PRInt32 nsCSSProps::kColorKTable[] = { eCSSKeyword__moz_dialogtext, nsILookAndFeel::eColor__moz_dialogtext, eCSSKeyword__moz_dragtargetzone, nsILookAndFeel::eColor__moz_dragtargetzone, eCSSKeyword__moz_hyperlinktext, NS_COLOR_MOZ_HYPERLINKTEXT, + eCSSKeyword__moz_html_cellhighlight, nsILookAndFeel::eColor__moz_html_cellhighlight, + eCSSKeyword__moz_html_cellhighlighttext, nsILookAndFeel::eColor__moz_html_cellhighlighttext, eCSSKeyword__moz_mac_focusring, nsILookAndFeel::eColor__moz_mac_focusring, eCSSKeyword__moz_mac_menuselect, nsILookAndFeel::eColor__moz_mac_menuselect, eCSSKeyword__moz_mac_menushadow, nsILookAndFeel::eColor__moz_mac_menushadow, @@ -500,6 +502,7 @@ const PRInt32 nsCSSProps::kCursorKTable[] = { eCSSKeyword_nwse_resize, NS_STYLE_CURSOR_NWSE_RESIZE, eCSSKeyword_ns_resize, NS_STYLE_CURSOR_NS_RESIZE, eCSSKeyword_ew_resize, NS_STYLE_CURSOR_EW_RESIZE, + eCSSKeyword_none, NS_STYLE_CURSOR_NONE, // -moz- prefixed aliases for some CSS3 cursors for backward compat eCSSKeyword__moz_copy, NS_STYLE_CURSOR_COPY, eCSSKeyword__moz_alias, NS_STYLE_CURSOR_ALIAS, diff --git a/layout/style/nsCSSScanner.cpp b/layout/style/nsCSSScanner.cpp index 81e2f339233b..8cd5674bf69d 100644 --- a/layout/style/nsCSSScanner.cpp +++ b/layout/style/nsCSSScanner.cpp @@ -317,9 +317,10 @@ void nsCSSScanner::OutputError() if (mError.IsEmpty()) return; #ifdef DEBUG - fprintf(stderr, "CSS Error (%s :%u.%u): %s\n", - mFileName.get(), mErrorLineNumber, mErrorColNumber, - NS_ConvertUTF16toUTF8(mError).get()); + if (gReportErrors) + fprintf(stderr, "CSS Error (%s :%u.%u): %s\n", + mFileName.get(), mErrorLineNumber, mErrorColNumber, + NS_ConvertUTF16toUTF8(mError).get()); #endif // Log it to the Error console diff --git a/layout/style/nsCSSStyleSheet.cpp b/layout/style/nsCSSStyleSheet.cpp index 2dc36f89d5a5..60444f78b641 100644 --- a/layout/style/nsCSSStyleSheet.cpp +++ b/layout/style/nsCSSStyleSheet.cpp @@ -522,6 +522,7 @@ nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy, nsICSSStyleSheet* aParentSheet) : mSheets(), mSheetURI(aCopy.mSheetURI), + mOriginalSheetURI(aCopy.mOriginalSheetURI), mBaseURI(aCopy.mBaseURI), mPrincipal(aCopy.mPrincipal), mComplete(aCopy.mComplete) @@ -1334,7 +1335,7 @@ nsCSSStyleSheet::SubjectSubsumesInnerPrincipal() const securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)); if (!subjectPrincipal) { - return NS_OK; + return NS_ERROR_DOM_SECURITY_ERR; } PRBool subsumes; @@ -1506,6 +1507,19 @@ NS_IMETHODIMP nsCSSStyleSheet::InsertRule(const nsAString& aRule, PRUint32 aIndex, PRUint32* aReturn) +{ + //-- Security check: Only scripts whose principal subsumes that of the + // style sheet can modify rule collections. + nsresult rv = SubjectSubsumesInnerPrincipal(); + NS_ENSURE_SUCCESS(rv, rv); + + return InsertRuleInternal(aRule, aIndex, aReturn); +} + +NS_IMETHODIMP +nsCSSStyleSheet::InsertRuleInternal(const nsAString& aRule, + PRUint32 aIndex, + PRUint32* aReturn) { // No doing this if the sheet is not complete! PRBool complete; @@ -1514,11 +1528,6 @@ nsCSSStyleSheet::InsertRule(const nsAString& aRule, return NS_ERROR_DOM_INVALID_ACCESS_ERR; } - //-- Security check: Only scripts whose principal subsumes that of the - // style sheet can modify rule collections. - nsresult rv = SubjectSubsumesInnerPrincipal(); - NS_ENSURE_SUCCESS(rv, rv); - if (aRule.IsEmpty()) { // Nothing to do here return NS_OK; diff --git a/layout/style/nsCSSStyleSheet.h b/layout/style/nsCSSStyleSheet.h index 9b72f99a6ccb..e9b30bab5a93 100644 --- a/layout/style/nsCSSStyleSheet.h +++ b/layout/style/nsCSSStyleSheet.h @@ -156,6 +156,8 @@ public: NS_IMETHOD SetModified(PRBool aModified); NS_IMETHOD AddRuleProcessor(nsCSSRuleProcessor* aProcessor); NS_IMETHOD DropRuleProcessor(nsCSSRuleProcessor* aProcessor); + NS_IMETHOD InsertRuleInternal(const nsAString& aRule, + PRUint32 aIndex, PRUint32* aReturn); // nsICSSLoaderObserver interface NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet* aSheet, PRBool aWasAlternate, diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 5fca84b3e6a6..c306281a75af 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -2861,16 +2861,11 @@ nsComputedDOMStyle::GetBorderWidthFor(PRUint8 aSide, nsIDOMCSSValue** aValue) NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY); nscoord width; - const nsStyleDisplay *disp = GetStyleDisplay(); - if (mFrame && mFrame->IsThemed(disp)) { - nsMargin result; - nsPresContext *presContext = mFrame->PresContext(); - presContext->GetTheme()->GetWidgetBorder(presContext->DeviceContext(), - mFrame, disp->mAppearance, - &result); - width = presContext->DevPixelsToAppUnits(result.side(aSide)); + if (mFrame) { + FlushPendingReflows(); + width = mFrame->GetUsedBorder().side(aSide); } else { - width = GetStyleBorder()->GetComputedBorderWidth(aSide); + width = GetStyleBorder()->GetBorderWidth(aSide); } val->SetAppUnits(width); diff --git a/layout/style/nsICSSStyleSheet.h b/layout/style/nsICSSStyleSheet.h index c38b8367a868..529608bbd23c 100644 --- a/layout/style/nsICSSStyleSheet.h +++ b/layout/style/nsICSSStyleSheet.h @@ -53,10 +53,10 @@ class nsICSSImportRule; class nsIPrincipal; // IID for the nsICSSStyleSheet interface -// 74fa10f3-fab7-425a-a7dd-e2afd1ba7a07 +// 363c1c5f-81ec-4d83-ad8a-b48d48f1398d #define NS_ICSS_STYLE_SHEET_IID \ -{ 0x74fa10f3, 0xfab7, 0x425a, \ - { 0xa7, 0xdd, 0xe2, 0xaf, 0xd1, 0xba, 0x7a, 0x07 } } +{ 0x363c1c5f, 0x81ec, 0x4d83, \ + { 0xad, 0x8a, 0xb4, 0x8d, 0x48, 0xf1, 0x39, 0x8d } } class nsICSSStyleSheet : public nsIStyleSheet { public: @@ -121,6 +121,12 @@ public: NS_IMETHOD AddRuleProcessor(nsCSSRuleProcessor* aProcessor) = 0; NS_IMETHOD DropRuleProcessor(nsCSSRuleProcessor* aProcessor) = 0; + + /** + * Like the DOM insertRule() method, but doesn't do any security checks + */ + NS_IMETHOD InsertRuleInternal(const nsAString& aRule, + PRUint32 aIndex, PRUint32* aReturn) = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSStyleSheet, NS_ICSS_STYLE_SHEET_IID) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 5c18741f1903..e2c335ce2ed5 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1969,12 +1969,15 @@ ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont, double scriptLevelScale = pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange); - // Compute the size we would have had if minscriptsize had never been applied + // Compute the size we would have had if minscriptsize had never been + // applied, also prevent overflow (bug 413274) *aUnconstrainedSize = - NSToCoordRound(aParentFont->mScriptUnconstrainedSize*scriptLevelScale); + NSToCoordRound(PR_MIN(aParentFont->mScriptUnconstrainedSize*scriptLevelScale, + nscoord_MAX)); // Compute the size we could get via scriptlevel change nscoord scriptLevelSize = - NSToCoordRound(aParentFont->mSize*scriptLevelScale); + NSToCoordRound(PR_MIN(aParentFont->mSize*scriptLevelScale, + nscoord_MAX)); if (scriptLevelScale <= 1.0) { if (aParentFont->mSize <= minScriptSize) { // We can't decrease the font size at all, so just stick to no change diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index e1df53f43f83..47edcfa14f2a 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -389,15 +389,6 @@ struct nsStyleBorder { return mActualBorder.side(aSide); } - // Get the computed border width for a particular side, in twips. Note that - // this is zero if and only if there is no border to be painted for this - // side. That is, this value takes into account the border style and the - // value is rounded to the nearest device pixel by NS_ROUND_BORDER_TO_PIXELS. - nscoord GetComputedBorderWidth(PRUint8 aSide) const - { - return mActualBorder.side(aSide) ? mBorder.side(aSide) : 0; - } - PRUint8 GetBorderStyle(PRUint8 aSide) const { NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side"); diff --git a/layout/style/test/Makefile.in b/layout/style/test/Makefile.in index 69cb05eb6791..5209ea8d0052 100644 --- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -84,6 +84,8 @@ _TEST_FILES = test_bug74880.html \ test_bug391034.html \ test_bug391221.html \ test_bug397427.html \ + test_bug405818.html \ + test_bug412901.html \ test_compute_data_with_start_struct.html \ test_dont_use_document_colors.html \ test_inherit_storage.html \ diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index a93bf886a3d1..3e81eccf9ca7 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -836,7 +836,7 @@ var gCSSProperties = { inherited: true, type: CSS_TYPE_LONGHAND, initial_values: [ "auto" ], - other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress" ], + other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "none" ], invalid_values: [] }, "direction": { diff --git a/layout/style/test/test_bug405818.html b/layout/style/test/test_bug405818.html new file mode 100644 index 000000000000..a313242769a5 --- /dev/null +++ b/layout/style/test/test_bug405818.html @@ -0,0 +1,72 @@ + + + + + Test for Bug 405818 + + + + + + + + + + + +Mozilla Bug 405818 +

+ +
+
+
+ + + diff --git a/layout/style/test/test_bug412901.html b/layout/style/test/test_bug412901.html new file mode 100644 index 000000000000..f28f3b4745f5 --- /dev/null +++ b/layout/style/test/test_bug412901.html @@ -0,0 +1,43 @@ + + + + + Test for Bug 412901 + + + + + +Mozilla Bug 412901 +
+
+

+
+ +
+
+
+ + diff --git a/layout/svg/base/src/nsISVGChildFrame.h b/layout/svg/base/src/nsISVGChildFrame.h index 090bf8623ccc..f9b6b0e42fef 100644 --- a/layout/svg/base/src/nsISVGChildFrame.h +++ b/layout/svg/base/src/nsISVGChildFrame.h @@ -51,8 +51,8 @@ class nsSVGRenderState; struct nsRect; #define NS_ISVGCHILDFRAME_IID \ -{ 0x93560e72, 0x6818, 0x4218, \ - { 0xa1, 0xe9, 0xf3, 0xb9, 0x63, 0x6a, 0xff, 0xc2 } } +{ 0x667e8781, 0x72bd, 0x4344, \ + { 0x95, 0x8c, 0x69, 0xa5, 0x70, 0xc4, 0xcc, 0xb3 } } class nsISVGChildFrame : public nsISupports { public: @@ -84,7 +84,19 @@ public: // into the frame tree (if they're inserted after the initial reflow). NS_IMETHOD InitialUpdate()=0; - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation)=0; + // Flags to pass to NotifySVGChange: + // + // SUPPRESS_INVALIDATION - do not invalidate rendered areas (only to be + // used in conjunction with TRANSFORM_CHANGED) + // TRANSFORM_CHANGED - the current transform matrix for this frame has changed + // COORD_CONTEXT_CHANGED - the dimensions of this frame's coordinate context has + // changed (percentage lengths must be reevaluated) + enum SVGChangedFlags { + SUPPRESS_INVALIDATION = 0x01, + TRANSFORM_CHANGED = 0x02, + COORD_CONTEXT_CHANGED = 0x04 + }; + virtual void NotifySVGChanged(PRUint32 aFlags)=0; NS_IMETHOD NotifyRedrawSuspended()=0; NS_IMETHOD NotifyRedrawUnsuspended()=0; diff --git a/layout/svg/base/src/nsSVGAFrame.cpp b/layout/svg/base/src/nsSVGAFrame.cpp index 6608aa53ebbe..ef9c9f307323 100755 --- a/layout/svg/base/src/nsSVGAFrame.cpp +++ b/layout/svg/base/src/nsSVGAFrame.cpp @@ -81,7 +81,7 @@ public: } #endif // nsISVGChildFrame interface: - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); // nsSVGContainerFrame methods: virtual already_AddRefed GetCanvasTM(); @@ -123,14 +123,7 @@ nsSVGAFrame::AttributeChanged(PRInt32 aNameSpaceID, // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; - nsIFrame* kid = mFrames.FirstChild(); - while (kid) { - nsISVGChildFrame* SVGFrame = nsnull; - CallQueryInterface(kid, &SVGFrame); - if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(PR_FALSE); - kid = kid->GetNextSibling(); - } + nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); } return NS_OK; @@ -153,13 +146,15 @@ nsSVGAFrame::GetType() const //---------------------------------------------------------------------- // nsISVGChildFrame methods -NS_IMETHODIMP -nsSVGAFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGAFrame::NotifySVGChanged(PRUint32 aFlags) { - // make sure our cached transform matrix gets (lazily) updated - mCanvasTM = nsnull; + if (aFlags & TRANSFORM_CHANGED) { + // make sure our cached transform matrix gets (lazily) updated + mCanvasTM = nsnull; + } - return nsSVGAFrameBase::NotifyCanvasTMChanged(suppressInvalidation); + nsSVGAFrameBase::NotifySVGChanged(aFlags); } //---------------------------------------------------------------------- diff --git a/layout/svg/base/src/nsSVGClipPathFrame.cpp b/layout/svg/base/src/nsSVGClipPathFrame.cpp index 261f73289a1a..461a339a4538 100644 --- a/layout/svg/base/src/nsSVGClipPathFrame.cpp +++ b/layout/svg/base/src/nsSVGClipPathFrame.cpp @@ -100,7 +100,9 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext, nsISVGChildFrame* SVGFrame = nsnull; CallQueryInterface(kid, &SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(PR_TRUE); + // The CTM of each frame referencing us can be different. + SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); SVGFrame->PaintSVG(aContext, nsnull); } } @@ -139,7 +141,7 @@ nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent, // Notify the child frame that we may be working with a // different transform, so it can update its covered region // (used to shortcut hit testing). - SVGFrame->NotifyCanvasTMChanged(PR_FALSE); + SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED); nsIFrame *temp = nsnull; nsresult rv = SVGFrame->GetFrameForPointSVG(aX, aY, &temp); diff --git a/layout/svg/base/src/nsSVGContainerFrame.cpp b/layout/svg/base/src/nsSVGContainerFrame.cpp index d3a6974636e8..07dc6704a938 100644 --- a/layout/svg/base/src/nsSVGContainerFrame.cpp +++ b/layout/svg/base/src/nsSVGContainerFrame.cpp @@ -241,15 +241,17 @@ nsSVGDisplayContainerFrame::InitialUpdate() return NS_OK; } -NS_IMETHODIMP -nsSVGDisplayContainerFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGDisplayContainerFrame::NotifySVGChanged(PRUint32 aFlags) { - if (!suppressInvalidation && + NS_ASSERTION(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + + if (!(aFlags & SUPPRESS_INVALIDATION) && !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) nsSVGUtils::UpdateFilterRegion(this); - nsSVGUtils::NotifyChildrenCanvasTMChanged(this, suppressInvalidation); - return NS_OK; + nsSVGUtils::NotifyChildrenOfSVGChange(this, aFlags); } NS_IMETHODIMP diff --git a/layout/svg/base/src/nsSVGContainerFrame.h b/layout/svg/base/src/nsSVGContainerFrame.h index 61397297850a..a8f33f41d415 100644 --- a/layout/svg/base/src/nsSVGContainerFrame.h +++ b/layout/svg/base/src/nsSVGContainerFrame.h @@ -107,7 +107,7 @@ public: NS_IMETHOD_(nsRect) GetCoveredRegion(); NS_IMETHOD UpdateCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_ERROR_FAILURE; } diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp index 2f0a6174367a..b01845ca3652 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.cpp +++ b/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -79,7 +79,8 @@ nsSVGFilterFrame::FilterFailCleanup(nsSVGRenderState *aContext, { aTarget->SetOverrideCTM(nsnull); aTarget->SetMatrixPropagation(PR_TRUE); - aTarget->NotifyCanvasTMChanged(PR_TRUE); + aTarget->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); aTarget->PaintSVG(aContext, nsnull); } @@ -121,7 +122,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, nsSVGElement *target = static_cast(frame->GetContent()); aTarget->SetMatrixPropagation(PR_FALSE); - aTarget->NotifyCanvasTMChanged(PR_TRUE); + aTarget->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); nsSVGFilterElement *filter = static_cast(mContent); @@ -192,7 +194,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, 0.0f, filterRes.height / height, -x * filterRes.width / width, -y * filterRes.height / height); aTarget->SetOverrideCTM(filterTransform); - aTarget->NotifyCanvasTMChanged(PR_TRUE); + aTarget->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); // paint the target geometry nsRefPtr tmpSurface = @@ -289,7 +292,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, aTarget->SetOverrideCTM(nsnull); aTarget->SetMatrixPropagation(PR_TRUE); - aTarget->NotifyCanvasTMChanged(PR_TRUE); + aTarget->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); return NS_OK; } @@ -314,12 +318,14 @@ nsSVGFilterFrame::GetInvalidationRegion(nsIFrame *aTarget) nsCOMPtr bbox; svg->SetMatrixPropagation(PR_FALSE); - svg->NotifyCanvasTMChanged(PR_TRUE); + svg->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); svg->GetBBox(getter_AddRefs(bbox)); svg->SetMatrixPropagation(PR_TRUE); - svg->NotifyCanvasTMChanged(PR_TRUE); + svg->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); nsSVGLength2 *tmpX, *tmpY, *tmpWidth, *tmpHeight; tmpX = &filter->mLengthAttributes[nsSVGFilterElement::X]; diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index cf91068dfec2..294646b39b63 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -380,40 +380,46 @@ nsSVGForeignObjectFrame::InitialUpdate() return NS_OK; } -NS_IMETHODIMP -nsSVGForeignObjectFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGForeignObjectFrame::NotifySVGChanged(PRUint32 aFlags) { - mCanvasTM = nsnull; + PRBool reflow = PR_FALSE; - // XXX we should really have a separate notification for viewport changes and - // not overload NotifyCanvasTMChanged, e.g. we wouldn't need to check - // IsReflowLocked below. Note both notifications would be required for - // viewport changes when there's a viewBox though! - // - // If our width/height have a percentage value then we need to reflow if the - // width/height of our parent coordinate context changes. XXX Perhaps - // unexpectedly we also reflow if our CTM changes. This is because glyph - // metrics do not necessarily scale uniformly with change in scale and, as a - // result, CTM changes may require text to break at different points. roc - // says we shouldn't do this. See bug 381285 comment 20. + if (aFlags & TRANSFORM_CHANGED) { + // Perhaps unexpectedly, we reflow if our CTM changes. This is because + // glyph metrics do not necessarily scale uniformly with change in scale + // and, as a result, CTM changes may require text to break at different + // points. + // XXX roc says we shouldn't do this. See bug 381285 comment 20. + reflow = PR_TRUE; + mCanvasTM = nsnull; - UpdateGraphic(); // update mRect before requesting reflow - - // If we're called while the PresShell is handling reflow events then we - // must have been called as a result of the NotifyViewportChange() call in - // our nsSVGOuterSVGFrame's Reflow() method. We must not call RequestReflow - // at this point (i.e. during reflow) because it could confuse the PresShell - // and prevent it from reflowing us properly in future. Besides that, - // nsSVGOuterSVGFrame::DidReflow will take care of reflowing us - // synchronously, so there's no need. - - PRBool reflowing; - PresContext()->PresShell()->IsReflowLocked(&reflowing); - if (!reflowing) { - RequestReflow(nsIPresShell::eResize); // XXX use mState & NS_FRAME_IN_REFLOW? + } else if (aFlags & COORD_CONTEXT_CHANGED) { + // Our coordinate context's width/height has changed. If we have a + // percentage width/height our dimensions will change so we must reflow. + nsSVGForeignObjectElement *fO = + static_cast(mContent); + if (fO->mLengthAttributes[nsSVGForeignObjectElement::WIDTH].IsPercentage() || + fO->mLengthAttributes[nsSVGForeignObjectElement::HEIGHT].IsPercentage()) { + reflow = PR_TRUE; + } } - return NS_OK; + if (reflow) { + // If we're called while the PresShell is handling reflow events then we + // must have been called as a result of the NotifyViewportChange() call in + // our nsSVGOuterSVGFrame's Reflow() method. We must not call RequestReflow + // at this point (i.e. during reflow) because it could confuse the + // PresShell and prevent it from reflowing us properly in future. Besides + // that, nsSVGOuterSVGFrame::DidReflow will take care of reflowing us + // synchronously, so there's no need. + PRBool reflowing; + PresContext()->PresShell()->IsReflowLocked(&reflowing); + if (!reflowing) { + UpdateGraphic(); // update mRect before requesting reflow + RequestReflow(nsIPresShell::eResize); + } + } } NS_IMETHODIMP diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.h b/layout/svg/base/src/nsSVGForeignObjectFrame.h index 49fef8defcd2..73d467538222 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.h +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.h @@ -112,7 +112,7 @@ public: NS_IMETHOD_(nsRect) GetCoveredRegion(); NS_IMETHOD UpdateCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate); diff --git a/layout/svg/base/src/nsSVGGFrame.cpp b/layout/svg/base/src/nsSVGGFrame.cpp index 3566a504610e..a8530052ff18 100644 --- a/layout/svg/base/src/nsSVGGFrame.cpp +++ b/layout/svg/base/src/nsSVGGFrame.cpp @@ -69,13 +69,15 @@ nsSVGGFrame::GetType() const //---------------------------------------------------------------------- // nsISVGChildFrame methods -NS_IMETHODIMP -nsSVGGFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGGFrame::NotifySVGChanged(PRUint32 aFlags) { - // make sure our cached transform matrix gets (lazily) updated - mCanvasTM = nsnull; + if (aFlags & TRANSFORM_CHANGED) { + // make sure our cached transform matrix gets (lazily) updated + mCanvasTM = nsnull; + } - return nsSVGGFrameBase::NotifyCanvasTMChanged(suppressInvalidation); + nsSVGGFrameBase::NotifySVGChanged(aFlags); } NS_IMETHODIMP @@ -155,13 +157,7 @@ nsSVGGFrame::AttributeChanged(PRInt32 aNameSpaceID, // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; - for (nsIFrame* kid = mFrames.FirstChild(); kid; - kid = kid->GetNextSibling()) { - nsISVGChildFrame* SVGFrame = nsnull; - CallQueryInterface(kid, &SVGFrame); - if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(PR_FALSE); - } + nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); } return NS_OK; diff --git a/layout/svg/base/src/nsSVGGFrame.h b/layout/svg/base/src/nsSVGGFrame.h index 1b95bc611005..f15b36c5e8c0 100644 --- a/layout/svg/base/src/nsSVGGFrame.h +++ b/layout/svg/base/src/nsSVGGFrame.h @@ -73,7 +73,7 @@ public: PRInt32 aModType); // nsISVGChildFrame interface: - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate); NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM); virtual already_AddRefed GetOverrideCTM(); diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index 22151fa19a5d..e8a5d1dd10ac 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -450,7 +450,7 @@ nsSVGGlyphFrame::UpdateCoveredRegion() extent = gfx->UserToDevice(extent); } else { gfx->IdentityMatrix(); - extent = gfx->GetUserFillExtent(); + extent = gfx->GetUserPathExtent(); } mRect = nsSVGUtils::ToBoundingPixelRect(extent); @@ -475,12 +475,10 @@ nsSVGGlyphFrame::InitialUpdate() return NS_OK; } -NS_IMETHODIMP -nsSVGGlyphFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGGlyphFrame::NotifySVGChanged(PRUint32 aFlags) { - UpdateGeometry(PR_TRUE, suppressInvalidation); - - return NS_OK; + UpdateGeometry(PR_TRUE, (aFlags & SUPPRESS_INVALIDATION) != 0); } NS_IMETHODIMP @@ -522,7 +520,7 @@ nsSVGGlyphFrame::GetBBox(nsIDOMSVGRect **_retval) LoopCharacters(gfx, text, cp, STROKE); gfx->IdentityMatrix(); - gfxRect rect = gfx->GetUserFillExtent(); + gfxRect rect = gfx->GetUserPathExtent(); return NS_NewSVGRect(_retval, rect); } @@ -891,7 +889,7 @@ nsSVGGlyphFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval) gfx->IdentityMatrix(); - gfxRect rect = gfx->GetUserFillExtent(); + gfxRect rect = gfx->GetUserPathExtent(); gfx->SetMatrix(matrix); diff --git a/layout/svg/base/src/nsSVGGlyphFrame.h b/layout/svg/base/src/nsSVGGlyphFrame.h index c01249e3347d..48d259177334 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.h +++ b/layout/svg/base/src/nsSVGGlyphFrame.h @@ -112,7 +112,7 @@ public: NS_IMETHOD_(nsRect) GetCoveredRegion(); NS_IMETHOD UpdateCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate) { return NS_OK; } diff --git a/layout/svg/base/src/nsSVGGradientFrame.cpp b/layout/svg/base/src/nsSVGGradientFrame.cpp index ffa445944245..79517c318a25 100644 --- a/layout/svg/base/src/nsSVGGradientFrame.cpp +++ b/layout/svg/base/src/nsSVGGradientFrame.cpp @@ -272,11 +272,13 @@ nsSVGGradientFrame::GetGradientTransform(nsSVGGeometryFrame *aSource) nsCOMPtr matrix = frame->GetOverrideCTM(); frame->SetMatrixPropagation(PR_FALSE); frame->SetOverrideCTM(nsnull); - frame->NotifyCanvasTMChanged(PR_TRUE); + frame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); frame->GetBBox(getter_AddRefs(rect)); frame->SetMatrixPropagation(PR_TRUE); frame->SetOverrideCTM(matrix); - frame->NotifyCanvasTMChanged(PR_TRUE); + frame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); } if (rect) { float x, y, width, height; diff --git a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp index a30f0bc4dca5..6a38a78477ba 100644 --- a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp @@ -87,7 +87,7 @@ public: // nsISVGChildFrame interface: NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect); - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate); NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM); virtual already_AddRefed GetOverrideCTM(); @@ -158,46 +158,77 @@ nsSVGInnerSVGFrame::GetType() const NS_IMETHODIMP nsSVGInnerSVGFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect) { - nsresult rv = NS_OK; - - gfxContext *gfx = aContext->GetGfxContext(); - - gfx->Save(); + gfxContextAutoSaveRestore autoSR; if (GetStyleDisplay()->IsScrollableOverflow()) { + float x, y, width, height; + static_cast(mContent)-> + GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); + + if (width <= 0 || height <= 0) { + return NS_OK; + } + nsCOMPtr clipTransform; if (!mPropagateTransform) { NS_NewSVGMatrix(getter_AddRefs(clipTransform)); } else { - nsSVGContainerFrame *parent = static_cast - (mParent); - clipTransform = parent->GetCanvasTM(); + clipTransform = static_cast(mParent)->GetCanvasTM(); } if (clipTransform) { - nsSVGSVGElement *svg = static_cast(mContent); - - float x, y, width, height; - svg->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); - + gfxContext *gfx = aContext->GetGfxContext(); + autoSR.SetContext(gfx); nsSVGUtils::SetClipRect(gfx, clipTransform, x, y, width, height); } } - rv = nsSVGInnerSVGFrameBase::PaintSVG(aContext, aDirtyRect); - - gfx->Restore(); - - return rv; + return nsSVGInnerSVGFrameBase::PaintSVG(aContext, aDirtyRect); } -NS_IMETHODIMP -nsSVGInnerSVGFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGInnerSVGFrame::NotifySVGChanged(PRUint32 aFlags) { - // make sure our cached transform matrix gets (lazily) updated - mCanvasTM = nsnull; + if (aFlags & COORD_CONTEXT_CHANGED) { - return nsSVGInnerSVGFrameBase::NotifyCanvasTMChanged(suppressInvalidation); + nsSVGSVGElement *svg = static_cast(mContent); + + // Coordinate context changes affect mCanvasTM if we have a + // percentage 'x' or 'y', or if we have a percentage 'width' or 'height' AND + // a 'viewBox'. + + if (!(aFlags & TRANSFORM_CHANGED) && + svg->mLengthAttributes[nsSVGSVGElement::X].IsPercentage() || + svg->mLengthAttributes[nsSVGSVGElement::Y].IsPercentage() || + (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox) && + (svg->mLengthAttributes[nsSVGSVGElement::WIDTH].IsPercentage() || + svg->mLengthAttributes[nsSVGSVGElement::HEIGHT].IsPercentage()))) { + + aFlags |= TRANSFORM_CHANGED; + } + + // XXX We could clear the COORD_CONTEXT_CHANGED flag in some circumstances + // if we have a non-percentage 'width' AND 'height, or if we have a 'viewBox' + // rect. This is because, when we have a viewBox rect, the viewBox rect + // is the coordinate context for our children, and it isn't changing. + // Percentage lengths on our children will continue to resolve to the + // same number of user units because they're relative to our viewBox rect. The + // same is true if we have a non-percentage width and height and don't have a + // viewBox. We (the ) establish the coordinate context for our children. Our + // children don't care about changes to our parent coordinate context unless that + // change results in a change to the coordinate context that _we_ establish. Hence + // we can (should, really) stop propagating COORD_CONTEXT_CHANGED in these cases. + // We'd actually need to check that we have a viewBox rect and not just + // that viewBox is set, since it could be set to none. + // Take care not to break the testcase for bug 394463 when implementing this + } + + if (aFlags & TRANSFORM_CHANGED) { + // make sure our cached transform matrix gets (lazily) updated + mCanvasTM = nsnull; + } + + nsSVGInnerSVGFrameBase::NotifySVGChanged(aFlags); } NS_IMETHODIMP @@ -275,19 +306,30 @@ nsSVGInnerSVGFrame::UnsuspendRedraw() NS_IMETHODIMP nsSVGInnerSVGFrame::NotifyViewportChange() { + PRUint32 flags = COORD_CONTEXT_CHANGED; + +#if 1 + // XXX nsSVGSVGElement::InvalidateTransformNotifyFrame calls us for changes + // to 'x' and 'y'. Until this is fixed, add TRANSFORM_CHANGED to flags + // unconditionally. + + flags |= TRANSFORM_CHANGED; + // make sure canvas transform matrix gets (lazily) recalculated: mCanvasTM = nsnull; +#else + // viewport changes only affect our transform if we have a viewBox attribute + if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) { + // make sure canvas transform matrix gets (lazily) recalculated: + mCanvasTM = nsnull; + + flags |= TRANSFORM_CHANGED; + } +#endif // inform children SuspendRedraw(); - nsIFrame* kid = mFrames.FirstChild(); - while (kid) { - nsISVGChildFrame* SVGFrame = nsnull; - CallQueryInterface(kid, &SVGFrame); - if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(PR_FALSE); - kid = kid->GetNextSibling(); - } + nsSVGUtils::NotifyChildrenOfSVGChange(this, flags); UnsuspendRedraw(); return NS_OK; } diff --git a/layout/svg/base/src/nsSVGMarkerFrame.cpp b/layout/svg/base/src/nsSVGMarkerFrame.cpp index 1ad476ddb88e..2e17434e6ee1 100644 --- a/layout/svg/base/src/nsSVGMarkerFrame.cpp +++ b/layout/svg/base/src/nsSVGMarkerFrame.cpp @@ -171,7 +171,9 @@ nsSVGMarkerFrame::PaintMark(nsSVGRenderState *aContext, nsISVGChildFrame* SVGFrame = nsnull; CallQueryInterface(kid, &SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(PR_TRUE); + // The CTM of each frame referencing us may be different. + SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); nsSVGUtils::PaintChildWithEffects(aContext, nsnull, kid); } } diff --git a/layout/svg/base/src/nsSVGMaskFrame.cpp b/layout/svg/base/src/nsSVGMaskFrame.cpp index 1b46bffe3524..d1f594396ce7 100644 --- a/layout/svg/base/src/nsSVGMaskFrame.cpp +++ b/layout/svg/base/src/nsSVGMaskFrame.cpp @@ -112,13 +112,15 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext, if (units == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { aParent->SetMatrixPropagation(PR_FALSE); - aParent->NotifyCanvasTMChanged(PR_TRUE); + aParent->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); nsCOMPtr bbox; aParent->GetBBox(getter_AddRefs(bbox)); aParent->SetMatrixPropagation(PR_TRUE); - aParent->NotifyCanvasTMChanged(PR_TRUE); + aParent->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); if (!bbox) return nsnull; diff --git a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp index af5b748af3ec..5f116415122e 100644 --- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp @@ -227,10 +227,15 @@ nsSVGOuterSVGFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext) nsSVGSVGElement *svg = static_cast(mContent); nsSVGLength2 &width = svg->mLengthAttributes[nsSVGSVGElement::WIDTH]; - if (width.GetSpecifiedUnitType() == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { - result = nscoord(0); + if (width.IsPercentage()) { + // If we're being called then our containing block's width depends on our + // width - fall back to 300px as required by CSS 2.1 section 10.3.2: + result = nsPresContext::CSSPixelsToAppUnits(300); } else { result = nsPresContext::CSSPixelsToAppUnits(width.GetAnimValue(svg)); + if (result < 0) { + result = nscoord(0); + } } return result; @@ -248,7 +253,7 @@ nsSVGOuterSVGFrame::GetIntrinsicSize() nsSVGLength2 &width = content->mLengthAttributes[nsSVGSVGElement::WIDTH]; nsSVGLength2 &height = content->mLengthAttributes[nsSVGSVGElement::HEIGHT]; - if (width.GetSpecifiedUnitType() == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { + if (width.IsPercentage()) { float val = width.GetAnimValInSpecifiedUnits() / 100.0f; if (val < 0.0f) val = 0.0f; intrinsicSize.width.SetPercentValue(val); @@ -258,7 +263,7 @@ nsSVGOuterSVGFrame::GetIntrinsicSize() intrinsicSize.width.SetCoordValue(val); } - if (height.GetSpecifiedUnitType() == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { + if (height.IsPercentage()) { float val = height.GetAnimValInSpecifiedUnits() / 100.0f; if (val < 0.0f) val = 0.0f; intrinsicSize.height.SetPercentValue(val); @@ -282,9 +287,15 @@ nsSVGOuterSVGFrame::GetIntrinsicRatio() nsSVGLength2 &width = content->mLengthAttributes[nsSVGSVGElement::WIDTH]; nsSVGLength2 &height = content->mLengthAttributes[nsSVGSVGElement::HEIGHT]; - if (width.GetSpecifiedUnitType() != nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE && - height.GetSpecifiedUnitType() != nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { - return nsSize(width.GetAnimValue(content), height.GetAnimValue(content)); + if (!width.IsPercentage() && !height.IsPercentage()) { + nsSize ratio(width.GetAnimValue(content), height.GetAnimValue(content)); + if (ratio.width < 0) { + ratio.width = 0; + } + if (ratio.height < 0) { + ratio.height = 0; + } + return ratio; } if (content->HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) { @@ -708,22 +719,28 @@ NS_IMETHODIMP nsSVGOuterSVGFrame::NotifyViewportChange() { // no point in doing anything when were not init'ed yet: - if (!mViewportInitialized) return NS_OK; - -/* XXX this caused reftest failures - // viewport changes only affect our transform if we have a viewBox attribute - nsSVGSVGElement *svgElem = static_cast(mContent); - if (!svgElem->HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) { + if (!mViewportInitialized) { return NS_OK; } -*/ - // make sure canvas transform matrix gets (lazily) recalculated: - mCanvasTM = nsnull; - + PRUint32 flags = COORD_CONTEXT_CHANGED; + + // viewport changes only affect our transform if we have a viewBox attribute +#if 1 + { +#else + // XXX this caused reftest failures (bug 413960) + if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) { +#endif + // make sure canvas transform matrix gets (lazily) recalculated: + mCanvasTM = nsnull; + + flags |= TRANSFORM_CHANGED; + } + // inform children SuspendRedraw(); - nsSVGUtils::NotifyChildrenCanvasTMChanged(this, PR_FALSE); + nsSVGUtils::NotifyChildrenOfSVGChange(this, flags); UnsuspendRedraw(); return NS_OK; } diff --git a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index e20a4b890129..ea7064700c5b 100644 --- a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -440,7 +440,7 @@ nsSVGPathGeometryFrame::UpdateCoveredRegion() } } else { context.IdentityMatrix(); - extent = context.GetUserFillExtent(); + extent = context.GetUserPathExtent(); if (!IsDegeneratePath(extent)) { mRect = nsSVGUtils::ToBoundingPixelRect(extent); } @@ -470,12 +470,10 @@ nsSVGPathGeometryFrame::InitialUpdate() return NS_OK; } -NS_IMETHODIMP -nsSVGPathGeometryFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGPathGeometryFrame::NotifySVGChanged(PRUint32 aFlags) { - UpdateGraphic(suppressInvalidation); - - return NS_OK; + UpdateGraphic((aFlags & SUPPRESS_INVALIDATION) != 0); } NS_IMETHODIMP @@ -524,14 +522,7 @@ nsSVGPathGeometryFrame::GetBBox(nsIDOMSVGRect **_retval) GeneratePath(&context); context.IdentityMatrix(); - gfxRect extent = context.GetUserFillExtent(); - - if (IsDegeneratePath(extent)) { - context.SetLineWidth(0); - extent = context.GetUserStrokeExtent(); - } - - return NS_NewSVGRect(_retval, extent); + return NS_NewSVGRect(_retval, context.GetUserPathExtent()); } //---------------------------------------------------------------------- diff --git a/layout/svg/base/src/nsSVGPathGeometryFrame.h b/layout/svg/base/src/nsSVGPathGeometryFrame.h index e421c5b1fec4..bb1a99859dd8 100644 --- a/layout/svg/base/src/nsSVGPathGeometryFrame.h +++ b/layout/svg/base/src/nsSVGPathGeometryFrame.h @@ -109,7 +109,7 @@ protected: NS_IMETHOD_(nsRect) GetCoveredRegion(); NS_IMETHOD UpdateCoveredRegion(); NS_IMETHOD InitialUpdate(); - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); NS_IMETHOD SetMatrixPropagation(PRBool aPropagate); diff --git a/layout/svg/base/src/nsSVGPatternFrame.cpp b/layout/svg/base/src/nsSVGPatternFrame.cpp index 18db92a29b8d..d9607b41782a 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.cpp +++ b/layout/svg/base/src/nsSVGPatternFrame.cpp @@ -781,10 +781,12 @@ nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM, CallQueryInterface(aSource, &callerSVGFrame); callerSVGFrame->SetMatrixPropagation(PR_FALSE); - callerSVGFrame->NotifyCanvasTMChanged(PR_TRUE); + callerSVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED ); callerSVGFrame->GetBBox(aBBox); callerSVGFrame->SetMatrixPropagation(PR_TRUE); - callerSVGFrame->NotifyCanvasTMChanged(PR_TRUE); + callerSVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | + nsISVGChildFrame::TRANSFORM_CHANGED); // Sanity check PRUint16 type = GetPatternUnits(); diff --git a/layout/svg/base/src/nsSVGTextFrame.cpp b/layout/svg/base/src/nsSVGTextFrame.cpp index eb3e48b5cd94..935a6bc5c3a8 100644 --- a/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/layout/svg/base/src/nsSVGTextFrame.cpp @@ -95,15 +95,9 @@ nsSVGTextFrame::AttributeChanged(PRInt32 aNameSpaceID, // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; - - nsIFrame* kid = mFrames.FirstChild(); - while (kid) { - nsISVGChildFrame* SVGFrame = nsnull; - CallQueryInterface(kid, &SVGFrame); - if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(PR_FALSE); - kid = kid->GetNextSibling(); - } + + nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); + } else if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y || aAttribute == nsGkAtoms::dx || @@ -198,19 +192,25 @@ nsSVGTextFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval) //---------------------------------------------------------------------- // nsISVGChildFrame methods -NS_IMETHODIMP -nsSVGTextFrame::NotifyCanvasTMChanged(PRBool suppressInvalidation) +void +nsSVGTextFrame::NotifySVGChanged(PRUint32 aFlags) { - // make sure our cached transform matrix gets (lazily) updated - mCanvasTM = nsnull; + if (aFlags & TRANSFORM_CHANGED) { + // make sure our cached transform matrix gets (lazily) updated + mCanvasTM = nsnull; + } - // If we are positioned using percentage values we need to update our - // position whenever our viewport's dimensions change. - // XXX we should really have a separate notification for viewport changes and - // not overload NotifyCanvasTMChanged. - NotifyGlyphMetricsChange(); + if (aFlags & COORD_CONTEXT_CHANGED) { + // If we are positioned using percentage values we need to update our + // position whenever our viewport's dimensions change. - return nsSVGTextFrameBase::NotifyCanvasTMChanged(suppressInvalidation); + // XXX We could check here whether the text frame or any of its children + // have any percentage co-ordinates and only update if they don't. This + // may not be worth it as we might need to check each glyph + NotifyGlyphMetricsChange(); + } + + nsSVGTextFrameBase::NotifySVGChanged(aFlags); } NS_IMETHODIMP diff --git a/layout/svg/base/src/nsSVGTextFrame.h b/layout/svg/base/src/nsSVGTextFrame.h index 3d98d06098c0..8ab3a438660e 100755 --- a/layout/svg/base/src/nsSVGTextFrame.h +++ b/layout/svg/base/src/nsSVGTextFrame.h @@ -81,7 +81,7 @@ public: NS_IMETHOD SetMatrixPropagation(PRBool aPropagate); NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM); virtual already_AddRefed GetOverrideCTM(); - NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation); + virtual void NotifySVGChanged(PRUint32 aFlags); NS_IMETHOD NotifyRedrawSuspended(); NS_IMETHOD NotifyRedrawUnsuspended(); NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval); diff --git a/layout/svg/base/src/nsSVGTextPathFrame.cpp b/layout/svg/base/src/nsSVGTextPathFrame.cpp index 8ef5d5fe9ef1..00cd7027169f 100644 --- a/layout/svg/base/src/nsSVGTextPathFrame.cpp +++ b/layout/svg/base/src/nsSVGTextPathFrame.cpp @@ -202,8 +202,7 @@ nsSVGTextPathFrame::GetStartOffset() if (val == 0.0f) return 0.0; - if (length->GetSpecifiedUnitType() == - nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { + if (length->IsPercentage()) { nsRefPtr data = GetFlattenedPath(); return data ? (val * data->GetLength() / 100.0) : 0.0; } else { diff --git a/layout/svg/base/src/nsSVGUseFrame.cpp b/layout/svg/base/src/nsSVGUseFrame.cpp index 9693ebc824ac..e3a8b03e0b81 100644 --- a/layout/svg/base/src/nsSVGUseFrame.cpp +++ b/layout/svg/base/src/nsSVGUseFrame.cpp @@ -130,13 +130,7 @@ nsSVGUseFrame::AttributeChanged(PRInt32 aNameSpaceID, // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; - for (nsIFrame* kid = mFrames.FirstChild(); kid; - kid = kid->GetNextSibling()) { - nsISVGChildFrame* SVGFrame = nsnull; - CallQueryInterface(kid, &SVGFrame); - if (SVGFrame) - SVGFrame->NotifyCanvasTMChanged(PR_FALSE); - } + nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); return NS_OK; } diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index eb9691fb6273..2209f323729f 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -918,8 +918,7 @@ nsSVGUtils::ObjectSpace(nsIDOMSVGRect *aRect, nsSVGLength2 *aLength) } } - if (aLength->GetSpecifiedUnitType() == - nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) { + if (aLength->IsPercentage()) { fraction = aLength->GetAnimValInSpecifiedUnits() / 100; } else fraction = aLength->GetAnimValue(static_cast @@ -1115,7 +1114,7 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame) } void -nsSVGUtils::NotifyChildrenCanvasTMChanged(nsIFrame *aFrame, PRBool suppressInvalidation) +nsSVGUtils::NotifyChildrenOfSVGChange(nsIFrame *aFrame, PRUint32 aFlags) { nsIFrame *aKid = aFrame->GetFirstChild(nsnull); @@ -1123,12 +1122,12 @@ nsSVGUtils::NotifyChildrenCanvasTMChanged(nsIFrame *aFrame, PRBool suppressInval nsISVGChildFrame* SVGFrame = nsnull; CallQueryInterface(aKid, &SVGFrame); if (SVGFrame) { - SVGFrame->NotifyCanvasTMChanged(suppressInvalidation); + SVGFrame->NotifySVGChanged(aFlags); } else { NS_ASSERTION(aKid->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected"); // recurse into the children of container frames e.g. , // in case they have child frames with transformation matrices - nsSVGUtils::NotifyChildrenCanvasTMChanged(aKid, suppressInvalidation); + nsSVGUtils::NotifyChildrenOfSVGChange(aKid, aFlags); } aKid = aKid->GetNextSibling(); } diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h index fd2d3695f876..57e5173c1845 100644 --- a/layout/svg/base/src/nsSVGUtils.h +++ b/layout/svg/base/src/nsSVGUtils.h @@ -354,10 +354,10 @@ public: static already_AddRefed GetCanvasTM(nsIFrame *aFrame); /* - * Tells child frames that the canvasTM has changed + * Tells child frames that something that might affect them has changed */ static void - NotifyChildrenCanvasTMChanged(nsIFrame *aFrame, PRBool suppressInvalidation); + NotifyChildrenOfSVGChange(nsIFrame *aFrame, PRUint32 aFlags); /* * Get frame's covered region by walking the children and doing union. diff --git a/layout/tables/BasicTableLayoutStrategy.cpp b/layout/tables/BasicTableLayoutStrategy.cpp index c511f9dd1c05..6e0a265c7859 100644 --- a/layout/tables/BasicTableLayoutStrategy.cpp +++ b/layout/tables/BasicTableLayoutStrategy.cpp @@ -254,7 +254,6 @@ BasicTableLayoutStrategy::ComputeColumnIntrinsicWidths(nsIRenderingContext* aRen nsTableFrame *tableFrame = mTableFrame; nsTableCellMap *cellMap = tableFrame->GetCellMap(); - nscoord spacing = tableFrame->GetCellSpacingX(); SpanningCellSorter spanningCells(tableFrame->PresContext()->PresShell()); // Loop over the columns to consider the columns and cells *without* @@ -351,191 +350,14 @@ BasicTableLayoutStrategy::ComputeColumnIntrinsicWidths(nsIRenderingContext* aRen CellWidthInfo info = GetCellWidthInfo(aRenderingContext, cellFrame); - // Before looping over the spanned columns to distribute - // this cell's width over the columns it spans, we first - // compute totals over the spanned columns so we know how to - // allocate the space. - - // Accumulate information about the spanned columns, and - // subtract the already-used space from |info|. - nscoord totalSPref = 0, totalSMin = 0; // total existing widths - nscoord totalSNonPctPref = 0; // total pref width of columns - // without percentage widths - nscoord totalSAutoPref = 0; // total pref width of auto-width cols - PRInt32 nonPctCount = 0; // # of columns without percentage widths - PRInt32 scol, scol_end; - for (scol = col, scol_end = col + colSpan; - scol < scol_end; ++scol) { - nsTableColFrame *scolFrame = tableFrame->GetColFrame(scol); - if (!scolFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - - if (mTableFrame->GetNumCellsOriginatingInCol(scol) && - scol != col) { - info.minCoord -= spacing; - info.prefCoord = NSCoordSaturatingSubtract(info.prefCoord, - spacing, - nscoord_MAX); - } - - totalSPref += scolFrame->GetPrefCoord(); - totalSMin += scolFrame->GetMinCoord(); - if (!scolFrame->GetHasSpecifiedCoord()) { - totalSAutoPref += scolFrame->GetPrefCoord(); - } - float scolPct = scolFrame->GetPrefPercent(); - if (scolPct == 0.0f) { - totalSNonPctPref += scolFrame->GetPrefCoord(); - ++nonPctCount; - } else { - info.prefPercent -= scolPct; - } - info.minCoord -= scolFrame->GetMinCoord(); - info.prefCoord = - NSCoordSaturatingSubtract(info.prefCoord, - scolFrame->GetPrefCoord(), - nscoord_MAX); + if (info.prefPercent > 0.0f) { + DistributePctWidthToColumns(info.prefPercent, + col, colSpan); } - - if (info.minCoord < 0) - info.minCoord = 0; - if (info.prefCoord < 0) - info.prefCoord = 0; - if (info.prefPercent < 0.0f) - info.prefPercent = 0.0f; - - // The min-width of this cell that fits inside the - // pref-width of the spanned columns gets distributed - // according to different ratios. - nscoord minWithinPref = - PR_MIN(info.minCoord, totalSPref - totalSMin); - NS_ASSERTION(minWithinPref >= 0, "neither value can be negative"); - nscoord minOutsidePref = info.minCoord - minWithinPref; - - // Loop invariants (that we might get confused about as we - // subtract amounts for completed columns) - const PRBool spanHasNonPctPref = totalSNonPctPref > 0; - const PRBool spanHasPref = totalSPref > 0; - const PRBool spanHasNonPct = nonPctCount > 0; - - // ... and actually do the distribution of the widths of - // this cell exceeding the totals already in the spanned - // columns. - for (scol = col, scol_end = col + colSpan; - scol < scol_end; ++scol) { - nsTableColFrame *scolFrame = tableFrame->GetColFrame(scol); - if (!scolFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - - // the percentage width (only to columns that don't - // already have percentage widths, in proportion to - // the existing pref widths) - float allocatedPct = 0.0f; - if (scolFrame->GetPrefPercent() == 0.0f && - info.prefPercent != 0.0f) { - NS_ASSERTION((!spanHasNonPctPref || - totalSNonPctPref != 0) && - nonPctCount != 0, - "should not be zero if we haven't allocated " - "all pref percent"); - if (spanHasNonPctPref) { - // Group so we're multiplying by 1.0f when we need - // to use up info.prefPercent. - allocatedPct = info.prefPercent * - (float(scolFrame->GetPrefCoord()) / - float(totalSNonPctPref)); - } else { - // distribute equally when all pref widths are 0 - allocatedPct = info.prefPercent / float(nonPctCount); - } - scolFrame->AddSpanPrefPercent(allocatedPct); - } - - // the part of the min width that fits within the - // existing pref width - float minRatio = 0.0f; - if (minWithinPref > 0) { - minRatio = float(scolFrame->GetPrefCoord() - - scolFrame->GetMinCoord()) / - float(totalSPref - totalSMin); - } - - // the rest of the min width, and the pref width (in - // proportion to the existing pref widths) - float coordRatio; // for both min and pref - if (spanHasPref) { - if (scolFrame->GetPrefCoord() == 0) { - // We might have already subtracted all of - // totalSPref. - coordRatio = 0.0f; - } else if (totalSAutoPref == 0) { - // No auto-width cols left -- dividing up totalSPref - coordRatio = float(scolFrame->GetPrefCoord()) / - float(totalSPref); - } else if (!scolFrame->GetHasSpecifiedCoord()) { - // There are auto-width cols left, and this is one - coordRatio = float(scolFrame->GetPrefCoord()) / - float(totalSAutoPref); - } else { - // There are auto-width cols left, and this isn't one - coordRatio = 0.0f; - } - } else { - // distribute equally when all pref widths are 0 - coordRatio = 1.0f / float(scol_end - scol); - } - - // combine the two min-width distributions, and record - // min and pref - nscoord allocatedMinWithinPref = - NSToCoordRound(float(minWithinPref) * minRatio); - nscoord allocatedMinOutsidePref = - NSToCoordRound(float(minOutsidePref) * coordRatio); - nscoord allocatedPref = - (info.prefCoord == nscoord_MAX ? - nscoord_MAX : - NSToCoordRound(float(info.prefCoord) * coordRatio)); - nscoord spanMin = scolFrame->GetMinCoord() + - allocatedMinWithinPref + allocatedMinOutsidePref; - nscoord spanPref = - NSCoordSaturatingAdd(scolFrame->GetPrefCoord(), - allocatedPref); - scolFrame->AddSpanCoords(spanMin, spanPref, - info.hasSpecifiedWidth); - - // To avoid accumulating rounding error from division, - // subtract everything to do with the column we've - // passed from the totals. - minWithinPref -= allocatedMinWithinPref; - minOutsidePref -= allocatedMinOutsidePref; - info.prefCoord = NSCoordSaturatingSubtract(info.prefCoord, - allocatedPref, - nscoord_MAX); - info.prefPercent -= allocatedPct; - totalSPref -= scolFrame->GetPrefCoord(); - totalSMin -= scolFrame->GetMinCoord(); - if (!scolFrame->GetHasSpecifiedCoord()) { - totalSAutoPref -= scolFrame->GetPrefCoord(); - } - if (scolFrame->GetPrefPercent() == 0.0f) { - totalSNonPctPref -= scolFrame->GetPrefCoord(); - --nonPctCount; - } - } - - // Note that we only distribute the percentage if - // spanHasNonPct. - NS_ASSERTION(totalSPref == 0 && totalSMin == 0 && - totalSNonPctPref == 0 && nonPctCount == 0 && - minOutsidePref == 0 && minWithinPref == 0 && - (info.prefCoord == 0 || - info.prefCoord == nscoord_MAX) && - (info.prefPercent == 0.0f || !spanHasNonPct), - "didn't subtract all that we added"); + DistributeWidthToColumns(info.minCoord, col, colSpan, + BTLS_MIN_WIDTH, info.hasSpecifiedWidth); + DistributeWidthToColumns(info.prefCoord, col, colSpan, + BTLS_PREF_WIDTH, info.hasSpecifiedWidth); } while ((item = item->next)); // Combine the results of the span analysis into the main results, @@ -699,25 +521,128 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt if (colCount <= 0) return; // nothing to do - nscoord spacing = mTableFrame->GetCellSpacingX(); + DistributeWidthToColumns(width, 0, colCount, BTLS_FINAL_WIDTH, PR_FALSE); - nscoord min = mMinWidth; +#ifdef DEBUG_TABLE_STRATEGY + printf("ComputeColumnWidths final\n"); + mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE); +#endif +} + +void +BasicTableLayoutStrategy::DistributePctWidthToColumns(float aSpanPrefPct, + PRInt32 aFirstCol, + PRInt32 aColCount) +{ + // First loop to determine: + PRInt32 nonPctColCount = 0; // number of spanned columns without % width + nscoord nonPctTotalPrefWidth = 0; // total pref width of those columns + // and to reduce aSpanPrefPct by columns that already have % width + + PRInt32 scol, scol_end; + for (scol = aFirstCol, scol_end = aFirstCol + aColCount; + scol < scol_end; ++scol) { + nsTableColFrame *scolFrame = mTableFrame->GetColFrame(scol); + if (!scolFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + float scolPct = scolFrame->GetPrefPercent(); + if (scolPct == 0.0f) { + nonPctTotalPrefWidth += scolFrame->GetPrefCoord(); + ++nonPctColCount; + } else { + aSpanPrefPct -= scolPct; + } + } + + if (aSpanPrefPct <= 0.0f || nonPctColCount == 0) { + // There's no %-width on the colspan left over to distribute, + // or there are no columns to which we could distribute %-width + return; + } + + // Second loop, to distribute what remains of aSpanPrefPct + // between the non-percent-width spanned columns + const PRBool spanHasNonPctPref = nonPctTotalPrefWidth > 0; // Loop invariant + for (scol = aFirstCol, scol_end = aFirstCol + aColCount; + scol < scol_end; ++scol) { + nsTableColFrame *scolFrame = mTableFrame->GetColFrame(scol); + if (!scolFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + + // the percentage width (only to columns that don't + // already have percentage widths, in proportion to + // the existing pref widths) + float allocatedPct = 0.0f; + if (scolFrame->GetPrefPercent() == 0.0f) { + NS_ASSERTION((!spanHasNonPctPref || + nonPctTotalPrefWidth != 0) && + nonPctColCount != 0, + "should not be zero if we haven't allocated " + "all pref percent"); + if (spanHasNonPctPref) { + // Group so we're multiplying by 1.0f when we need + // to use up aSpanPrefPct. + allocatedPct = aSpanPrefPct * + (float(scolFrame->GetPrefCoord()) / + float(nonPctTotalPrefWidth)); + } else { + // distribute equally when all pref widths are 0 + allocatedPct = aSpanPrefPct / float(nonPctColCount); + } + // Allocate the percent + scolFrame->AddSpanPrefPercent(allocatedPct); + + // To avoid accumulating rounding error from division, + // subtract this column's values from the totals. + aSpanPrefPct -= allocatedPct; + nonPctTotalPrefWidth -= scolFrame->GetPrefCoord(); + --nonPctColCount; + } + } +} + +void +BasicTableLayoutStrategy::DistributeWidthToColumns(nscoord aWidth, + PRInt32 aFirstCol, + PRInt32 aColCount, + BtlsWidthType aWidthType, + PRBool aSpanHasSpecifiedWidth) +{ + NS_ASSERTION(aWidthType != BTLS_FINAL_WIDTH || + (aFirstCol == 0 && + aColCount == mTableFrame->GetCellMap()->GetColCount()), + "Computing final column widths, but didn't get full column range"); // border-spacing isn't part of the basis for percentages. - nscoord subtract = spacing; - for (PRInt32 col = 0; col < colCount; ++col) { + nscoord spacing = mTableFrame->GetCellSpacingX(); + nscoord subtract = 0; + // aWidth initially includes border-spacing for the boundaries in between + // each of the columns. We start at aFirstCol + 1 because the first + // in-between boundary would be at the left edge of column aFirstCol + 1 + for (PRInt32 col = aFirstCol + 1; col < aFirstCol + aColCount; ++col) { if (mTableFrame->GetNumCellsOriginatingInCol(col)) { subtract += spacing; } } - width = NSCoordSaturatingSubtract(width, subtract, nscoord_MAX); - min -= subtract; - - // XXX is |width| the right basis for percentage widths? + if (aWidthType == BTLS_FINAL_WIDTH) { + // If we're computing final col-width, then aWidth initially includes + // border spacing on the table's far left + far right edge, too. Need + // to subtract those out, too. + subtract += spacing * 2; + } + aWidth = NSCoordSaturatingSubtract(aWidth, subtract, nscoord_MAX); /* - * The goal of this function is to allocate |width| to the columns - * by making an appropriate SetFinalWidth call to each column. + * The goal of this function is to distribute |aWidth| between the + * columns by making an appropriate AddSpanCoords or SetFinalWidth + * call for each column. (We call AddSpanCoords if we're + * distributing a column-spanning cell's minimum or preferred width + * to its spanned columns. We call SetFinalWidth if we're + * distributing a table's final width to its columns.) * * The idea is to either assign one of the following sets of widths * or a weighted average of two adjacent sets of widths. It is not @@ -740,7 +665,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt * 4. [guess_pref] Assign all columns with percentage widths their * specified width, and all other columns their pref width. * - * If |width| is *larger* than what we would assign in (4), then we + * If |aWidth| is *larger* than what we would assign in (4), then we * expand the columns: * * a. if any columns without a specified coordinate width or @@ -769,7 +694,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt PRInt32 numInfiniteWidthCols = 0; PRInt32 col; - for (col = 0; col < colCount; ++col) { + for (col = aFirstCol; col < aFirstCol + aColCount; ++col) { nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); if (!colFrame) { NS_ERROR("column frames out of sync with cell map"); @@ -780,7 +705,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt if (colFrame->GetPrefPercent() != 0.0f) { float pct = colFrame->GetPrefPercent(); total_pct += pct; - nscoord val = nscoord(float(width) * pct); + nscoord val = nscoord(float(aWidth) * pct); if (val < min_width) val = min_width; guess_min_pct += val; @@ -813,10 +738,10 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt FLEX_PCT_SMALL, // between (1) and (2) above FLEX_FIXED_SMALL, // between (2) and (3) above FLEX_FLEX_SMALL, // between (3) and (4) above - FLEX_FLEX_LARGE, // above (4) above, case (a) - FLEX_FIXED_LARGE, // above (4) above, case (b) - FLEX_PCT_LARGE, // above (4) above, case (c) - FLEX_ALL_LARGE // above (4) above, case (d) + FLEX_FLEX_LARGE, // greater than (4) above, case (a) + FLEX_FIXED_LARGE, // greater than (4) above, case (b) + FLEX_PCT_LARGE, // greater than (4) above, case (c) + FLEX_ALL_LARGE // greater than (4) above, case (d) }; Loop2Type l2t; @@ -828,28 +753,32 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt nscoord c; float f; } basis; // the sum of the statistic over columns to divide it - if (width < guess_pref) { - NS_ASSERTION(width >= guess_min, "bad width"); - if (width < guess_min_pct) { + if (aWidth < guess_pref) { + if ((aWidthType == BTLS_MIN_WIDTH && aWidth <= guess_min) || + (aWidthType == BTLS_PREF_WIDTH && aWidth <= guess_pref)) { + // Return early -- we don't have any extra space to distribute. + return; + } + NS_ASSERTION(!(aWidthType == BTLS_FINAL_WIDTH && aWidth < guess_min), + "Table width is less than the " + "sum of its columns' min widths"); + if (aWidth < guess_min_pct) { l2t = FLEX_PCT_SMALL; - space = width - guess_min; + space = aWidth - guess_min; basis.c = guess_min_pct - guess_min; - } else if (width < guess_min_spec) { + } else if (aWidth < guess_min_spec) { l2t = FLEX_FIXED_SMALL; - space = width - guess_min_pct; + space = aWidth - guess_min_pct; basis.c = NSCoordSaturatingSubtract(guess_min_spec, guess_min_pct, nscoord_MAX); } else { l2t = FLEX_FLEX_SMALL; - space = width - guess_min_spec; + space = aWidth - guess_min_spec; basis.c = NSCoordSaturatingSubtract(guess_pref, guess_min_spec, nscoord_MAX); } } else { - // Note: Shouldn't have to check for nscoord_MAX in this case, because - // width should be much less than nscoord_MAX, and being here means - // guess_pref is no larger than width. - space = width - guess_pref; + space = NSCoordSaturatingSubtract(aWidth, guess_pref, nscoord_MAX); if (total_flex_pref > 0) { l2t = FLEX_FLEX_LARGE; basis.c = total_flex_pref; @@ -861,7 +790,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt basis.f = total_pct; } else { l2t = FLEX_ALL_LARGE; - basis.c = colCount; + basis.c = aColCount; } } @@ -869,13 +798,13 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt printf("ComputeColumnWidths: %d columns in width %d,\n" " guesses=[%d,%d,%d,%d], totals=[%d,%d,%f],\n" " l2t=%d, space=%d, basis.c=%d\n", - colCount, width, + aColCount, aWidth, guess_min, guess_min_pct, guess_min_spec, guess_pref, total_flex_pref, total_fixed_pref, total_pct, l2t, space, basis.c); #endif - for (col = 0; col < colCount; ++col) { + for (col = aFirstCol; col < aFirstCol + aColCount; ++col) { nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); if (!colFrame) { NS_ERROR("column frames out of sync with cell map"); @@ -885,7 +814,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt float pct = colFrame->GetPrefPercent(); if (pct != 0.0f) { - col_width = nscoord(float(width) * pct); + col_width = nscoord(float(aWidth) * pct); nscoord col_min = colFrame->GetMinCoord(); if (col_width < col_min) col_width = col_min; @@ -900,7 +829,7 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt col_width = col_width_before_adjust = colFrame->GetMinCoord(); if (pct != 0.0f) { nscoord pct_minus_min = - nscoord(float(width) * pct) - col_width; + nscoord(float(aWidth) * pct) - col_width; if (pct_minus_min > 0) { float c = float(space) / float(basis.c); basis.c -= pct_minus_min; @@ -968,9 +897,14 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt NS_ASSERTION(col_width == colFrame->GetPrefCoord(), "wrong width assigned"); if (col_width != 0) { - float c = float(space) / float(basis.c); - basis.c -= col_width; - col_width += NSToCoordRound(float(col_width) * c); + if (space == nscoord_MAX) { + basis.c -= col_width; + col_width = nscoord_MAX; + } else { + float c = float(space) / float(basis.c); + basis.c -= col_width; + col_width += NSToCoordRound(float(col_width) * c); + } } } break; @@ -1006,24 +940,53 @@ BasicTableLayoutStrategy::ComputeColumnWidths(const nsHTMLReflowState& aReflowSt break; } - space -= col_width - col_width_before_adjust; + // Only subtract from space if it's a real number. + if (space != nscoord_MAX) { + NS_ASSERTION(col_width != nscoord_MAX, + "How is col_width nscoord_MAX if space isn't?"); + NS_ASSERTION(col_width_before_adjust != nscoord_MAX, + "How is col_width_before_adjust nscoord_MAX if space isn't?"); + space -= col_width - col_width_before_adjust; + } NS_ASSERTION(col_width >= colFrame->GetMinCoord(), "assigned width smaller than min"); - - nscoord old_final = colFrame->GetFinalWidth(); - colFrame->SetFinalWidth(col_width); - - if (old_final != col_width) - mTableFrame->DidResizeColumns(); + + // Apply the new width + switch (aWidthType) { + case BTLS_MIN_WIDTH: + { + // Note: AddSpanCoords requires both a min and pref width. + // For the pref width, we'll just pass in our computed + // min width, because the real pref width will be at least + // as big + colFrame->AddSpanCoords(col_width, col_width, + aSpanHasSpecifiedWidth); + } + break; + case BTLS_PREF_WIDTH: + { + // Note: AddSpanCoords requires both a min and pref width. + // For the min width, we'll just pass in 0, because + // the real min width will be at least 0 + colFrame->AddSpanCoords(0, col_width, + aSpanHasSpecifiedWidth); + } + break; + case BTLS_FINAL_WIDTH: + { + nscoord old_final = colFrame->GetFinalWidth(); + colFrame->SetFinalWidth(col_width); + + if (old_final != col_width) + mTableFrame->DidResizeColumns(); + } + break; + } } - NS_ASSERTION(space == 0 && + NS_ASSERTION((space == 0 || space == nscoord_MAX) && ((l2t == FLEX_PCT_LARGE) ? (-0.001f < basis.f && basis.f < 0.001f) : (basis.c == 0 || basis.c == nscoord_MAX)), "didn't subtract all that we added"); -#ifdef DEBUG_TABLE_STRATEGY - printf("ComputeColumnWidths final\n"); - mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE); -#endif } diff --git a/layout/tables/BasicTableLayoutStrategy.h b/layout/tables/BasicTableLayoutStrategy.h index 62dcb5882f6f..205b682feff4 100644 --- a/layout/tables/BasicTableLayoutStrategy.h +++ b/layout/tables/BasicTableLayoutStrategy.h @@ -62,9 +62,42 @@ public: virtual void ComputeColumnWidths(const nsHTMLReflowState& aReflowState); private: + // NOTE: Using prefix "BTLS" to avoid overlapping names with + // the values of nsLayoutUtils::IntrinsicWidthType + enum BtlsWidthType { BTLS_MIN_WIDTH, + BTLS_PREF_WIDTH, + BTLS_FINAL_WIDTH }; + // Compute intrinsic width member variables on the columns. void ComputeColumnIntrinsicWidths(nsIRenderingContext* aRenderingContext); + // Distribute a colspanning cell's percent width (if any) to its columns. + void DistributePctWidthToColumns(float aSpanPrefPct, + PRInt32 aFirstCol, + PRInt32 aColCount); + + // Distribute a width of some BltsWidthType type to a set of columns. + // aWidth: The amount of width to be distributed + // aFirstCol: The index (in the table) of the first column to be + // considered for receiving width + // aColCount: The number of consecutive columns (starting with aFirstCol) + // to be considered for receiving width + // aWidthType: The type of width being distributed. (BTLS_MIN_WIDTH and + // BTLS_PREF_WIDTH are intended to be used for dividing up + // colspan's min & pref width. BTLS_FINAL_WIDTH is intended + // to be used for distributing the table's final width across + // all its columns) + // aSpanHasSpecifiedWidth: Should be PR_TRUE iff: + // - We're distributing a colspanning cell's + // pref or min width to its columns + // - The colspanning cell has a specified width. + void DistributeWidthToColumns(nscoord aWidth, + PRInt32 aFirstCol, + PRInt32 aColCount, + BtlsWidthType aWidthType, + PRBool aSpanHasSpecifiedWidth); + + // Compute the min and pref widths of the table from the width // variables on the columns. void ComputeIntrinsicWidths(nsIRenderingContext* aRenderingContext); diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp index 1d9aa6d3b9a7..2f6599c8fd1f 100644 --- a/layout/tables/nsTableColFrame.cpp +++ b/layout/tables/nsTableColFrame.cpp @@ -155,9 +155,9 @@ void nsTableColFrame::Dump(PRInt32 aIndent) printf(" anonymous-cell "); break; } - printf("\nm:%d c:%d(%c) p:%f sm:%d sc:%d(%c) sp:%f f:%d", + printf("\nm:%d c:%d(%c) p:%f sm:%d sc:%d sp:%f f:%d", mMinCoord, mPrefCoord, mHasSpecifiedCoord ? 's' : 'u', mPrefPercent, - mSpanMinCoord, mSpanPrefCoord, mSpanHasSpecifiedCoord ? 's' : 'u', + mSpanMinCoord, mSpanPrefCoord, mSpanPrefPercent, GetFinalWidth()); printf("\n%s**END COL DUMP** ", indent); diff --git a/layout/tables/nsTableColFrame.h b/layout/tables/nsTableColFrame.h index 15cd58bd8582..146eec19acc6 100644 --- a/layout/tables/nsTableColFrame.h +++ b/layout/tables/nsTableColFrame.h @@ -165,7 +165,6 @@ public: mSpanMinCoord = 0; mSpanPrefCoord = 0; mSpanPrefPercent = 0.0f; - mSpanHasSpecifiedCoord = PR_FALSE; } /** @@ -249,11 +248,7 @@ public: NS_ASSERTION(aSpanMinCoord <= aSpanPrefCoord, "intrinsic widths out of order"); - if (aSpanHasSpecifiedCoord && !mSpanHasSpecifiedCoord) { - mSpanPrefCoord = mSpanMinCoord; - mSpanHasSpecifiedCoord = PR_TRUE; - } - if (!aSpanHasSpecifiedCoord && mSpanHasSpecifiedCoord) { + if (!aSpanHasSpecifiedCoord && mHasSpecifiedCoord) { aSpanPrefCoord = aSpanMinCoord; // NOTE: modifying argument } @@ -279,7 +274,7 @@ public: * the primary variables. */ void AccumulateSpanIntrinsics() { - AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord && mSpanHasSpecifiedCoord); + AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord); AddPrefPercent(mSpanPrefPercent); } @@ -322,7 +317,6 @@ protected: BCPixelSize mBottomContBorderWidth; PRPackedBool mHasSpecifiedCoord; - PRPackedBool mSpanHasSpecifiedCoord; // XXX... nscoord mMinCoord; nscoord mPrefCoord; nscoord mSpanMinCoord; // XXX... diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index 42d470671af9..0f05eb3e9d22 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -1325,67 +1325,6 @@ NS_METHOD nsTableOuterFrame::VerifyTree() const } #endif -/** - * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow - * pointers. - * - * Updates the child count and content offsets of all containers that are - * affected - * - * Overloaded here because nsContainerFrame makes assumptions about pseudo-frames - * that are not true for tables. - * - * @param aChild child this child's next-in-flow - * @return PR_TRUE if successful and PR_FALSE otherwise - */ -void nsTableOuterFrame::DeleteChildsNextInFlow(nsPresContext* aPresContext, - nsIFrame* aChild) -{ - if (!aChild) return; - NS_PRECONDITION(mFrames.ContainsFrame(aChild), "bad geometric parent"); - - nsIFrame* nextInFlow = aChild->GetNextInFlow(); - if (!nextInFlow) { - NS_ASSERTION(PR_FALSE, "null next-in-flow"); - return; - } - - nsTableOuterFrame* parent = static_cast - (nextInFlow->GetParent()); - if (!parent) { - NS_ASSERTION(PR_FALSE, "null parent"); - return; - } - // If the next-in-flow has a next-in-flow then delete it too (and - // delete it first). - nsIFrame* nextNextInFlow = nextInFlow->GetNextInFlow(); - if (nextNextInFlow) { - parent->DeleteChildsNextInFlow(aPresContext, nextInFlow); - } - - // Disconnect the next-in-flow from the flow list - nsSplittableFrame::BreakFromPrevFlow(nextInFlow); - - // Take the next-in-flow out of the parent's child list - if (parent->mFrames.FirstChild() == nextInFlow) { - parent->mFrames.SetFrames(nextInFlow->GetNextSibling()); - } else { - // Because the next-in-flow is not the first child of the parent - // we know that it shares a parent with aChild. Therefore, we need - // to capture the next-in-flow's next sibling (in case the - // next-in-flow is the last next-in-flow for aChild AND the - // next-in-flow is not the last child in parent) - NS_ASSERTION(aChild->GetNextSibling() == nextInFlow, "unexpected sibling"); - - aChild->SetNextSibling(nextInFlow->GetNextSibling()); - } - - // Delete the next-in-flow frame and adjust its parent's child count - nextInFlow->Destroy(); - - NS_POSTCONDITION(!aChild->GetNextInFlow(), "non null next-in-flow"); -} - nsIAtom* nsTableOuterFrame::GetType() const { diff --git a/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index 153cc55cbede..a4781a100f53 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/layout/tables/nsTableOuterFrame.h @@ -215,21 +215,6 @@ protected: NS_IMETHOD VerifyTree() const; #endif - /** - * Remove and delete aChild's next-in-flow(s). Updates the sibling and flow - * pointers. - * - * Updates the child count and content offsets of all containers that are - * affected - * - * Overloaded here because nsContainerFrame makes assumptions about pseudo-frames - * that are not true for tables. - * - * @param aChild child this child's next-in-flow - * @return PR_TRUE if successful and PR_FALSE otherwise - */ - virtual void DeleteChildsNextInFlow(nsPresContext* aPresContext, nsIFrame* aChild); - PRUint8 GetCaptionSide(); PRUint8 GetCaptionVerticalAlign(); diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index a2ea2eac513f..3dfe28a3496e 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -1051,6 +1051,10 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext, PRBool isTopOfPage = aReflowState.mFlags.mIsTopOfPage; nsTableRowFrame* firstRowThisPage = GetFirstRow(); + // Need to dirty the table's geometry, or else the row might skip + // reflowing its cell as an optimization. + aTableFrame->SetGeometryDirty(); + // Walk each of the row frames looking for the first row frame that doesn't fit // in the available space for (nsTableRowFrame* rowFrame = firstRowThisPage; rowFrame; rowFrame = rowFrame->GetNextRow()) { @@ -1286,7 +1290,8 @@ nsTableRowGroupFrame::Reflow(nsPresContext* aPresContext, // not paginated ... we can't split across columns yet. if (aReflowState.mFlags.mTableIsSplittable && (NS_FRAME_NOT_COMPLETE == aStatus || splitDueToPageBreak || - aDesiredSize.height > aReflowState.availableHeight)) { + (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight && + aDesiredSize.height > aReflowState.availableHeight))) { // Nope, find a place to split the row group PRBool specialReflow = (PRBool)aReflowState.mFlags.mSpecialHeightReflow; ((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = PR_FALSE; diff --git a/layout/tools/pageloader/report.js b/layout/tools/pageloader/report.js index cdb0cd6a4767..4fa91f637dc4 100644 --- a/layout/tools/pageloader/report.js +++ b/layout/tools/pageloader/report.js @@ -107,18 +107,22 @@ function getArrayStats(ary) { } // median - sorted_ary = ary.concat(); - sorted_ary.sort(); - // remove longest run - sorted_ary.pop(); - if (sorted_ary.length%2) { - r.median = sorted_ary[(sorted_ary.length-1)/2]; + if (ary.length > 1) { + sorted_ary = ary.concat(); + sorted_ary.sort(); + // remove longest run + sorted_ary.pop(); + if (sorted_ary.length%2) { + r.median = sorted_ary[(sorted_ary.length-1)/2]; + }else{ + var n = Math.floor(sorted_ary.length / 2); + if (n >= sorted_ary.length) + r.median = sorted_ary[n]; + else + r.median = (sorted_ary[n] + sorted_ary[n + 1]) / 2; + } }else{ - var n = Math.floor(sorted_ary.length / 2); - if (n >= sorted_ary.length) - r.median = sorted_ary[n]; - else - r.median = (sorted_ary[n] + sorted_ary[n + 1]) / 2; + r.median = ary[0]; } // ignore max value when computing mean and stddev diff --git a/layout/xul/base/src/grid/nsGridRowLeafLayout.cpp b/layout/xul/base/src/grid/nsGridRowLeafLayout.cpp index 318eea49bb09..f745db39fbc5 100644 --- a/layout/xul/base/src/grid/nsGridRowLeafLayout.cpp +++ b/layout/xul/base/src/grid/nsGridRowLeafLayout.cpp @@ -219,6 +219,7 @@ nsGridRowLeafLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, ns } // initialize the box size here + max = PR_MAX(min, max); pref = nsBox::BoundsCheck(min, pref, max); current = new (aState) nsBoxSize(); diff --git a/layout/xul/base/src/nsLeafBoxFrame.cpp b/layout/xul/base/src/nsLeafBoxFrame.cpp index 8c080ffc1057..3b7a6f20c63d 100644 --- a/layout/xul/base/src/nsLeafBoxFrame.cpp +++ b/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -229,6 +229,17 @@ nsLeafBoxFrame::GetIntrinsicWidth() return 0; } +nsSize +nsLeafBoxFrame::ComputeAutoSize(nsIRenderingContext *aRenderingContext, + nsSize aCBSize, nscoord aAvailableWidth, + nsSize aMargin, nsSize aBorder, + nsSize aPadding, PRBool aShrinkWrap) +{ + // Important: NOT calling our direct superclass here! + return nsFrame::ComputeAutoSize(aRenderingContext, aCBSize, aAvailableWidth, + aMargin, aBorder, aPadding, aShrinkWrap); +} + NS_IMETHODIMP nsLeafBoxFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/xul/base/src/nsLeafBoxFrame.h b/layout/xul/base/src/nsLeafBoxFrame.h index 2049ccc68237..5c5fe6a621da 100644 --- a/layout/xul/base/src/nsLeafBoxFrame.h +++ b/layout/xul/base/src/nsLeafBoxFrame.h @@ -77,6 +77,12 @@ public: virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext); virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext); + // Our auto size is that provided by nsFrame, not nsLeafFrame + virtual nsSize ComputeAutoSize(nsIRenderingContext *aRenderingContext, + nsSize aCBSize, nscoord aAvailableWidth, + nsSize aMargin, nsSize aBorder, + nsSize aPadding, PRBool aShrinkWrap); + NS_IMETHOD Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, diff --git a/layout/xul/base/src/nsSprocketLayout.cpp b/layout/xul/base/src/nsSprocketLayout.cpp index 638783feb468..36b1297fab0c 100644 --- a/layout/xul/base/src/nsSprocketLayout.cpp +++ b/layout/xul/base/src/nsSprocketLayout.cpp @@ -920,6 +920,7 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox // we specified all our children are equal size; if (frameState & NS_STATE_EQUAL_SIZE) { + smallestMaxWidth = PR_MAX(smallestMaxWidth, biggestMinWidth); biggestPrefWidth = nsBox::BoundsCheck(biggestMinWidth, biggestPrefWidth, smallestMaxWidth); currentBox = aBoxSizes; diff --git a/layout/xul/base/src/nsTextBoxFrame.cpp b/layout/xul/base/src/nsTextBoxFrame.cpp index 95c7bbea94bc..34f26f684eff 100644 --- a/layout/xul/base/src/nsTextBoxFrame.cpp +++ b/layout/xul/base/src/nsTextBoxFrame.cpp @@ -628,7 +628,7 @@ nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext, return; // fits, done. } - const nsDependentString kEllipsis = nsContentUtils::GetLocalizedEllipsis(); + const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis(); // start with an ellipsis mCroppedTitle.Assign(kEllipsis); @@ -819,7 +819,7 @@ nsTextBoxFrame::UpdateAccessTitle() return; } - const nsDependentString kEllipsis = nsContentUtils::GetLocalizedEllipsis(); + const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis(); PRUint32 offset = mTitle.Length(); if (StringEndsWith(mTitle, kEllipsis)) { offset -= kEllipsis.Length(); diff --git a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp index 2f21b4bd5b1e..5492e87846d3 100644 --- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -1350,7 +1350,7 @@ nsTreeBodyFrame::AdjustForCellText(nsAutoString& aText, if (width > maxWidth) { // See if the width is even smaller than the ellipsis // If so, clear the text completely. - const nsDependentString kEllipsis = nsContentUtils::GetLocalizedEllipsis(); + const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis(); nscoord ellipsisWidth; aRenderingContext.SetTextRunRTL(PR_FALSE); aRenderingContext.GetWidth(kEllipsis, ellipsisWidth); diff --git a/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp b/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp index 810be3db6eed..b9d275ac05a2 100644 --- a/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp @@ -207,6 +207,7 @@ NS_IMETHODIMP nsTreeBoxObject::SetView(nsITreeView * aView) NS_IMETHODIMP nsTreeBoxObject::GetFocused(PRBool* aFocused) { + *aFocused = PR_FALSE; nsITreeBoxObject* body = GetTreeBody(); if (body) return body->GetFocused(aFocused); @@ -223,6 +224,7 @@ NS_IMETHODIMP nsTreeBoxObject::SetFocused(PRBool aFocused) NS_IMETHODIMP nsTreeBoxObject::GetTreeBody(nsIDOMElement** aElement) { + *aElement = nsnull; nsITreeBoxObject* body = GetTreeBody(); if (body) return body->GetTreeBody(aElement); @@ -231,57 +233,64 @@ NS_IMETHODIMP nsTreeBoxObject::GetTreeBody(nsIDOMElement** aElement) NS_IMETHODIMP nsTreeBoxObject::GetColumns(nsITreeColumns** aColumns) { + *aColumns = nsnull; nsITreeBoxObject* body = GetTreeBody(); if (body) return body->GetColumns(aColumns); return NS_OK; } -NS_IMETHODIMP nsTreeBoxObject::GetRowHeight(PRInt32* _retval) +NS_IMETHODIMP nsTreeBoxObject::GetRowHeight(PRInt32* aRowHeight) { + *aRowHeight = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->GetRowHeight(_retval); + return body->GetRowHeight(aRowHeight); return NS_OK; } NS_IMETHODIMP nsTreeBoxObject::GetRowWidth(PRInt32 *aRowWidth) { + *aRowWidth = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) return body->GetRowWidth(aRowWidth); return NS_OK; } -NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(PRInt32 *_retval) +NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(PRInt32 *aFirstVisibleRow) { + *aFirstVisibleRow = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->GetFirstVisibleRow(_retval); + return body->GetFirstVisibleRow(aFirstVisibleRow); return NS_OK; } -NS_IMETHODIMP nsTreeBoxObject::GetLastVisibleRow(PRInt32 *_retval) +NS_IMETHODIMP nsTreeBoxObject::GetLastVisibleRow(PRInt32 *aLastVisibleRow) { + *aLastVisibleRow = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->GetLastVisibleRow(_retval); + return body->GetLastVisibleRow(aLastVisibleRow); return NS_OK; } NS_IMETHODIMP nsTreeBoxObject::GetHorizontalPosition(PRInt32 *aHorizontalPosition) { + *aHorizontalPosition = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) return body->GetHorizontalPosition(aHorizontalPosition); return NS_OK; } -NS_IMETHODIMP nsTreeBoxObject::GetPageLength(PRInt32 *_retval) +NS_IMETHODIMP nsTreeBoxObject::GetPageLength(PRInt32 *aPageLength) { + *aPageLength = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->GetPageLength(_retval); + return body->GetPageLength(aPageLength); return NS_OK; } @@ -406,20 +415,23 @@ NS_IMETHODIMP nsTreeBoxObject::InvalidateColumnRange(PRInt32 aStart, PRInt32 aEn return NS_OK; } -NS_IMETHODIMP nsTreeBoxObject::GetRowAt(PRInt32 x, PRInt32 y, PRInt32 *_retval) +NS_IMETHODIMP nsTreeBoxObject::GetRowAt(PRInt32 x, PRInt32 y, PRInt32 *aRow) { + *aRow = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->GetRowAt(x, y, _retval); + return body->GetRowAt(x, y, aRow); return NS_OK; } -NS_IMETHODIMP nsTreeBoxObject::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, nsITreeColumn** col, - nsACString& childElt) +NS_IMETHODIMP nsTreeBoxObject::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32 *aRow, nsITreeColumn** aCol, + nsACString& aChildElt) { + *aRow = 0; + *aCol = nsnull; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->GetCellAt(x, y, row, col, childElt); + return body->GetCellAt(aX, aY, aRow, aCol, aChildElt); return NS_OK; } @@ -427,6 +439,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetCoordsForCellItem(PRInt32 aRow, nsITreeColumn* aCol, const nsACString& aElement, PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight) { + *aX = *aY = *aWidth = *aHeight = 0; nsITreeBoxObject* body = GetTreeBody(); if (body) return body->GetCoordsForCellItem(aRow, aCol, aElement, aX, aY, aWidth, aHeight); @@ -434,11 +447,12 @@ nsTreeBoxObject::GetCoordsForCellItem(PRInt32 aRow, nsITreeColumn* aCol, const n } NS_IMETHODIMP -nsTreeBoxObject::IsCellCropped(PRInt32 aRow, nsITreeColumn* aCol, PRBool *_retval) +nsTreeBoxObject::IsCellCropped(PRInt32 aRow, nsITreeColumn* aCol, PRBool *aIsCropped) { + *aIsCropped = PR_FALSE; nsITreeBoxObject* body = GetTreeBody(); if (body) - return body->IsCellCropped(aRow, aCol, _retval); + return body->IsCellCropped(aRow, aCol, aIsCropped); return NS_OK; } diff --git a/modules/libimg/png/CHANGES b/modules/libimg/png/CHANGES index 33c494627d9f..a6e5856aa045 100644 --- a/modules/libimg/png/CHANGES +++ b/modules/libimg/png/CHANGES @@ -1480,7 +1480,7 @@ version 1.2.9beta5 [March 4, 2006] Restored scripts/makefile.elf which was inadvertently deleted. version 1.2.9beta6 [March 6, 2006] - Fixed typo (23) in configuration files. + Fixed typo (RELEASE) in configuration files. version 1.2.9beta7 [March 7, 2006] Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am @@ -1669,7 +1669,7 @@ version 1.2.15rc2 [December 21, 2006] Added scripts/makefile.nommx version 1.2.15rc3 [December 25, 2006] - Fixed shared library numbering error that was intruduced in 1.2.15beta6. + Fixed shared library numbering error that was introduced in 1.2.15beta6. version 1.2.15rc4 [December 27, 2006] Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. @@ -1897,6 +1897,7 @@ version 1.0.27 and 1.2.19 [August 18, 2007] version 1.2.20beta01 [August 19, 2007] Fixed problem with compiling pnggccrd.c on Intel-Apple platforms. + Changed png_malloc() to png_malloc_warn() in png_set_sPLT(). Added PNG_NO_ERROR_TEXT feature, with demo in contrib/pngminim Removed define PNG_WARN_UNINITIALIZED_ROW 1 /* 0: warning; 1: error */ because it caused some trouble. @@ -2010,6 +2011,27 @@ version 1.2.23rc01 [November 2, 2007] version 1.2.23 [November 6, 2007] No changes. +version 1.2.24beta01 [November 19, 2007] + Moved misplaced test for malloc failure in png_set_sPLT(). This bug was + introduced in libpng-1.2.20beta01. + Ifdef out avg_row etc from png.h and pngwrite.c when PNG_NO_WRITE_FILTER + Do not use png_ptr->free_fn and png_ptr->mem_fn in png_destroy_read_struct() + when png_ptr is NULL (Marshall Clow). + Updated handling of symbol prefixes in Makefile.am and configure.ac (Mike + Frysinger). + +version 1.2.24beta02 [November 30, 2007] + Removed a useless test and fixed incorrect test in png_set_cHRM_fixed() + (David Hill). + +version 1.2.24rc01 [December 7, 2007] + No changes. + +version 1.2.24 [December 14, 2007] + Make sure not to redefine _BSD_SOURCE in pngconf.h + Revised gather.sh and makefile.std in contrib/pngminim to avoid compiling + unused files. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/modules/libimg/png/LICENSE b/modules/libimg/png/LICENSE index 5d70f168d995..6b81b55a63ce 100644 --- a/modules/libimg/png/LICENSE +++ b/modules/libimg/png/LICENSE @@ -8,7 +8,7 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.23, November 6, 2007, are +libpng versions 1.2.6, August 15, 2004, through 1.2.24, December 14, 2007, are Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -106,4 +106,4 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -November 6, 2007 +December 14, 2007 diff --git a/modules/libimg/png/MOZCHANGES b/modules/libimg/png/MOZCHANGES index c23b797179cf..88f7ed906b77 100644 --- a/modules/libimg/png/MOZCHANGES +++ b/modules/libimg/png/MOZCHANGES @@ -1,11 +1,13 @@ Changes made to pristine png source by mozilla.org developers. -2007/11/10 -- Synced with libpng-1.2.23; Removed pnggccrd.c and pngvcrd.c; +2008/01/18 -- Synced with libpng-1.2.24 (bug #408429). + +2007/11/13 -- Synced with libpng-1.2.23; Removed pnggccrd.c and pngvcrd.c; Reduced footprint by removing error and warning text (bug #403239) -2007/10/13 -- Synced with libpng-1.2.22 (removes MMX support) (bug #386585) +2007/11/06 -- Synced with libpng-1.2.22 (removes MMX support) (bug #386585) 2007/07/27 -- Enabled cHRM and iCCP chunks for color management (bug #16769) diff --git a/modules/libimg/png/Makefile.in b/modules/libimg/png/Makefile.in index 33512c74a7f1..44f1bcfc5201 100644 --- a/modules/libimg/png/Makefile.in +++ b/modules/libimg/png/Makefile.in @@ -49,6 +49,13 @@ LIBRARY_NAME = png endif LIBXUL_LIBRARY = 1 +ifndef GNU_CC +ifeq ($(OS_ARCH),WINNT) +# FIXME: bug 413019 +OS_COMPILE_CFLAGS += -GL- +endif +endif + REQUIRES = $(ZLIB_REQUIRES) \ $(NULL) diff --git a/modules/libimg/png/README b/modules/libimg/png/README index 887fe8ee5d01..6f84c69f0d88 100644 --- a/modules/libimg/png/README +++ b/modules/libimg/png/README @@ -1,4 +1,4 @@ -README for libpng version 1.2.23 - November 6, 2007 (shared library 12.0) +README for libpng version 1.2.24 - December 14, 2007 (shared library 12.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. @@ -190,11 +190,11 @@ Files in this distribution: descrip.mms => VMS makefile for MMS or MMK makefile.std => Generic UNIX makefile (cc, creates static libpng.a) makefile.elf => Linux/ELF makefile symbol versioning, - gcc, creates libpng12.so.0.1.2.23) + gcc, creates libpng12.so.0.1.2.24) makefile.linux => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.23) + (gcc, creates libpng12.so.0.1.2.24) makefile.gcmmx => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.23, + (gcc, creates libpng12.so.0.1.2.24, uses assembler code tuned for Intel MMX platform) makefile.gcc => Generic makefile (gcc, creates static libpng.a) makefile.knr => Archaic UNIX Makefile that converts files with @@ -216,12 +216,12 @@ Files in this distribution: makefile.openbsd => OpenBSD makefile makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) makefile.sggcc => Silicon Graphics - (gcc, creates libpng12.so.0.1.2.23) + (gcc, creates libpng12.so.0.1.2.24) makefile.sunos => Sun makefile makefile.solaris => Solaris 2.X makefile - (gcc, creates libpng12.so.0.1.2.23) + (gcc, creates libpng12.so.0.1.2.24) makefile.so9 => Solaris 9 makefile - (gcc, creates libpng12.so.0.1.2.23) + (gcc, creates libpng12.so.0.1.2.24) makefile.32sunu => Sun Ultra 32-bit makefile makefile.64sunu => Sun Ultra 64-bit makefile makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc diff --git a/modules/libimg/png/libpng.txt b/modules/libimg/png/libpng.txt index 793d605c3921..5b8dc53b970b 100644 --- a/modules/libimg/png/libpng.txt +++ b/modules/libimg/png/libpng.txt @@ -1,6 +1,6 @@ libpng.txt - A description on how to use and modify libpng - libpng version 1.2.23 - November 6, 2007 + libpng version 1.2.24 - December 14, 2007 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2007 Glenn Randers-Pehrson @@ -2796,13 +2796,13 @@ application: IX. Y2K Compliance in libpng -November 6, 2007 +December 14, 2007 Since the PNG Development group is an ad-hoc body, we can't make an official declaration. This is your unofficial assurance that libpng from version 0.71 and -upward through 1.2.23 are Y2K compliant. It is my belief that earlier +upward through 1.2.24 are Y2K compliant. It is my belief that earlier versions were also Y2K compliant. Libpng only has three year fields. One is a 2-byte unsigned integer that diff --git a/modules/libimg/png/png.c b/modules/libimg/png/png.c index 74d7966cd1ac..176feebc5b10 100644 --- a/modules/libimg/png/png.c +++ b/modules/libimg/png/png.c @@ -13,7 +13,7 @@ #include "png.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef version_1_2_23 Your_png_h_is_not_version_1_2_23; +typedef version_1_2_24 Your_png_h_is_not_version_1_2_24; /* Version information for C files. This had better match the version * string defined in png.h. */ @@ -696,7 +696,7 @@ png_charp PNGAPI png_get_copyright(png_structp png_ptr) { png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) "\n libpng version 1.2.23 - November 6, 2007\n\ + return ((png_charp) "\n libpng version 1.2.24 - December 14, 2007\n\ Copyright (c) 1998-2007 Glenn Randers-Pehrson\n\ Copyright (c) 1996-1997 Andreas Dilger\n\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); diff --git a/modules/libimg/png/png.h b/modules/libimg/png/png.h index 2477818d92df..53904fa48e8b 100644 --- a/modules/libimg/png/png.h +++ b/modules/libimg/png/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.2.23 - November 6, 2007 + * libpng version 1.2.24 - December 14, 2007 * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -9,7 +9,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.2.23 - November 6, 2007: Glenn + * libpng versions 0.97, January 1998, through 1.2.24 - December 14, 2007: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: @@ -172,6 +172,9 @@ * 1.2.23beta01-05 13 10223 12.so.0.23[.0] * 1.2.23rc01 13 10223 12.so.0.23[.0] * 1.2.23 13 10223 12.so.0.23[.0] + * 1.2.24beta01-02 13 10224 12.so.0.24[.0] + * 1.2.24rc01 13 10224 12.so.0.24[.0] + * 1.2.24 13 10224 12.so.0.24[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -201,7 +204,7 @@ * If you modify libpng you may insert additional notices immediately following * this sentence. * - * libpng versions 1.2.6, August 15, 2004, through 1.2.23, November 6, 2007, are + * libpng versions 1.2.6, August 15, 2004, through 1.2.24, December 14, 2007, are * Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are * distributed according to the same disclaimer and license as libpng-1.2.5 * with the following individual added to the list of Contributing Authors: @@ -313,13 +316,13 @@ * Y2K compliance in libpng: * ========================= * - * November 6, 2007 + * December 14, 2007 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.2.23 are Y2K compliant. It is my belief that earlier + * upward through 1.2.24 are Y2K compliant. It is my belief that earlier * versions were also Y2K compliant. * * Libpng only has three year fields. One is a 2-byte unsigned integer @@ -375,9 +378,9 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.2.23" +#define PNG_LIBPNG_VER_STRING "1.2.24" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.2.23 - November 6, 2007\n" + " libpng version 1.2.24 - December 14, 2007\n" #define PNG_LIBPNG_VER_SONUM 0 #define PNG_LIBPNG_VER_DLLNUM 13 @@ -385,7 +388,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 2 -#define PNG_LIBPNG_VER_RELEASE 23 +#define PNG_LIBPNG_VER_RELEASE 24 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ @@ -413,7 +416,7 @@ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10223 /* 1.2.23 */ +#define PNG_LIBPNG_VER 10224 /* 1.2.24 */ #ifndef PNG_VERSION_INFO_ONLY /* include the compression library's header */ @@ -1203,10 +1206,12 @@ struct png_struct_def png_uint_32 row_number; /* current row in interlace pass */ png_bytep prev_row; /* buffer to save previous (unfiltered) row */ png_bytep row_buf; /* buffer to save current (unfiltered) row */ +#ifndef PNG_NO_WRITE_FILTERING png_bytep sub_row; /* buffer to save "sub" row when filtering */ png_bytep up_row; /* buffer to save "up" row when filtering */ png_bytep avg_row; /* buffer to save "avg" row when filtering */ png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ +#endif png_row_info row_info; /* used for transformation routines */ png_uint_32 idat_size; /* current IDAT size for read */ @@ -1477,7 +1482,7 @@ struct png_struct_def /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef png_structp version_1_2_23; +typedef png_structp version_1_2_24; typedef png_struct FAR * FAR * png_structpp; diff --git a/modules/libimg/png/pngconf.h b/modules/libimg/png/pngconf.h index 842a02c81af8..66ad51ef41e2 100644 --- a/modules/libimg/png/pngconf.h +++ b/modules/libimg/png/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.2.23 - November 6, 2007 + * libpng version 1.2.24 - December 14, 2007 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -325,7 +325,7 @@ /* If you encounter a compiler error here, see the explanation * near the end of INSTALL. */ - __png.h__ already includes setjmp.h; + __pngconf.h__ already includes setjmp.h; __dont__ include it again.; # endif # endif /* __linux__ */ @@ -335,7 +335,9 @@ # ifdef __linux__ # ifdef PNG_SAVE_BSD_SOURCE -# define _BSD_SOURCE +# ifndef _BSD_SOURCE +# define _BSD_SOURCE +# endif # undef PNG_SAVE_BSD_SOURCE # endif # endif /* __linux__ */ diff --git a/modules/libimg/png/pngerror.c b/modules/libimg/png/pngerror.c index 9f6b90dd6ae6..b364fc00af4f 100644 --- a/modules/libimg/png/pngerror.c +++ b/modules/libimg/png/pngerror.c @@ -1,7 +1,7 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.2.22 [November 6, 2007] + * Last changed in libpng 1.2.22 [October 13, 2007] * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/modules/libimg/png/pngpread.c b/modules/libimg/png/pngpread.c index 583a8960d118..30da457ce7c0 100644 --- a/modules/libimg/png/pngpread.c +++ b/modules/libimg/png/pngpread.c @@ -1,7 +1,7 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.2.22 [November 6, 2007] + * Last changed in libpng 1.2.23 [November 6, 2007] * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/modules/libimg/png/pngread.c b/modules/libimg/png/pngread.c index 05e19e9a6ad4..837674fcc8d5 100644 --- a/modules/libimg/png/pngread.c +++ b/modules/libimg/png/pngread.c @@ -1,7 +1,7 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.2.20 September 7, 2007 + * Last changed in libpng 1.2.24 December 14, 2007 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -1239,13 +1239,19 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_structp png_ptr = NULL; png_infop info_ptr = NULL, end_info_ptr = NULL; #ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn; - png_voidp mem_ptr; + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; #endif png_debug(1, "in png_destroy_read_struct\n"); if (png_ptr_ptr != NULL) + { png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } if (info_ptr_ptr != NULL) info_ptr = *info_ptr_ptr; @@ -1253,11 +1259,6 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, if (end_info_ptr_ptr != NULL) end_info_ptr = *end_info_ptr_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; - mem_ptr = png_ptr->mem_ptr; -#endif - png_read_destroy(png_ptr, info_ptr, end_info_ptr); if (info_ptr != NULL) diff --git a/modules/libimg/png/pngrtran.c b/modules/libimg/png/pngrtran.c index 1a428faf8a65..cda392154e59 100644 --- a/modules/libimg/png/pngrtran.c +++ b/modules/libimg/png/pngrtran.c @@ -1,7 +1,7 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.2.22 [November 6, 2007] + * Last changed in libpng 1.2.22 [October 13, 2007] * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/modules/libimg/png/pngrutil.c b/modules/libimg/png/pngrutil.c index 50dc84034364..25aa9e975072 100644 --- a/modules/libimg/png/pngrutil.c +++ b/modules/libimg/png/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.2.22 [November 6, 2007] + * Last changed in libpng 1.2.23 [November 6, 2007] * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/modules/libimg/png/pngset.c b/modules/libimg/png/pngset.c index dbe9c34f64d3..6920a4f7e825 100644 --- a/modules/libimg/png/pngset.c +++ b/modules/libimg/png/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.2.22 [November 6, 2007] + * Last changed in libpng 1.2.24 [December 14, 2007] * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -115,25 +115,14 @@ png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, "Ignoring attempt to set negative chromaticity value"); return; } -#ifdef PNG_FLOATING_POINT_SUPPORTED - if (white_x > (double) PNG_UINT_31_MAX || - white_y > (double) PNG_UINT_31_MAX || - red_x > (double) PNG_UINT_31_MAX || - red_y > (double) PNG_UINT_31_MAX || - green_x > (double) PNG_UINT_31_MAX || - green_y > (double) PNG_UINT_31_MAX || - blue_x > (double) PNG_UINT_31_MAX || - blue_y > (double) PNG_UINT_31_MAX) -#else - if (white_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L) -#endif + if (white_x > (png_fixed_point) PNG_UINT_31_MAX || + white_y > (png_fixed_point) PNG_UINT_31_MAX || + red_x > (png_fixed_point) PNG_UINT_31_MAX || + red_y > (png_fixed_point) PNG_UINT_31_MAX || + green_x > (png_fixed_point) PNG_UINT_31_MAX || + green_y > (png_fixed_point) PNG_UINT_31_MAX || + blue_x > (png_fixed_point) PNG_UINT_31_MAX || + blue_y > (png_fixed_point) PNG_UINT_31_MAX ) { png_warning(png_ptr, "Ignoring attempt to set chromaticity value exceeding 21474.83"); @@ -1000,13 +989,9 @@ png_set_sPLT(png_structp png_ptr, png_warning(png_ptr, "Out of memory while processing sPLT chunk"); } - /* TODO: use png_malloc_warn */ png_memcpy(to->name, from->name, length); to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, from->nentries * png_sizeof(png_sPLT_entry)); - /* TODO: use png_malloc_warn */ - png_memcpy(to->entries, from->entries, - from->nentries * png_sizeof(png_sPLT_entry)); if (to->entries == NULL) { png_warning(png_ptr, @@ -1014,6 +999,8 @@ png_set_sPLT(png_structp png_ptr, png_free(png_ptr,to->name); to->name = NULL; } + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); to->nentries = from->nentries; to->depth = from->depth; } diff --git a/modules/libimg/png/pngwrite.c b/modules/libimg/png/pngwrite.c index abfb1ad7ba69..4c876fba5da4 100644 --- a/modules/libimg/png/pngwrite.c +++ b/modules/libimg/png/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.2.15 January 5, 2007 + * Last changed in libpng 1.2.24 December 14, 2007 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2007 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -1068,11 +1068,13 @@ png_write_destroy(png_structp png_ptr) /* free our memory. png_free checks NULL for us. */ png_free(png_ptr, png_ptr->zbuf); png_free(png_ptr, png_ptr->row_buf); +#ifndef PNG_NO_WRITE_FILTERING png_free(png_ptr, png_ptr->prev_row); png_free(png_ptr, png_ptr->sub_row); png_free(png_ptr, png_ptr->up_row); png_free(png_ptr, png_ptr->avg_row); png_free(png_ptr, png_ptr->paeth_row); +#endif #if defined(PNG_TIME_RFC1123_SUPPORTED) png_free(png_ptr, png_ptr->time_buffer); diff --git a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp index 37476e889021..d5ee13635f45 100644 --- a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp +++ b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp @@ -264,12 +264,12 @@ NS_IMETHODIMP nsGIFDecoder2::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR /* necko doesn't propagate the errors from ReadDataOut - take matters into our own hands. if we have at least one frame of an animated gif, then return success so we keep displaying as much as possible. */ - if (NS_SUCCEEDED(rv) && mGIFStruct.state == gif_error) { + if (mGIFStruct.state == gif_error || mGIFStruct.state == gif_oom) { PRUint32 numFrames = 0; if (mImageContainer) mImageContainer->GetNumFrames(&numFrames); - if (numFrames <= 0) - return NS_ERROR_FAILURE; + if (numFrames <= 1) + rv = NS_ERROR_FAILURE; } return rv; @@ -395,7 +395,7 @@ void nsGIFDecoder2::EndImageFrame() if (mGIFStruct.rows_remaining != mGIFStruct.height) { if (mGIFStruct.rows_remaining && mGIFStruct.images_decoded) { // Clear the remaining rows (only needed for the animation frames) - PRUint8 *rowp = mImageData + ((mGIFStruct.rows_remaining - mGIFStruct.height) * mGIFStruct.width); + PRUint8 *rowp = mImageData + ((mGIFStruct.height - mGIFStruct.rows_remaining) * mGIFStruct.width); memset(rowp, 0, mGIFStruct.rows_remaining * mGIFStruct.width); } @@ -590,6 +590,8 @@ nsGIFDecoder2::DoLzw(const PRUint8 *q) } if (oldcode == -1) { + if (code >= MAX_BITS) + return PR_FALSE; *rowp++ = suffix[code]; if (rowp == rowend) OUTPUT_ROW(); @@ -603,13 +605,13 @@ nsGIFDecoder2::DoLzw(const PRUint8 *q) *stackp++ = firstchar; code = oldcode; - if (stackp == stack + MAX_BITS) + if (stackp >= stack + MAX_BITS) return PR_FALSE; } while (code >= clear_code) { - if (code == prefix[code]) + if ((code >= MAX_BITS) || (code == prefix[code])) return PR_FALSE; *stackp++ = suffix[code]; diff --git a/modules/libpr0n/decoders/icon/os2/Makefile.in b/modules/libpr0n/decoders/icon/os2/Makefile.in index 6921dc57a668..20d8d0a91340 100644 --- a/modules/libpr0n/decoders/icon/os2/Makefile.in +++ b/modules/libpr0n/decoders/icon/os2/Makefile.in @@ -51,6 +51,7 @@ REQUIRES = xpcom \ necko \ mimetype \ exthandler \ + widget \ $(NULL) CPPSRCS = nsIconChannel.cpp diff --git a/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp b/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp index 5dbd61257fd5..baf469840ba5 100644 --- a/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp +++ b/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp @@ -1,6 +1,6 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 sts=2 et cin: */ +/* ***** 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 @@ -48,9 +48,10 @@ #include "nsMemory.h" #include "nsNetUtil.h" #include "nsInt64.h" -#include "nsIFile.h" +#include "nsILocalFile.h" #include "nsIFileURL.h" #include "nsDirectoryServiceDefs.h" +#include "nsIRwsService.h" #define INCL_PM #include @@ -68,12 +69,24 @@ #define UNALIGNEDBPR(cx,bits) (( ((cx)*(bits)) + 7) / 8) // native icon functions -HPOINTER GetFileIcon(nsCString& file, PRBool fExists); +static HPOINTER GetIcon(nsCString& file, PRBool fExists, + PRBool fMini, PRBool *fWpsIcon); +static void DestroyIcon(HPOINTER hIcon, PRBool fWpsIcon); -void ConvertColorBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf); -void ShrinkColorBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf); -void ConvertMaskBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf); -void ShrinkMaskBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf); +void ConvertColorBitMap(PRUint8 *inBuf, PBITMAPINFO2 pBMInfo, + PRUint8 *outBuf, PRBool fShrink); +void ConvertMaskBitMap(PRUint8 *inBuf, PBITMAPINFO2 pBMInfo, + PRUint8 *outBuf, PRBool fShrink); + +//------------------------------------------------------------------------ + +// reduces overhead by preventing calls to nsRws when it isn't present +#ifdef MOZ_PHOENIX // should work fine in Firefox +static PRBool sUseRws = PR_TRUE; +#else // XXX causes duplicate attachment icons and crashes in apps that + // use mailnews, so off now for other apps +static PRBool sUseRws = PR_FALSE; +#endif //------------------------------------------------------------------------ // nsIconChannel methods @@ -237,26 +250,23 @@ nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile ** aLocalFile, PRUint32 * //------------------------------------------------------------------------ -// retrieves a native icon with 16, 256, or 16M colors and converts it -// to 24-bit BGR with 1-bit alpha data (BGR_A1 format); Note: this -// implementation ignores the file's MIME-type because using it virtually -// guarantees we'll end up with an inappropriate icon (i.e. an .exe icon) +// retrieves a native icon with 16, 256, or 16M colors and converts it to cairo +// format; Note: this implementation ignores the file's MIME-type because +// using it virtually guarantees we'll end up with an inappropriate icon (i.e. +// an .exe icon) -nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBlocking) +nsresult nsIconChannel::MakeInputStream(nsIInputStream **_retval, + PRBool nonBlocking) { -#ifdef MOZ_CAIRO_GFX - // This needs to be changed to match the format changes described in - // nsIconDecoder.h. For cairo, the icon format is ARGB (A in highest - // bits, B in lowest bits, based on platform endianness). - return NS_ERROR_NOT_IMPLEMENTED; -#endif // get some details about this icon nsCOMPtr localFile; PRUint32 desiredImageSize; nsXPIDLCString contentType; nsCAutoString filePath; - nsresult rv = ExtractIconInfoFromUrl(getter_AddRefs(localFile), &desiredImageSize, contentType, filePath); + nsresult rv = ExtractIconInfoFromUrl(getter_AddRefs(localFile), + &desiredImageSize, contentType, + filePath); NS_ENSURE_SUCCESS(rv, rv); // if the file exists, get its path @@ -266,15 +276,17 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc localFile->Exists(&fileExists); } - // get the icon from the file - HPOINTER hIcon = GetFileIcon(filePath, fileExists); + // get the file's icon from either the WPS or PM + PRBool fWpsIcon = PR_FALSE; + HPOINTER hIcon = GetIcon(filePath, fileExists, + desiredImageSize <= 16, &fWpsIcon); if (hIcon == NULLHANDLE) return NS_ERROR_FAILURE; // get the color & mask bitmaps used by the icon POINTERINFO IconInfo; if (!WinQueryPointerInfo(hIcon, &IconInfo)) { - WinFreeFileIcon( hIcon); + DestroyIcon(hIcon, fWpsIcon); return NS_ERROR_FAILURE; } @@ -285,9 +297,9 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc if (IconInfo.hbmMiniPointer) { IconInfo.hbmColor = IconInfo.hbmMiniColor; IconInfo.hbmPointer = IconInfo.hbmMiniPointer; - } - else + } else { fShrink = TRUE; + } } // various resources to be allocated @@ -297,12 +309,12 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc HDC hdc = 0; HPS hps = 0; - // using this dummy do{...}while(0) "loop" guarantees resources will - // be deallocated, eliminates the need for nesting, and generally makes + // using this dummy do{...}while(0) "loop" guarantees that resources will + // be deallocated, but eliminates the need for nesting, and generally makes // testing for & dealing with errors pretty painless (just 'break') do { rv = NS_ERROR_FAILURE; - + // get the details for the color bitmap; if there isn't one // or this is 1-bit color, exit BITMAPINFOHEADER2 BMHeader; @@ -311,98 +323,90 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc !GpiQueryBitmapInfoHeader(IconInfo.hbmColor, &BMHeader) || BMHeader.cBitCount == 1) break; - + // alloc space for the color bitmap's info, including its color table PRUint32 cbBMInfo = sizeof(BITMAPINFO2) + (sizeof(RGB2) * 255); pBMInfo = (PBITMAPINFO2)nsMemory::Alloc(cbBMInfo); if (!pBMInfo) break; - + // alloc space for the color bitmap data - PRUint32 cbInRow = ALIGNEDBPR( BMHeader.cx, BMHeader.cBitCount); + PRUint32 cbInRow = ALIGNEDBPR(BMHeader.cx, BMHeader.cBitCount); PRUint32 cbInBuf = cbInRow * BMHeader.cy; pInBuf = (PRUint8*)nsMemory::Alloc(cbInBuf); if (!pInBuf) break; - memset( pInBuf, 0, cbInBuf); - - // alloc space for the 24-bit BGR_A1 bitmap we're creating - PRUint32 cxOut = (fShrink ? BMHeader.cx / 2 : BMHeader.cx); - PRUint32 cyOut = (fShrink ? BMHeader.cy / 2 : BMHeader.cy); - PRUint32 cbColor = ALIGNEDBPR( cxOut, 24) * cyOut; - PRUint32 cbMask = ALIGNEDBPR( cxOut, 1) * cyOut; - PRUint32 cbOutBuf = 3 + cbColor + cbMask; + memset(pInBuf, 0, cbInBuf); + + // alloc space for the BGRA32 bitmap we're creating + PRUint32 cxOut = fShrink ? BMHeader.cx / 2 : BMHeader.cx; + PRUint32 cyOut = fShrink ? BMHeader.cy / 2 : BMHeader.cy; + PRUint32 cbOutBuf = 2 + ALIGNEDBPR(cxOut, 32) * cyOut; pOutBuf = (PRUint8*)nsMemory::Alloc(cbOutBuf); if (!pOutBuf) break; - memset( pOutBuf, 0, cbOutBuf); - + memset(pOutBuf, 0, cbOutBuf); + // create a DC and PS - DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - hdc = DevOpenDC( (HAB)0, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE); + DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + hdc = DevOpenDC((HAB)0, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE); if (!hdc) break; - + SIZEL sizel = {0,0}; hps = GpiCreatePS((HAB)0, hdc, &sizel, GPIA_ASSOC | PU_PELS | GPIT_MICRO); if (!hps) break; - + // get the color bits - memset( pBMInfo, 0, cbBMInfo); - *((PBITMAPINFOHEADER2)pBMInfo ) = BMHeader; + memset(pBMInfo, 0, cbBMInfo); + *((PBITMAPINFOHEADER2)pBMInfo) = BMHeader; GpiSetBitmap(hps, IconInfo.hbmColor); - if (GpiQueryBitmapBits( hps, 0L, (LONG)BMHeader.cy, - (BYTE*)pInBuf, pBMInfo) <= 0) + if (GpiQueryBitmapBits(hps, 0L, (LONG)BMHeader.cy, + (BYTE*)pInBuf, pBMInfo) <= 0) break; - - // The first 2 bytes are the width & height of the icon in pixels + + // The first 2 bytes are the width & height of the icon in pixels, + // the remaining bytes are BGRA32 (B in first byte, A in last) PRUint8* outPtr = pOutBuf; *outPtr++ = (PRUint8)cxOut; *outPtr++ = (PRUint8)cyOut; - // then the number of bits of alpha per pixel - *outPtr++ = (PRUint8)1; - + // convert the color bitmap pBMInfo->cbImage = cbInBuf; - if (fShrink) - ShrinkColorBitMap( pInBuf, pBMInfo, outPtr); - else - ConvertColorBitMap( pInBuf, pBMInfo, outPtr); - outPtr += cbColor; - - // now we need to tack on the alpha data - + ConvertColorBitMap(pInBuf, pBMInfo, outPtr, fShrink); + + // now we need to tack on the alpha data, so jump back to the first + // pixel in the output buffer + outPtr = pOutBuf+2; + // Get the mask info BMHeader.cbFix = sizeof(BMHeader); if (!GpiQueryBitmapInfoHeader(IconInfo.hbmPointer, &BMHeader)) break; - + // if the existing input buffer isn't large enough, reallocate it - cbInRow = ALIGNEDBPR( BMHeader.cx, BMHeader.cBitCount); + cbInRow = ALIGNEDBPR(BMHeader.cx, BMHeader.cBitCount); if ((cbInRow * BMHeader.cy) > cbInBuf) // Need more for mask { cbInBuf = cbInRow * BMHeader.cy; nsMemory::Free(pInBuf); - pInBuf = (PRUint8*)nsMemory::Alloc(cbInBuf); - memset( pInBuf, 0, cbInBuf); + pInBuf = (PRUint8*)nsMemory::Alloc(cbInBuf); + memset(pInBuf, 0, cbInBuf); } - + // get the mask/alpha bits - memset( pBMInfo, 0, cbBMInfo); - *((PBITMAPINFOHEADER2)pBMInfo ) = BMHeader; + memset(pBMInfo, 0, cbBMInfo); + *((PBITMAPINFOHEADER2)pBMInfo) = BMHeader; GpiSetBitmap(hps, IconInfo.hbmPointer); - if (GpiQueryBitmapBits( hps, 0L, (LONG)BMHeader.cy, - (BYTE*)pInBuf, pBMInfo) <= 0) + if (GpiQueryBitmapBits(hps, 0L, (LONG)BMHeader.cy, + (BYTE*)pInBuf, pBMInfo) <= 0) break; // convert the mask/alpha bitmap pBMInfo->cbImage = cbInBuf; - if (fShrink) - ShrinkMaskBitMap( pInBuf, pBMInfo, outPtr); - else - ConvertMaskBitMap( pInBuf, pBMInfo, outPtr); - + ConvertMaskBitMap(pInBuf, pBMInfo, outPtr, fShrink); + // create a pipe nsCOMPtr inStream; nsCOMPtr outStream; @@ -410,26 +414,25 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc cbOutBuf, cbOutBuf, nonBlocking); if (NS_FAILED(rv)) break; - + // put our data into the pipe PRUint32 written; - rv = outStream->Write( reinterpret_cast(pOutBuf), - cbOutBuf, &written); + rv = outStream->Write(reinterpret_cast(pOutBuf), + cbOutBuf, &written); if (NS_FAILED(rv)) break; - + // success! so addref the pipe NS_ADDREF(*_retval = inStream); - } while (0); // free all the resources we allocated if (pOutBuf) - nsMemory::Free( pOutBuf); + nsMemory::Free(pOutBuf); if (pInBuf) - nsMemory::Free( pInBuf); + nsMemory::Free(pInBuf); if (pBMInfo) - nsMemory::Free( pBMInfo); + nsMemory::Free(pBMInfo); if (hps) { GpiAssociate(hps, NULLHANDLE); GpiDestroyPS(hps); @@ -437,42 +440,68 @@ nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBloc if (hdc) DevCloseDC(hdc); if (hIcon) - WinFreeFileIcon( hIcon); + DestroyIcon(hIcon, fWpsIcon); return rv; } //------------------------------------------------------------------------ -// if the file exists, get its icon; if it doesn't, create a dummy file -// with the same extension, then use whatever icon the system assigns it +// get the file's icon from either the WPS or PM -HPOINTER GetFileIcon(nsCString& file, PRBool fExists) +static HPOINTER GetIcon(nsCString& file, PRBool fExists, + PRBool fMini, PRBool *fWpsIcon) { + HPOINTER hRtn = 0; + *fWpsIcon = PR_FALSE; - if (fExists) - return WinLoadFileIcon( file.get(), FALSE); - - nsCOMPtr dummyPath; - if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, - getter_AddRefs(dummyPath)))) + if (file.IsEmpty()) return 0; + // if RWS is enabled, try to get the icon from the WPS + if (sUseRws) { + nsCOMPtr rwsSvc(do_GetService("@mozilla.org/rwsos2;1")); + if (!rwsSvc) + sUseRws = PR_FALSE; + else { + if (fExists) { + rwsSvc->IconFromPath(file.get(), PR_FALSE, fMini, (PRUint32*)&hRtn); + } else { + const char *ptr = file.get(); + if (*ptr == '.') + ptr++; + rwsSvc->IconFromExtension(ptr, fMini, (PRUint32*)&hRtn); + } + } + } + + // if we got an icon from the WPS, set the flag & exit + if (hRtn) { + *fWpsIcon = PR_TRUE; + return hRtn; + } + + // if the file exists already, get its icon + if (fExists) + return WinLoadFileIcon(file.get(), FALSE); + + // otherwise, create a temporary file with the correct extension, + // then retrieve whatever icon PM assigns it if (file.First() == '.') file.Insert("moztmp", 0); - if (NS_FAILED(dummyPath->AppendNative(file))) + nsCOMPtr tempPath; + if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempPath))) || + NS_FAILED(tempPath->AppendNative(file))) return 0; - nsCAutoString dummyFile; - dummyPath->GetNativePath(dummyFile); - - HPOINTER hRtn = 0; - FILE* fp = fopen( dummyFile.get(), "wb+"); + nsCAutoString pathStr; + tempPath->GetNativePath(pathStr); + FILE* fp = fopen(pathStr.get(), "wb+"); if (fp) { - fclose( fp); - hRtn = WinLoadFileIcon(dummyFile.get(), FALSE); - remove(dummyFile.get()); + fclose(fp); + hRtn = WinLoadFileIcon(pathStr.get(), FALSE); + remove(pathStr.get()); } return hRtn; @@ -480,177 +509,103 @@ HPOINTER GetFileIcon(nsCString& file, PRBool fExists) //------------------------------------------------------------------------ -// converts 16, 256, & 16M color bitmaps to 24-bit BGR format; since the -// scanlines in OS/2 bitmaps run bottom-to-top, it starts at the end of the -// input buffer & works its way back; Note: no output padding is needed -// for any expected color-depth or size; only 4-bit, 20x20 icons contain -// input padding that has to be ignored - -void ConvertColorBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf) +static void DestroyIcon(HPOINTER hIcon, PRBool fWpsIcon) { + if (fWpsIcon) + WinDestroyPointer(hIcon); + else + WinFreeFileIcon(hIcon); - PRUint32 bprIn = ALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); - PRUint8* pIn = inBuf + (pBMInfo->cy - 1) * bprIn; - PRUint8* pOut = outBuf; - PRGB2 pColorTable = &pBMInfo->argbColor[0]; + return; +} + +//------------------------------------------------------------------------ + +// converts 16, 256, & 16M color bitmaps to BGRA32 format; the alpha +// channel byte is left open & will be filled in by ConvertMaskBitMap(); +// since the scanlines in OS/2 bitmaps run bottom-to-top, it starts at the +// end of the input buffer & works its way back; Note: only 4-bit, 20x20 +// icons contain input padding that has to be ignored + +void ConvertColorBitMap(PRUint8 *inBuf, PBITMAPINFO2 pBMInfo, + PRUint8 *outBuf, PRBool fShrink) +{ + PRUint32 next = fShrink ? 2 : 1; + PRUint32 bprIn = ALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); + PRUint8 *pIn = inBuf + (pBMInfo->cy - 1) * bprIn; + PRUint8 *pOut = outBuf; + PRGB2 pColorTable = &pBMInfo->argbColor[0]; if (pBMInfo->cBitCount == 4) { PRUint32 ubprIn = UNALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); PRUint32 padIn = bprIn - ubprIn; - for (PRUint32 row = pBMInfo->cy; row > 0; row--) { + for (PRUint32 row = pBMInfo->cy; row > 0; row -= next) { for (PRUint32 ndx = 0; ndx < ubprIn; ndx++, pIn++) { - pOut = 3 + (PRUint8*)memcpy( pOut, &pColorTable[FIRSTPEL(*pIn)], 3); - pOut = 3 + (PRUint8*)memcpy( pOut, &pColorTable[SECONDPEL(*pIn)], 3); + pOut = 4 + (PRUint8*)memcpy(pOut, &pColorTable[FIRSTPEL(*pIn)], 3); + if (!fShrink) { + pOut = 4 + (PRUint8*)memcpy(pOut, &pColorTable[SECONDPEL(*pIn)], 3); + } } - pIn -= (2 * bprIn) - padIn; + pIn -= ((next + 1) * bprIn) - padIn; } - } - else - if (pBMInfo->cBitCount == 8) { - for (PRUint32 row = pBMInfo->cy; row > 0; row--) { - for (PRUint32 ndx = 0; ndx < bprIn; ndx++, pIn++) { - pOut = 3 + (PRUint8*)memcpy( pOut, &pColorTable[*pIn], 3); + } else if (pBMInfo->cBitCount == 8) { + for (PRUint32 row = pBMInfo->cy; row > 0; row -= next) { + for (PRUint32 ndx = 0; ndx < bprIn; ndx += next, pIn += next) { + pOut = 4 + (PRUint8*)memcpy(pOut, &pColorTable[*pIn], 3); } - pIn -= 2 * bprIn; + pIn -= (next + 1) * bprIn; + } + } else if (pBMInfo->cBitCount == 24) { + PRUint32 next3 = next * 3; + for (PRUint32 row = pBMInfo->cy; row > 0; row -= next) { + for (PRUint32 ndx = 0; ndx < bprIn; ndx += next3, pIn += next3) { + pOut = 4 + (PRUint8*)memcpy(pOut, pIn, 3); + } + pIn -= (next + 1) * bprIn; } } - else - if (pBMInfo->cBitCount == 24) { - for (PRUint32 row = pBMInfo->cy; row > 0; row--) { - pOut = bprIn + (PRUint8*)memcpy( pOut, pIn, bprIn); - pIn -= bprIn; - } - } - - return; } //------------------------------------------------------------------------ -// similar to ConvertColorBitMap() except that it skips every other pixel -// horizontally, & every other line vertically; this is the exact reverse -// of what GPI does when it expands a mini-icon to full-size +// converts an icon's AND mask into 8-bit alpha data and stores it in the +// high-order bytes of the BGRA32 bitmap created by ConvertColorBitMap(); +// the AND mask is the 2nd half of a pair of bitmaps & the scanlines run +// bottom-to-top - starting at the end and working back to the midpoint +// converts the entire bitmap; since each row is dword-aligned, 16, 20, +// and 40-pixel icons all have padding bits at the end of every row that +// must be skipped over -void ShrinkColorBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf) +void ConvertMaskBitMap(PRUint8 *inBuf, PBITMAPINFO2 pBMInfo, + PRUint8 *outBuf, PRBool fShrink) { + PRUint32 next = (fShrink ? 2 : 1); + PRUint32 bprIn = ALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); + PRUint32 padIn = bprIn - UNALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); + PRUint8 *pIn = inBuf + (pBMInfo->cy - 1) * bprIn; + PRUint8 *pOut = outBuf + 3; - PRUint32 bprIn = ALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); - PRUint8* pIn = inBuf + (pBMInfo->cy - 1) * bprIn; - PRUint8* pOut = outBuf; - PRGB2 pColorTable = &pBMInfo->argbColor[0]; + // for each row or every other row + for (PRUint32 row = pBMInfo->cy/2; row > 0; row -= next) { - if (pBMInfo->cBitCount == 4) { - PRUint32 ubprIn = UNALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); - PRUint32 padIn = bprIn - ubprIn; - - for (PRUint32 row = pBMInfo->cy; row > 0; row -= 2) { - for (PRUint32 ndx = 0; ndx < ubprIn; ndx++, pIn++) { - pOut = 3 + (PRUint8*)memcpy( pOut, &pColorTable[FIRSTPEL(*pIn)], 3); - } - pIn -= (3 * bprIn) - padIn; - } - } - else - if (pBMInfo->cBitCount == 8) { - for (PRUint32 row = pBMInfo->cy; row > 0; row -= 2) { - for (PRUint32 ndx = 0; ndx < bprIn; ndx += 2, pIn += 2) { - pOut = 3 + (PRUint8*)memcpy( pOut, &pColorTable[*pIn], 3); - } - pIn -= 3 * bprIn; - } - } - else - if (pBMInfo->cBitCount == 24) { - for (PRUint32 row = pBMInfo->cy; row > 0; row -= 2) { - for (PRUint32 ndx = 0; ndx < bprIn; ndx += 6, pIn += 3) { - pOut = 3 + (PRUint8*)memcpy( pOut, pIn, 3); - pIn += 3; - } - pIn -= 3 * bprIn; - } - } - - return; -} - -//------------------------------------------------------------------------ - -// converts an icon's AND mask into 1-bit alpha data; since the AND mask -// is the 2nd half of a pair of bitmaps & the scanlines run bottom-to-top, -// starting at the end & working back to the midpoint converts the entire -// bitmap; Note: because the input is already padded to a dword boundary, -// the output will be padded automatically - -void ConvertMaskBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf) -{ - - PRUint32 bprIn = ALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); - PRUint32 lprIn = bprIn / 4; - PRUint32* pOut32 = (PRUint32*)outBuf; - PRUint32* pIn32 = (PRUint32*)(inBuf + (pBMInfo->cy - 1) * bprIn); - - for (PRUint32 row = pBMInfo->cy/2; row > 0; row--) { - for (PRUint32 ndx = 0; ndx < lprIn; ndx++) { - *pOut32++ = ~(*pIn32++); - } - pIn32 -= 2 * lprIn; - } - - return; -} - -//------------------------------------------------------------------------ - -// similar to ConvertMaskBitMap() except that it skips every other pixel -// horizontally, & every other line vertically; Note: this is the only -// one of these functions that may have to add padding to its output - -void ShrinkMaskBitMap(PRUint8* inBuf, PBITMAPINFO2 pBMInfo, PRUint8* outBuf) -{ - - PRUint32 bprIn = ALIGNEDBPR(pBMInfo->cx, pBMInfo->cBitCount); - PRUint32 padOut = (bprIn / 2) & 3; - PRUint8* pOut = outBuf; - PRUint8* pIn = inBuf + (pBMInfo->cy - 1) * bprIn; - - // for every other row - for (PRUint32 row = pBMInfo->cy/2; row > 0; row -= 2) { - PRUint8 dest = 0; - PRUint8 destMask = 0x80; - - // for every byte in the row - for (PRUint32 ndx = 0; ndx < bprIn; ndx++) { - PRUint8 src = ~(*pIn++); + // for all of the non-padding bits in the row + for (PRUint32 bits = pBMInfo->cx; bits; pIn++) { + PRUint8 src = ~(*pIn); PRUint8 srcMask = 0x80; - // for every other bit in the current byte - for (PRUint32 bitNdx = 0; bitNdx < 8; bitNdx += 2) { - if (src & srcMask) - dest |= destMask; - srcMask >>= 2; - destMask >>= 1; - } - - // if we've filled an output byte from two input bytes, save it - if (!destMask) { - *pOut++ = dest; - dest = 0; - destMask = 0x80; + // for each bit or every other bit in the current byte + for ( ; srcMask && bits; srcMask >>= next, bits -= next, pOut += 4) { + if (src & srcMask) { + *pOut = 0xff; + } } } - // after we've processed every input byte in the row, - // does the output row need padding? - if (padOut) { - memset( pOut, 0, padOut); - pOut += padOut; - } - - pIn -= 3 * bprIn; + // if the row just completed had padding, pIn won't be pointing + // at the first byte in the next row; padIn compensates for this + pIn -= ((next + 1) * bprIn) - padIn; } - - return; } //------------------------------------------------------------------------ diff --git a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp index b1242b42367c..247889e3319c 100644 --- a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp +++ b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp @@ -85,14 +85,15 @@ nsJPEGDecoder::nsJPEGDecoder() { mState = JPEG_HEADER; mReading = PR_TRUE; + mError = NS_OK; mBytesToSkip = 0; memset(&mInfo, 0, sizeof(jpeg_decompress_struct)); memset(&mSourceMgr, 0, sizeof(mSourceMgr)); mInfo.client_data = (void*)this; - mBuffer = nsnull; - mBufferLen = mBufferSize = 0; + mSegment = nsnull; + mSegmentLen = 0; mBackBuffer = nsnull; mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0; @@ -107,7 +108,6 @@ nsJPEGDecoder::nsJPEGDecoder() nsJPEGDecoder::~nsJPEGDecoder() { - PR_FREEIF(mBuffer); PR_FREEIF(mBackBuffer); if (mTransform) cmsDeleteTransform(mTransform); @@ -196,14 +196,17 @@ NS_IMETHODIMP nsJPEGDecoder::Close() PR_LOG(gJPEGlog, PR_LOG_DEBUG, ("[this=%p] nsJPEGDecoder::Close\n", this)); - if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) - NS_WARNING("Never finished decoding the JPEG."); - /* Step 8: Release JPEG decompression object */ mInfo.src = nsnull; jpeg_destroy_decompress(&mInfo); + if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) { + NS_WARNING("Never finished decoding the JPEG."); + /* Tell imgLoader that image decoding has failed */ + return NS_ERROR_FAILURE; + } + return NS_OK; } @@ -214,58 +217,57 @@ NS_IMETHODIMP nsJPEGDecoder::Flush() PRUint32 ret; if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER && mState != JPEG_ERROR) - return this->WriteFrom(nsnull, 0, &ret); + return this->ProcessData(nsnull, 0, &ret); return NS_OK; } -/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */ -NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval) +static NS_METHOD ReadDataOut(nsIInputStream* in, + void* closure, + const char* fromRawSegment, + PRUint32 toOffset, + PRUint32 count, + PRUint32 *writeCount) { - LOG_SCOPE_WITH_PARAM(gJPEGlog, "nsJPEGDecoder::WriteFrom", "count", count); + nsJPEGDecoder *decoder = static_cast(closure); + nsresult rv = decoder->ProcessData(fromRawSegment, count, writeCount); + if (NS_FAILED(rv)) { + /* Tell imgLoader that image decoding has failed */ + decoder->mError = rv; + *writeCount = 0; + } - PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, - ("nsJPEGDecoder::WriteFrom(decoder = %p) {\n" - " image container %s; %u bytes to be added", - this, - mImage ? "exists" : "does not exist", - count)); + return NS_OK; +} - if (inStr) { - if (!mBuffer) { - mBuffer = (JOCTET *)PR_Malloc(count); - if (!mBuffer) { - mState = JPEG_ERROR; - PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, - ("} (out of memory allocating buffer)")); - return NS_ERROR_OUT_OF_MEMORY; - } - mBufferSize = count; - } else if (count > mBufferSize) { - JOCTET *buf = (JOCTET *)PR_Realloc(mBuffer, count); - if (!buf) { - mState = JPEG_ERROR; - PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, - ("} (out of memory resizing buffer)")); - return NS_ERROR_OUT_OF_MEMORY; - } - mBuffer = buf; - mBufferSize = count; - } - nsresult rv = inStr->Read((char*)mBuffer, count, &mBufferLen); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsJPEGDecoder::WriteFrom -- inStr->Read failed"); +/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */ +NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *writeCount) +{ + NS_ENSURE_ARG_POINTER(inStr); + NS_ENSURE_ARG_POINTER(writeCount); - PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, - ("nsJPEGDecoder::WriteFrom(): decoder %p got %u bytes, read %u from the stream (buffer size %u)", - this, - count, - mBufferLen, - mBufferSize)); - - *_retval = mBufferLen; + /* necko doesn't propagate the errors from ReadDataOut */ + nsresult rv = inStr->ReadSegments(ReadDataOut, this, count, writeCount); + if (NS_FAILED(mError)) { + /* Tell imgLoader that image decoding has failed */ + rv = NS_ERROR_FAILURE; + } - nsresult result = mImage->AddRestoreData((char *) mBuffer, count); + return rv; +} + +//****************************************************************************** +nsresult nsJPEGDecoder::ProcessData(const char *data, PRUint32 count, PRUint32 *writeCount) +{ + LOG_SCOPE_WITH_PARAM(gJPEGlog, "nsJPEGDecoder::ProcessData", "count", count); + + mSegment = (const JOCTET *)data; + mSegmentLen = count; + *writeCount = count; + + if (data && count) { + nsresult result = mImage->AddRestoreData((char *) data, count); if (NS_FAILED(result)) { mState = JPEG_ERROR; @@ -301,12 +303,12 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR } PR_LOG(gJPEGlog, PR_LOG_DEBUG, - ("[this=%p] nsJPEGDecoder::WriteFrom -- processing JPEG data\n", this)); + ("[this=%p] nsJPEGDecoder::ProcessData -- processing JPEG data\n", this)); switch (mState) { case JPEG_HEADER: { - LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_HEADER case"); + LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::ProcessData -- entering JPEG_HEADER case"); /* Step 3: read file parameters with jpeg_read_header() */ if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED) { @@ -494,7 +496,7 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR mImage->AppendFrame(mFrame); PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, - (" JPEGDecoderAccounting: nsJPEGDecoder::WriteFrom -- created image frame with %ux%u pixels", + (" JPEGDecoderAccounting: nsJPEGDecoder::ProcessData -- created image frame with %ux%u pixels", mInfo.image_width, mInfo.image_height)); } @@ -504,7 +506,7 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR case JPEG_START_DECOMPRESS: { - LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_START_DECOMPRESS case"); + LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::ProcessData -- entering JPEG_START_DECOMPRESS case"); /* Step 4: set parameters for decompression */ /* FIXME -- Should reset dct_method and dither mode @@ -535,7 +537,7 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR { if (mState == JPEG_DECOMPRESS_SEQUENTIAL) { - LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- JPEG_DECOMPRESS_SEQUENTIAL case"); + LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::ProcessData -- JPEG_DECOMPRESS_SEQUENTIAL case"); if (!OutputScanlines()) { PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, @@ -553,7 +555,7 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR { if (mState == JPEG_DECOMPRESS_PROGRESSIVE) { - LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- JPEG_DECOMPRESS_PROGRESSIVE case"); + LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::ProcessData -- JPEG_DECOMPRESS_PROGRESSIVE case"); int status; do { @@ -618,7 +620,7 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR { nsresult result; - LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_DONE case"); + LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::ProcessData -- entering JPEG_DONE case"); /* Step 7: Finish decompression */ @@ -643,13 +645,13 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR } case JPEG_SINK_NON_JPEG_TRAILER: PR_LOG(gJPEGlog, PR_LOG_DEBUG, - ("[this=%p] nsJPEGDecoder::WriteFrom -- entering JPEG_SINK_NON_JPEG_TRAILER case\n", this)); + ("[this=%p] nsJPEGDecoder::ProcessData -- entering JPEG_SINK_NON_JPEG_TRAILER case\n", this)); break; case JPEG_ERROR: PR_LOG(gJPEGlog, PR_LOG_DEBUG, - ("[this=%p] nsJPEGDecoder::WriteFrom -- entering JPEG_ERROR case\n", this)); + ("[this=%p] nsJPEGDecoder::ProcessData -- entering JPEG_ERROR case\n", this)); break; } @@ -674,7 +676,6 @@ nsJPEGDecoder::OutputScanlines() mFrame->GetImageData(&imageData, &imageDataLength); while ((mInfo.output_scanline < mInfo.output_height)) { - /* Request one scanline. Returns 0 or 1 scanlines. */ PRUint32 *imageRow = ((PRUint32*)imageData) + (mInfo.output_scanline * mInfo.output_width); @@ -686,6 +687,7 @@ nsJPEGDecoder::OutputScanlines() sampleRow += mInfo.output_width; } + /* Request one scanline. Returns 0 or 1 scanlines. */ if (jpeg_read_scanlines(&mInfo, &sampleRow, 1) != 1) { rv = PR_FALSE; /* suspend */ break; @@ -878,13 +880,13 @@ fill_input_buffer (j_decompress_ptr jd) nsJPEGDecoder *decoder = (nsJPEGDecoder *)(jd->client_data); if (decoder->mReading) { - unsigned char *new_buffer = (unsigned char *)decoder->mBuffer; - PRUint32 new_buflen = decoder->mBufferLen; + const JOCTET *new_buffer = decoder->mSegment; + PRUint32 new_buflen = decoder->mSegmentLen; if (!new_buffer || new_buflen == 0) return PR_FALSE; /* suspend */ - decoder->mBufferLen = 0; + decoder->mSegmentLen = 0; if (decoder->mBytesToSkip) { if (decoder->mBytesToSkip < new_buflen) { @@ -908,7 +910,7 @@ fill_input_buffer (j_decompress_ptr jd) return PR_TRUE; } - if (src->next_input_byte != decoder->mBuffer) { + if (src->next_input_byte != decoder->mSegment) { /* Backtrack data has been permanently consumed. */ decoder->mBackBufferUnreadLen = 0; decoder->mBackBufferLen = 0; @@ -919,37 +921,24 @@ fill_input_buffer (j_decompress_ptr jd) /* Make sure backtrack buffer is big enough to hold new data. */ if (decoder->mBackBufferSize < new_backtrack_buflen) { - - - /* Round up to multiple of 256 bytes. */ - const PRUint32 roundup_buflen = ((new_backtrack_buflen + 255) >> 8) << 8; - - if (decoder->mBackBuffer) { - JOCTET *buf = (JOCTET *)PR_REALLOC(decoder->mBackBuffer, roundup_buflen); - /* Check for OOM */ - if (!buf) { - decoder->mInfo.err->msg_code = JERR_OUT_OF_MEMORY; - my_error_exit((j_common_ptr)(&decoder->mInfo)); - } - decoder->mBackBuffer = buf; - } else { - decoder->mBackBuffer = (JOCTET*)PR_MALLOC(roundup_buflen); - /* Check for OOM */ - if (!decoder->mBackBuffer) { - decoder->mInfo.err->msg_code = JERR_OUT_OF_MEMORY; - my_error_exit((j_common_ptr)(&decoder->mInfo)); - } - } - - decoder->mBackBufferSize = (size_t)roundup_buflen; - - /* Check for malformed MARKER segment lengths. */ + /* Check for malformed MARKER segment lengths, before allocating space for it */ if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) { my_error_exit((j_common_ptr)(&decoder->mInfo)); } + + /* Round up to multiple of 256 bytes. */ + const size_t roundup_buflen = ((new_backtrack_buflen + 255) >> 8) << 8; + JOCTET *buf = (JOCTET *)PR_REALLOC(decoder->mBackBuffer, roundup_buflen); + /* Check for OOM */ + if (!buf) { + decoder->mInfo.err->msg_code = JERR_OUT_OF_MEMORY; + my_error_exit((j_common_ptr)(&decoder->mInfo)); + } + decoder->mBackBuffer = buf; + decoder->mBackBufferSize = roundup_buflen; } - /* Copy remainder of netlib buffer into backtrack buffer. */ + /* Copy remainder of netlib segment into backtrack buffer. */ memmove(decoder->mBackBuffer + decoder->mBackBufferLen, src->next_input_byte, src->bytes_in_buffer); diff --git a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h index dae586fe4c5e..0f285e1d0eab 100644 --- a/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h +++ b/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.h @@ -91,6 +91,8 @@ public: nsJPEGDecoder(); virtual ~nsJPEGDecoder(); + nsresult ProcessData(const char *data, PRUint32 count, PRUint32 *writeCount); + protected: PRBool OutputScanlines(); @@ -105,12 +107,12 @@ public: struct jpeg_source_mgr mSourceMgr; decoder_error_mgr mErr; jstate mState; + nsresult mError; PRUint32 mBytesToSkip; - JOCTET *mBuffer; - PRUint32 mBufferLen; // amount of data currently in mBuffer - PRUint32 mBufferSize; // size in bytes what mBuffer was created with + const JOCTET *mSegment; // The current segment we are decoding from + PRUint32 mSegmentLen; // amount of data in mSegment JOCTET *mBackBuffer; PRUint32 mBackBufferLen; // Offset of end of active backtrack data @@ -124,10 +126,6 @@ public: cmsHTRANSFORM mTransform; PRPackedBool mReading; - -private: - - nsresult AddToTmpAccumulateBuffer(JOCTET *src, PRUint32 len); }; #endif // nsJPEGDecoder_h__ diff --git a/modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp b/modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp index 71c89999141a..77120f53a401 100644 --- a/modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp +++ b/modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp @@ -266,7 +266,7 @@ NS_IMETHODIMP nsJPEGEncoder::ReadSegments(nsWriteSegmentFun aWriter, void *aClos aCount = maxCount; nsresult rv = aWriter(this, aClosure, reinterpret_cast(mImageBuffer), - 0, aCount, _retval); + mImageBufferReadPoint, aCount, _retval); if (NS_SUCCEEDED(rv)) { NS_ASSERTION(*_retval <= aCount, "bad write count"); mImageBufferReadPoint += *_retval; diff --git a/modules/libpr0n/encoders/png/nsPNGEncoder.cpp b/modules/libpr0n/encoders/png/nsPNGEncoder.cpp index 83dc98403220..3b5cd56930f3 100644 --- a/modules/libpr0n/encoders/png/nsPNGEncoder.cpp +++ b/modules/libpr0n/encoders/png/nsPNGEncoder.cpp @@ -45,12 +45,6 @@ #include "nsString.h" #include "nsStreamUtils.h" -// Bug 308126 - AIX defines jmpbuf in sys/context.h which conflicts with the -// definition of jmpbuf in the png.h header file. -#ifdef jmpbuf -#undef jmpbuf -#endif - // Input streams that do not implement nsIAsyncInputStream should be threadsafe // so that they may be used with nsIInputStreamPump and nsIInputStreamChannel, // which read such a stream on a background thread. @@ -336,10 +330,12 @@ nsPNGEncoder::ParseOptions(const nsAString& aOptions, PRUint32* offsetX, PRUint32* offsetY) { - char* token; - char* options = nsCRT::strdup(PromiseFlatCString(NS_ConvertUTF16toUTF8(aOptions)).get()); + // Make a copy of aOptions, because strtok() will modify it. + nsCAutoString optionsCopy; + optionsCopy.Assign(NS_ConvertUTF16toUTF8(aOptions)); + char* options = optionsCopy.BeginWriting(); - while ((token = nsCRT::strtok(options, ";", &options))) { + while (char* token = nsCRT::strtok(options, ";", &options)) { // If there's an '=' character, split the token around it. char* equals = token, *value = nsnull; while(*equals != '=' && *equals) { ++equals; } @@ -488,7 +484,7 @@ NS_IMETHODIMP nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter, aCount = maxCount; nsresult rv = aWriter(this, aClosure, reinterpret_cast(mImageBuffer), - 0, aCount, _retval); + mImageBufferReadPoint, aCount, _retval); if (NS_SUCCEEDED(rv)) { NS_ASSERTION(*_retval <= aCount, "bad write count"); mImageBufferReadPoint += *_retval; diff --git a/modules/libpr0n/src/imgContainer.cpp b/modules/libpr0n/src/imgContainer.cpp index 864d4224e9af..863c67a50258 100644 --- a/modules/libpr0n/src/imgContainer.cpp +++ b/modules/libpr0n/src/imgContainer.cpp @@ -124,6 +124,9 @@ NS_IMETHODIMP imgContainer::Init(PRInt32 aWidth, PRInt32 aHeight, mSize.SizeTo(aWidth, aHeight); + // As we are reloading it means we are no longer in 'discarded' state + mDiscarded = PR_FALSE; + mObserver = do_GetWeakReference(aObserver); return NS_OK; @@ -566,14 +569,9 @@ NS_IMETHODIMP imgContainer::AddRestoreData(const char *aBuffer, PRUint32 aCount) { NS_ASSERTION(aBuffer, "imgContainer::AddRestoreData() called with null aBuffer"); - if (!DiscardingEnabled ()) + if (!mDiscardable) return NS_OK; - if (!mDiscardable) { - NS_WARNING ("imgContainer::AddRestoreData() can only be called if SetDiscardable is called first"); - return NS_ERROR_FAILURE; - } - if (mRestoreDataDone) { /* We are being called from the decoder while the data is being restored * (i.e. we were fully loaded once, then we discarded the image data, then @@ -622,8 +620,8 @@ get_header_str (char *buf, char *data, PRSize data_len) /* void restoreDataDone(); */ NS_IMETHODIMP imgContainer::RestoreDataDone (void) { - - if (!DiscardingEnabled ()) + // If image is not discardable, don't start discard timer + if (!mDiscardable) return NS_OK; if (mRestoreDataDone) @@ -654,17 +652,12 @@ NS_IMETHODIMP imgContainer::RestoreDataDone (void) /* void notify(in nsITimer timer); */ NS_IMETHODIMP imgContainer::Notify(nsITimer *timer) { - nsresult result; - - result = RestoreDiscardedData(); - if (NS_FAILED (result)) - return result; + nsresult rv = RestoreDiscardedData(); + NS_ENSURE_SUCCESS(rv, rv); // This should never happen since the timer is only set up in StartAnimation() // after mAnim is checked to exist. - NS_ASSERTION(mAnim, "imgContainer::Notify() called but mAnim is null"); - if (!mAnim) - return NS_ERROR_UNEXPECTED; + NS_ENSURE_TRUE(mAnim, NS_ERROR_UNEXPECTED); NS_ASSERTION(mAnim->timer == timer, "imgContainer::Notify() called with incorrect timer"); @@ -1104,41 +1097,46 @@ PRBool imgContainer::CopyFrameImage(gfxIImageFrame *aSrcFrame, } //****************************************************************************** +/* + * aSrc is the current frame being drawn, + * aDst is the composition frame where the current frame is drawn into. + * aSrcRect is the size of the current frame, and the position of that frame + * in the composition frame. + */ nsresult imgContainer::DrawFrameTo(gfxIImageFrame *aSrc, gfxIImageFrame *aDst, - nsIntRect& aDstRect) + nsIntRect& aSrcRect) { - if (!aSrc || !aDst) - return NS_ERROR_NOT_INITIALIZED; + NS_ENSURE_ARG_POINTER(aSrc); + NS_ENSURE_ARG_POINTER(aDst); - nsIntRect srcRect, dstRect; - aSrc->GetRect(srcRect); + nsIntRect dstRect; aDst->GetRect(dstRect); + // According to both AGIF and APNG specs, offsets are unsigned + if (aSrcRect.x < 0 || aSrcRect.y < 0) { + NS_WARNING("imgContainer::DrawFrameTo: negative offsets not allowed"); + return NS_ERROR_FAILURE; + } + // Outside the destination frame, skip it + if ((aSrcRect.x > dstRect.width) || (aSrcRect.y > dstRect.height)) { + return NS_OK; + } gfx_format format; aSrc->GetFormat(&format); if (format == gfxIFormats::PAL || format == gfxIFormats::PAL_A1) { - // Outside the destination frame, skip it - if ((aDstRect.x > dstRect.width) || (aDstRect.y > dstRect.height)) { - return NS_OK; - } // Larger than the destination frame, clip it - PRInt32 width = (PRUint32)aDstRect.width; - PRInt32 height = (PRUint32)aDstRect.height; - if (aDstRect.x + aDstRect.width > dstRect.width) { - width = dstRect.width - aDstRect.x; - } - if (aDstRect.y + aDstRect.height > dstRect.height) { - height = dstRect.height - aDstRect.y; - } - // dstRect must fully fit within destination image - NS_ASSERTION((aDstRect.x >= 0) && (aDstRect.y >= 0) && - (aDstRect.x + width <= dstRect.width) && - (aDstRect.y + height <= dstRect.height), - "imgContainer::DrawFrameTo: Invalid aDstRect"); + PRInt32 width = PR_MIN(aSrcRect.width, dstRect.width - aSrcRect.x); + PRInt32 height = PR_MIN(aSrcRect.height, dstRect.height - aSrcRect.y); - // dstRect size may be smaller than source, but not larger - NS_ASSERTION((width <= srcRect.width) && (height <= srcRect.height), + // The clipped image must now fully fit within destination image frame + NS_ASSERTION((aSrcRect.x >= 0) && (aSrcRect.y >= 0) && + (aSrcRect.x + width <= dstRect.width) && + (aSrcRect.y + height <= dstRect.height), + "imgContainer::DrawFrameTo: Invalid aSrcRect"); + + // clipped image size may be smaller than source, but not larger + NS_ASSERTION((width <= aSrcRect.width) && (height <= aSrcRect.height), "imgContainer::DrawFrameTo: source must be smaller than dest"); if (NS_FAILED(aDst->LockImageData())) @@ -1158,14 +1156,14 @@ nsresult imgContainer::DrawFrameTo(gfxIImageFrame *aSrc, } // Skip to the right offset - dstPixels += aDstRect.x + (aDstRect.y * dstRect.width); + dstPixels += aSrcRect.x + (aSrcRect.y * dstRect.width); if (format == gfxIFormats::PAL) { for (PRInt32 r = height; r > 0; --r) { for (PRInt32 c = 0; c < width; c++) { dstPixels[c] = colormap[srcPixels[c]]; } // Go to the next row in the source resp. destination image - srcPixels += srcRect.width; + srcPixels += aSrcRect.width; dstPixels += dstRect.width; } } else { @@ -1177,7 +1175,7 @@ nsresult imgContainer::DrawFrameTo(gfxIImageFrame *aSrc, dstPixels[c] = color; } // Go to the next row in the source resp. destination image - srcPixels += srcRect.width; + srcPixels += aSrcRect.width; dstPixels += dstRect.width; } } @@ -1194,26 +1192,18 @@ nsresult imgContainer::DrawFrameTo(gfxIImageFrame *aSrc, dstImg->GetSurface(getter_AddRefs(dstSurf)); gfxContext dst(dstSurf); + dst.Translate(gfxPoint(aSrcRect.x, aSrcRect.y)); + dst.Rectangle(gfxRect(0, 0, aSrcRect.width, aSrcRect.height), PR_TRUE); // first clear the surface if the blend flag says so PRInt32 blendMethod; aSrc->GetBlendMethod(&blendMethod); - gfxContext::GraphicsOperator defaultOperator = dst.CurrentOperator(); if (blendMethod == imgIContainer::kBlendSource) { + gfxContext::GraphicsOperator defaultOperator = dst.CurrentOperator(); dst.SetOperator(gfxContext::OPERATOR_CLEAR); - dst.Rectangle(gfxRect(aDstRect.x, aDstRect.y, aDstRect.width, aDstRect.height)); dst.Fill(); + dst.SetOperator(defaultOperator); } - - dst.NewPath(); - dst.SetOperator(defaultOperator); - // We don't use PixelSnappedRectangleAndSetPattern because if - // these coords aren't already pixel aligned, we've lost - // before we've even begun. - dst.Translate(gfxPoint(aDstRect.x, aDstRect.y)); - dst.Rectangle(gfxRect(0, 0, aDstRect.width, aDstRect.height), PR_TRUE); - dst.Scale(double(aDstRect.width) / srcRect.width, - double(aDstRect.height) / srcRect.height); dst.SetSource(srcSurf); dst.Paint(); @@ -1269,21 +1259,20 @@ static int get_discard_timer_ms (void) { /* FIXME: don't hardcode this */ - return 45000; /* 45 seconds */ + return 15000; /* 15 seconds */ } void imgContainer::sDiscardTimerCallback(nsITimer *aTimer, void *aClosure) { imgContainer *self = (imgContainer *) aClosure; - int old_frame_count; NS_ASSERTION(aTimer == self->mDiscardTimer, "imgContainer::DiscardTimerCallback() got a callback for an unknown timer"); self->mDiscardTimer = nsnull; - old_frame_count = self->mFrames.Count(); + int old_frame_count = self->mFrames.Count(); if (self->mAnim) { delete self->mAnim; @@ -1313,12 +1302,10 @@ imgContainer::ResetDiscardTimer (void) if (!mDiscardTimer) { mDiscardTimer = do_CreateInstance("@mozilla.org/timer;1"); - - if (!mDiscardTimer) - return NS_ERROR_OUT_OF_MEMORY; + NS_ENSURE_TRUE(mDiscardTimer, NS_ERROR_OUT_OF_MEMORY); } else { - if (NS_FAILED(mDiscardTimer->Cancel())) - return NS_ERROR_FAILURE; + nsresult rv = mDiscardTimer->Cancel(); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); } return mDiscardTimer->InitWithFuncCallback(sDiscardTimerCallback, @@ -1330,31 +1317,26 @@ imgContainer::ResetDiscardTimer (void) nsresult imgContainer::RestoreDiscardedData(void) { - nsresult result; - int num_expected_frames; - - if (!mDiscardable) + // mRestoreDataDone = PR_TRUE means that we want to timeout and then discard the image frames + // So, we only need to restore, if mRestoreDataDone is true, and then only when the frames are discarded... + if (!mRestoreDataDone) return NS_OK; - result = ResetDiscardTimer(); - if (NS_FAILED (result)) - return result; + // Reset timer, as the frames are accessed + nsresult rv = ResetDiscardTimer(); + NS_ENSURE_SUCCESS(rv, rv); if (!mDiscarded) return NS_OK; - num_expected_frames = mNumFrames; - - result = ReloadImages (); - if (NS_FAILED (result)) { - PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, - ("CompressedImageAccounting: imgContainer::RestoreDiscardedData() for container %p failed to ReloadImages()", - this)); - return result; - } + int num_expected_frames = mNumFrames; + // To prevent that ReloadImages is called multiple times, reset the flag before reloading mDiscarded = PR_FALSE; + rv = ReloadImages(); + NS_ENSURE_SUCCESS(rv, rv); + NS_ASSERTION (mNumFrames == mFrames.Count(), "number of restored image frames doesn't match"); NS_ASSERTION (num_expected_frames == mNumFrames, @@ -1495,9 +1477,6 @@ ContainerLoader::FrameChanged(imgIContainer *aContainer, gfxIImageFrame *aFrame, nsresult imgContainer::ReloadImages(void) { - nsresult result = NS_ERROR_FAILURE; - nsCOMPtr stream; - NS_ASSERTION(!mRestoreData.IsEmpty(), "imgContainer::ReloadImages(): mRestoreData should not be empty"); NS_ASSERTION(mRestoreDataDone, @@ -1528,7 +1507,7 @@ imgContainer::ReloadImages(void) loader->SetImage(this); - result = decoder->Init(loader); + nsresult result = decoder->Init(loader); if (NS_FAILED(result)) { PR_LOG(gCompressedImageAccountingLog, PR_LOG_WARNING, ("CompressedImageAccounting: imgContainer::ReloadImages() image container %p " @@ -1538,6 +1517,7 @@ imgContainer::ReloadImages(void) return result; } + nsCOMPtr stream; result = NS_NewByteInputStream(getter_AddRefs(stream), mRestoreData.Elements(), mRestoreData.Length(), NS_ASSIGNMENT_DEPEND); NS_ENSURE_SUCCESS(result, result); @@ -1558,8 +1538,8 @@ imgContainer::ReloadImages(void) result = decoder->WriteFrom(stream, mRestoreData.Length(), &written); NS_ENSURE_SUCCESS(result, result); - if (NS_FAILED(decoder->Flush())) - return result; + result = decoder->Flush(); + NS_ENSURE_SUCCESS(result, result); result = decoder->Close(); NS_ENSURE_SUCCESS(result, result); diff --git a/modules/libpr0n/src/imgTools.cpp b/modules/libpr0n/src/imgTools.cpp index dd822a11d2b9..d22b549c9371 100644 --- a/modules/libpr0n/src/imgTools.cpp +++ b/modules/libpr0n/src/imgTools.cpp @@ -233,7 +233,8 @@ NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr, NS_ENSURE_SUCCESS(rv, rv); rv = decoder->WriteFrom(aInStr, length, &written); NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(written == length, "decoder didn't eat all of its vegetables"); + if (written != length) + NS_WARNING("decoder didn't eat all of its vegetables"); rv = decoder->Flush(); NS_ENSURE_SUCCESS(rv, rv); rv = decoder->Close(); @@ -287,6 +288,8 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, nsCOMPtr frame; rv = aContainer->GetFrameAt(0, getter_AddRefs(frame)); NS_ENSURE_SUCCESS(rv, rv); + if (!frame) + return NS_ERROR_NOT_AVAILABLE; PRInt32 w,h; frame->GetWidth(&w); diff --git a/modules/libpr0n/test/unit/bug413512.ico b/modules/libpr0n/test/unit/bug413512.ico new file mode 100644 index 000000000000..b2db0429f66e Binary files /dev/null and b/modules/libpr0n/test/unit/bug413512.ico differ diff --git a/modules/libpr0n/test/unit/image1png16x16.jpg b/modules/libpr0n/test/unit/image1png16x16.jpg index cfb749ab47a3..c8088f43aa26 100644 Binary files a/modules/libpr0n/test/unit/image1png16x16.jpg and b/modules/libpr0n/test/unit/image1png16x16.jpg differ diff --git a/modules/libpr0n/test/unit/image2jpg16x16-win.png b/modules/libpr0n/test/unit/image2jpg16x16-win.png new file mode 100755 index 000000000000..a821626c0752 Binary files /dev/null and b/modules/libpr0n/test/unit/image2jpg16x16-win.png differ diff --git a/modules/libpr0n/test/unit/image2jpg16x16.png b/modules/libpr0n/test/unit/image2jpg16x16.png index c3a4aee61667..0418a096d9e5 100644 Binary files a/modules/libpr0n/test/unit/image2jpg16x16.png and b/modules/libpr0n/test/unit/image2jpg16x16.png differ diff --git a/modules/libpr0n/test/unit/image2jpg32x32-win.png b/modules/libpr0n/test/unit/image2jpg32x32-win.png new file mode 100755 index 000000000000..4d84df26a0b2 Binary files /dev/null and b/modules/libpr0n/test/unit/image2jpg32x32-win.png differ diff --git a/modules/libpr0n/test/unit/image3ico32x32.png b/modules/libpr0n/test/unit/image3ico32x32.png index 421b9ce30d13..cffe0e9bee09 100644 Binary files a/modules/libpr0n/test/unit/image3ico32x32.png and b/modules/libpr0n/test/unit/image3ico32x32.png differ diff --git a/modules/libpr0n/test/unit/test_imgtools.js b/modules/libpr0n/test/unit/test_imgtools.js index 39c7620a80b7..46782b9dd6fa 100644 --- a/modules/libpr0n/test/unit/test_imgtools.js +++ b/modules/libpr0n/test/unit/test_imgtools.js @@ -92,10 +92,29 @@ function compareArrays(aArray1, aArray2) { } -function run_test() { +/* + * checkExpectedError + * + * Checks to see if a thrown error was expected or not, and if it + * matches the expected value. + */ +function checkExpectedError (aExpectedError, aActualError) { + if (aExpectedError) { + if (!aActualError) + throw "Didn't throw as expected (" + aExpectedError + ")"; -// Disable test for now. -return; + if (!aExpectedError.test(aActualError)) + throw "Threw (" + aActualError + "), not (" + aExpectedError; + + // We got the expected error, so make a note in the test log. + dump("...that error was expected.\n\n"); + } else if (aActualError) { + throw "Threw unexpected error: " + aActualError; + } +} + + +function run_test() { try { @@ -103,6 +122,7 @@ try { /* ========== 0 ========== */ var testnum = 0; var testdesc = "imgITools setup"; +var err = null; var imgTools = Cc["@mozilla.org/image/tools;1"]. getService(Ci.imgITools); @@ -110,6 +130,13 @@ var imgTools = Cc["@mozilla.org/image/tools;1"]. if (!imgTools) throw "Couldn't get imgITools service" +// Ugh, this is an ugly hack. The pixel values we get in Windows are sometimes +// +/- 1 value compared to other platforms, so we need to compare against a +// different set of reference images. nsIXULRuntime.OS doesn't seem to be +// available in xpcshell, so we'll use this as a kludgy way to figure out if +// we're running on Windows. +var isWindows = ("@mozilla.org/windows-registry-key;1" in Cc); + /* ========== 1 ========== */ testnum++; @@ -197,12 +224,13 @@ do_check_eq(container.height, 32); testnum++; testdesc = "test encoding a scaled PNG"; +if (!isWindows) { // we'll reuse the container from the previous test istream = imgTools.encodeScaledImage(container, "image/png", 16, 16); encodedBytes = streamToArray(istream); // Get bytes for exected result -refName = "image2jpg16x16.png"; +refName = isWindows ? "image2jpg16x16-win.png" : "image2jpg16x16.png"; refFile = do_get_file(TESTDIR + refName); istream = getFileInputStream(refFile); do_check_eq(istream.available(), 948); @@ -210,18 +238,20 @@ referenceBytes = streamToArray(istream); // compare the encoder's output to the reference file. compareArrays(encodedBytes, referenceBytes); +} /* ========== 6 ========== */ testnum++; testdesc = "test encoding an unscaled PNG"; +if (!isWindows) { // we'll reuse the container from the previous test istream = imgTools.encodeImage(container, "image/png"); encodedBytes = streamToArray(istream); // Get bytes for exected result -refName = "image2jpg32x32.png"; +refName = isWindows ? "image2jpg32x32-win.png" : "image2jpg32x32.png"; refFile = do_get_file(TESTDIR + refName); istream = getFileInputStream(refFile); do_check_eq(istream.available(), 3105); @@ -229,6 +259,7 @@ referenceBytes = streamToArray(istream); // compare the encoder's output to the reference file. compareArrays(encodedBytes, referenceBytes); +} /* ========== 7 ========== */ @@ -265,7 +296,7 @@ encodedBytes = streamToArray(istream); refName = "image3ico32x32.png"; refFile = do_get_file(TESTDIR + refName); istream = getFileInputStream(refFile); -do_check_eq(istream.available(), 2281); +do_check_eq(istream.available(), 2372); referenceBytes = streamToArray(istream); // compare the encoder's output to the reference file. @@ -290,6 +321,35 @@ referenceBytes = streamToArray(istream); // compare the encoder's output to the reference file. compareArrays(encodedBytes, referenceBytes); + + + +/* ========== bug 413512 ========== */ +testnum = 413512; +testdesc = "test decoding bad favicon (bug 413512)"; + +imgName = "bug413512.ico"; +inMimeType = "image/x-icon"; +imgFile = do_get_file(TESTDIR + imgName); + +istream = getFileInputStream(imgFile); +do_check_eq(istream.available(), 17759); + +// You'd think the decoder would fail, but it doesn't. The decoders use +// stream->ReadSegments with a callback, and buffered streams ignore errors +// from the callback. :-( See bug 413595. +outParam = { value: null }; +imgTools.decodeImageData(istream, inMimeType, outParam); +container = outParam.value; + +try { + istream = imgTools.encodeImage(container, "image/png"); +} catch (e) { + err = e; +} +checkExpectedError(/NS_ERROR_NOT_AVAILABLE/, err); + + /* ========== end ========== */ } catch (e) { diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index f18f934c10eb..98a104b89566 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -71,6 +71,14 @@ pref("browser.cache.offline.enable", true); // offline cache capacity in kilobytes pref("browser.cache.offline.capacity", 10240); +// offline apps should be limited to this much data in global storage +// (in kilobytes) +pref("offline-apps.quota.max", 204800); + +// the user should be warned if offline app disk usage exceeds this amount +// (in kilobytes) +pref("offline-apps.quota.warn", 51200); + // Fastback caching - if this pref is negative, then we calculate the number // of content viewers to cache based on the amount of available memory. pref("browser.sessionhistory.max_total_viewers", -1); @@ -626,6 +634,7 @@ pref("network.IDN.whitelist.fi", true); pref("network.IDN.whitelist.gr", true); pref("network.IDN.whitelist.hu", true); pref("network.IDN.whitelist.io", true); +pref("network.IDN.whitelist.ir", true); pref("network.IDN.whitelist.is", true); pref("network.IDN.whitelist.jp", true); pref("network.IDN.whitelist.kr", true); @@ -2135,8 +2144,6 @@ pref("font.alias-list", "sans,sans-serif,serif,monospace"); // ar -#ifdef MOZ_ENABLE_XFT - pref("font.name.serif.el", "serif"); pref("font.name.sans-serif.el", "sans-serif"); pref("font.name.monospace.el", "monospace"); @@ -2194,67 +2201,6 @@ pref("font.name.sans-serif.zh-HK", "sans-serif"); pref("font.name.monospace.zh-HK", "monospace"); // zh-TW -# MOZ_ENABLE_XFT -#else -pref("font.name.serif.el", "misc-fixed-iso8859-7"); -pref("font.name.sans-serif.el", "misc-fixed-iso8859-7"); -pref("font.name.monospace.el", "misc-fixed-iso8859-7"); - -pref("font.name.serif.he", "misc-fixed-iso8859-8"); -pref("font.name.sans-serif.he", "misc-fixed-iso8859-8"); -pref("font.name.monospace.he", "misc-fixed-iso8859-8"); - -pref("font.name.serif.ja", "jis-fixed-jisx0208.1983-0"); -pref("font.name.sans-serif.ja", "jis-fixed-jisx0208.1983-0"); -pref("font.name.monospace.ja", "jis-fixed-jisx0208.1983-0"); - -pref("font.name.serif.ko", "daewoo-mincho-ksc5601.1987-0"); -pref("font.name.sans-serif.ko", "daewoo-mincho-ksc5601.1987-0"); -pref("font.name.monospace.ko", "daewoo-mincho-ksc5601.1987-0"); - -// th - -pref("font.name.serif.tr", "adobe-times-iso8859-9"); -pref("font.name.sans-serif.tr", "adobe-helvetica-iso8859-9"); -pref("font.name.monospace.tr", "adobe-courier-iso8859-9"); - -pref("font.name.serif.x-baltic", "b&h-lucidux serif-iso8859-4"); -pref("font.name.sans-serif.x-baltic", "b&h-lucidux sans-iso8859-4"); -pref("font.name.monospace.x-baltic", "b&h-lucidux mono-iso8859-4"); - -pref("font.name.serif.x-central-euro", "adobe-times-iso8859-2"); -pref("font.name.sans-serif.x-central-euro", "adobe-helvetica-iso8859-2"); -pref("font.name.monospace.x-central-euro", "adobe-courier-iso8859-2"); - -pref("font.name.serif.x-cyrillic", "cronyx-times-koi8-r"); -pref("font.name.sans-serif.x-cyrillic", "cronyx-helvetica-koi8-r"); -pref("font.name.monospace.x-cyrillic", "cronyx-courier-koi8-r"); - -pref("font.name.serif.x-unicode", "adobe-times-iso8859-1"); -pref("font.name.sans-serif.x-unicode", "adobe-helvetica-iso8859-1"); -pref("font.name.monospace.x-unicode", "adobe-courier-iso8859-1"); - -pref("font.name.serif.x-user-def", "adobe-times-iso8859-1"); -pref("font.name.sans-serif.x-user-def", "adobe-helvetica-iso8859-1"); -pref("font.name.monospace.x-user-def", "adobe-courier-iso8859-1"); - -pref("font.name.serif.x-western", "adobe-times-iso8859-1"); -pref("font.name.sans-serif.x-western", "adobe-helvetica-iso8859-1"); -pref("font.name.monospace.x-western", "adobe-courier-iso8859-1"); - -pref("font.name.serif.zh-CN", "isas-song ti-gb2312.1980-0"); -pref("font.name.sans-serif.zh-CN", "isas-song ti-gb2312.1980-0"); -pref("font.name.monospace.zh-CN", "isas-song ti-gb2312.1980-0"); - -// ming_uni.ttf (HKSCS-2001) -// http://www.info.gov.hk/digital21/eng/hkscs/download/uime.exe -pref("font.name.serif.zh-HK", "-arphic-Ming for ISO10646-big5hkscs-0"); -pref("font.name.sans-serif.zh-HK", "-arphic-Ming for ISO10646-big5hkscs-0"); -pref("font.name.monospace.zh-HK", "-arphic-Ming for ISO10646-big5hkscs-0"); - -// zh-TW -# MOZ_ENABLE_XFT -#endif pref("font.default.ar", "sans-serif"); pref("font.size.variable.ar", 16); diff --git a/modules/plugin/base/src/nsJSNPRuntime.cpp b/modules/plugin/base/src/nsJSNPRuntime.cpp index e348e22da4af..64c30c79abf6 100644 --- a/modules/plugin/base/src/nsJSNPRuntime.cpp +++ b/modules/plugin/base/src/nsJSNPRuntime.cpp @@ -42,6 +42,7 @@ #include "nsPIPluginInstancePeer.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptContext.h" +#include "nsDOMJSUtils.h" #include "nsIDocument.h" #include "nsIJSRuntimeService.h" #include "nsIJSContextStack.h" @@ -265,7 +266,22 @@ struct AutoCXPusher ~AutoCXPusher() { - sContextStack->Pop(nsnull); + JSContext *cx = nsnull; + sContextStack->Pop(&cx); + + JSContext *currentCx = nsnull; + sContextStack->Peek(¤tCx); + + if (!currentCx) { + // No JS is running, tell the context we're done executing + // script. + + nsIScriptContext *scx = GetScriptContextFromJSContext(cx); + + if (scx) { + scx->ScriptEvaluated(PR_TRUE); + } + } OnWrapperDestroyed(); } diff --git a/netwerk/cache/public/nsIOfflineCacheSession.idl b/netwerk/cache/public/nsIOfflineCacheSession.idl index d98403ff9e2e..397ab7f579c4 100644 --- a/netwerk/cache/public/nsIOfflineCacheSession.idl +++ b/netwerk/cache/public/nsIOfflineCacheSession.idl @@ -80,14 +80,15 @@ interface nsIOfflineCacheSession : nsISupports /** * Gets the list of owner URIs associated with a domain. * - * @param ownerDomain + * @param ownerAsciiDomain * The domain to query + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost * @param count * The number of uris returned * @param uris * The uris in this domain that own resources */ - void getOwnerURIs(in ACString ownerDomain, + void getOwnerURIs(in ACString ownerAsciiDomain, out unsigned long count, [array, size_is(count)]out string uris); @@ -101,37 +102,41 @@ interface nsIOfflineCacheSession : nsISupports * an entry is created with this key, it will be owned by the * domain/URI pair. * - * @param ownerDomain - * The domain that owns the resources. - * @param ownerURI - * The specific URI that owns the resources. This can be empty if - * no URI specifically owns the resources. + * @param ownerAsciiDomain + * The domain that owns the resources + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost + * @param ownerAsciiKey + * The specific key that owns the resources. You may use + * ascii encoded URI spec of the owner - nsIURI.asciiSpec. + * This can be empty if none specifically owns the resources. * @param count * The number of keys in keys. * @param keys * The keys that the domain/URI pair own. This can be empty to * clear ownership for the domain/URI pair. */ - void setOwnedKeys(in ACString ownerDomain, - in ACString ownerURI, + void setOwnedKeys(in ACString ownerAsciiDomain, + in ACString ownerAsciiKey, in unsigned long count, [array, size_is(count)]in string keys); /** * Gets the list of resources owned by a given domain/URI pair. * - * @param ownerDomain - * The domain that owns the resources. - * @param ownerURI - * The specific URI that owns the resources. This can be empty - * if no URI specifically owns the resources. + * @param ownerAsciiDomain + * The domain that owns the resources + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost + * @param ownerAsciiKey + * The specific key that owns the resources. You may use + * ascii encoded URI spec of the owner - nsIURI.asciiSpec. + * This can be empty if none specifically owns the resources. * @param count * The number of keys in keys. * @param keys * The keys that the domain/URI pair own. */ - void getOwnedKeys(in ACString ownerDomain, - in ACString ownerURI, + void getOwnedKeys(in ACString ownerAsciiDomain, + in ACString ownerAsciiKey, out unsigned long count, [array, size_is(count)]out string keys); @@ -142,16 +147,18 @@ interface nsIOfflineCacheSession : nsISupports * an entry is created with this key, it will be owned by the * domain/URI pair. * - * @param ownerDomain - * The domain that owns the resources. - * @param ownerURI - * The specific URI that owns the resources. This can be empty - * if no URI specifically owns the resources. + * @param ownerAsciiDomain + * The domain that owns the resources + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost + * @param ownerAsciiKey + * The specific key that owns the resources. You may use + * ascii encoded URI spec of the owner - nsIURI.asciiSpec. + * This can be empty if none specifically owns the resources. * @param key * The key to add. */ - void addOwnedKey(in ACString ownerDomain, - in ACString ownerURI, + void addOwnedKey(in ACString ownerAsciiDomain, + in ACString ownerAsciiKey, in ACString key); /** @@ -160,38 +167,44 @@ interface nsIOfflineCacheSession : nsISupports * If the key does not exist, an NS_ERROR_NOT_AVAILABLE exception * will be thrown. * - * @param ownerDomain - * The domain that owns the resources. - * @param ownerURI - * The specific URI that owns the resources. This can be empty - * if no URI specifically owns the resources. + * @param ownerAsciiDomain + * The domain that owns the resources + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost + * @param ownerAsciiKey + * The specific key that owns the resources. You may use + * ascii encoded URI spec of the owner - nsIURI.asciiSpec. + * This can be empty if none specifically owns the resources. * @param key The key to remove. */ - void removeOwnedKey(in ACString ownerDomain, - in ACString ownerURI, + void removeOwnedKey(in ACString ownerAsciiDomain, + in ACString ownerAsciiKey, in ACString key); /** * Checks whether a key is owned by a given domain/URI pair. * - * @param ownerDomain - * The domain that owns the resources. - * @param ownerURI - * The specific URI that owns the resources. This can be empty - * if no URI specifically owns the resources. + * @param ownerAsciiDomain + * The domain that owns the resources + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost + * @param ownerAsciiKey + * The specific key that owns the resources. You may use + * ascii encoded URI spec of the owner - nsIURI.asciiSpec. + * This can be empty if none specifically owns the resources. * @param key The key to check */ - boolean keyIsOwned(in ACString ownerDomain, - in ACString ownerURI, + boolean keyIsOwned(in ACString ownerAsciiDomain, + in ACString ownerAsciiKey, in ACString key); /** * Remove all keys owned by a domain, including keys owned by * a specific URI. * - * @param domain The domain for which keys should be removed. + * @param ownerAsciiDomain + * The domain for which keys should be removed + * !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost */ - void clearKeysOwnedByDomain(in ACString ownerDomain); + void clearKeysOwnedByDomain(in ACString ownerAsciiDomain); /** * Evict all entries that are not owned by a domain. diff --git a/netwerk/cache/src/nsCacheService.cpp b/netwerk/cache/src/nsCacheService.cpp index 3d2c5f7abb42..c2e45a9684ac 100644 --- a/netwerk/cache/src/nsCacheService.cpp +++ b/netwerk/cache/src/nsCacheService.cpp @@ -769,8 +769,8 @@ nsCacheService::EvictEntriesForClient(const char * clientID, #endif // ! NECKO_DISK_CACHE #ifdef NECKO_OFFLINE_CACHE - if (storagePolicy == nsICache::STORE_ANYWHERE || - storagePolicy == nsICache::STORE_OFFLINE) { + // Only clear the offline cache if it has been specifically asked for. + if (storagePolicy == nsICache::STORE_OFFLINE) { if (mEnableOfflineDevice) { if (!mOfflineDevice) { rv = CreateOfflineDevice(); diff --git a/netwerk/dns/src/effective_tld_names.dat b/netwerk/dns/src/effective_tld_names.dat index a7e78d1646fe..ac8701afec6c 100644 --- a/netwerk/dns/src/effective_tld_names.dat +++ b/netwerk/dns/src/effective_tld_names.dat @@ -1,4 +1,4 @@ -// ac : http://en.wikipedia.org/wiki/.am +// ac : http://en.wikipedia.org/wiki/.ac ac com.ac edu.ac @@ -229,6 +229,7 @@ info.az pp.az mil.az name.az +pro.az biz.az // ba : http://en.wikipedia.org/wiki/.ba @@ -304,7 +305,70 @@ mil.bo tv.bo // br : http://en.wikipedia.org/wiki/.br -*.br +// http://registro.br/info/dpn.html +br +adm.br +adv.br +agr.br +am.br +arq.br +art.br +ato.br +bio.br +blog.br +bmd.br +cim.br +cng.br +cnt.br +com.br +coop.br +ecn.br +edu.br +eng.br +esp.br +etc.br +eti.br +far.br +flog.br +fm.br +fnd.br +fot.br +fst.br +g12.br +ggf.br +gov.br +imb.br +ind.br +inf.br +jor.br +jus.br +lel.br +mat.br +med.br +mil.br +mus.br +net.br +nom.br +not.br +ntr.br +odo.br +org.br +ppg.br +pro.br +psc.br +psi.br +qsl.br +rec.br +slg.br +srv.br +tmp.br +trd.br +tur.br +tv.br +vet.br +vlog.br +wiki.br +zlg.br // bs : http://www.nic.bs/rules.html bs @@ -774,6 +838,7 @@ info // int : http://en.wikipedia.org/wiki/.int int +eu.int // io : http://www.nic.io/rules.html // list of 2nd level tlds ? @@ -806,242 +871,243 @@ int.is // it : http://en.wikipedia.org/wiki/.it it -gov.edu +gov.it +edu.it // geo-names found at http://www.nic.it/RA/en/domini/regole/nomi-riservati.pdf -Agrigento.it -AG.it -Alessandria.it -AL.it -Ancona.it -AN.it -Aosta.it -Aoste.it -AO.it -Arezzo.it -AR.it -Ascoli-Piceno.it -AscoliPiceno.it -AP.it -Asti.it -AT.it -Avellino.it -AV.it -Bari.it -BA.it -BarlettaAndriaTrani.it -Barletta-Andria-Trani.it -Belluno.it -BL.it -Benevento.it -BN.it -Bergamo.it -BG.it -Biella.it -BI.it -Bologna.it -BO.it -Bolzano.it -Bozen.it -Balsan.it -Alto-Adige.it -AltoAdige.it -Suedtirol.it -BZ.it -Brescia.it -BS.it -Brindisi.it -BR.it -Cagliari.it -CA.it -Caltanissetta.it -CL.it -Campobasso.it -CB.it -Caserta.it -CE.it -Catania.it -CT.it -Catanzaro.it -CZ.it -Chieti.it -CH.it -Como.it -CO.it -Cosenza.it -CS.it -Cremona.it -CR.it -Crotone.it -KR.it -Cuneo.it -CN.it -Enna.it -EN.it -Fermo.it -Ferrara.it -FE.it -Firenze.it -Florence.it -FI.it -Foggia.it -FG.it -Forli-Cesena.it -ForliCesena.it -FC.it -Frosinone.it -FR.it -Genova.it -Genoa.it -GE.it -Gorizia.it -GO.it -Grosseto.it -GR.it -Imperia.it -IM.it -Isernia.it -IS.it -LAquila.it -Aquila.it -AQ.it -La-Spezia.it -LaSpezia.it -SP.it -Latina.it -LT.it -Lecce.it -LE.it -Lecco.it -LC.it -Livorno.it -LI.it -Lodi.it -LO.it -Lucca.it -LU.it -Macerata.it -MC.it -Mantova.it -MN.it -Massa-Carrara.it -MassaCarrara.it -MS.it -Matera.it -MT.it -Messina.it -ME.it -Milano.it -Milan.it -MI.it -Modena.it -MO.it -Monza.it -Napoli.it -Naples.it -NA.it -Novara.it -NO.it -Nuoro.it -NU.it -Oristano.it -OR.it -Padova.it -Padua.it -PD.it -Palermo.it -PA.it -Parma.it -PR.it -Pavia.it -PV.it -Perugia.it -PG.it -Pescara.it -PE.it -Pesaro-Urbino.it -PesaroUrbino.it -PU.it -Piacenza.it -PC.it -Pisa.it -PI.it -Pistoia.it -PT.it -Pordenone.it -PN.it -Potenza.it -PZ.it -Prato.it -PO.it -Ragusa.it -RG.it -Ravenna.it -RA.it -Reggio-Calabria.it -ReggioCalabria.it -RC.it -Reggio-Emilia.it -ReggioEmilia.it -RE.it -Rieti.it -RI.it -Rimini.it -RN.it -Roma.it -Rome.it -RM.it -Rovigo.it -RO.it -Salerno.it -SA.it -Sassari.it -SS.it -Savona.it -SV.it -Siena.it -SI.it -Siracusa.it -SR.it -Sondrio.it -SO.it -Taranto.it -TA.it -Teramo.it -TE.it -Terni.it -TR.it -Torino.it -Turin.it -TO.it -Trapani.it -TP.it -Trento.it -Trentino.it -TN.it -Treviso.it -TV.it -Trieste.it -TS.it -Udine.it -UD.it -Varese.it -VA.it -Venezia.it -Venice.it -VE.it -Verbania.it -VB.it -Vercelli.it -VC.it -Verona.it -VR.it -Vibo-Valentia.it -ViboValentia.it -VV.it -Vicenza.it -VI.it -Viterbo.it -VT.it +agrigento.it +ag.it +alessandria.it +al.it +ancona.it +an.it +aosta.it +aoste.it +ao.it +arezzo.it +ar.it +ascoli-piceno.it +ascolipiceno.it +ap.it +asti.it +at.it +avellino.it +av.it +bari.it +ba.it +barlettaandriatrani.it +barletta-andria-trani.it +belluno.it +bl.it +benevento.it +bn.it +bergamo.it +bg.it +biella.it +bi.it +bologna.it +bo.it +bolzano.it +bozen.it +balsan.it +alto-adige.it +altoadige.it +suedtirol.it +bz.it +brescia.it +bs.it +brindisi.it +br.it +cagliari.it +ca.it +caltanissetta.it +cl.it +campobasso.it +cb.it +caserta.it +ce.it +catania.it +ct.it +catanzaro.it +cz.it +chieti.it +ch.it +como.it +co.it +cosenza.it +cs.it +cremona.it +cr.it +crotone.it +kr.it +cuneo.it +cn.it +enna.it +en.it +fermo.it +ferrara.it +fe.it +firenze.it +florence.it +fi.it +foggia.it +fg.it +forli-cesena.it +forlicesena.it +fc.it +frosinone.it +fr.it +genova.it +genoa.it +ge.it +gorizia.it +go.it +grosseto.it +gr.it +imperia.it +im.it +isernia.it +is.it +laquila.it +aquila.it +aq.it +la-spezia.it +laspezia.it +sp.it +latina.it +lt.it +lecce.it +le.it +lecco.it +lc.it +livorno.it +li.it +lodi.it +lo.it +lucca.it +lu.it +macerata.it +mc.it +mantova.it +mn.it +massa-carrara.it +massacarrara.it +ms.it +matera.it +mt.it +messina.it +me.it +milano.it +milan.it +mi.it +modena.it +mo.it +monza.it +napoli.it +naples.it +na.it +novara.it +no.it +nuoro.it +nu.it +oristano.it +or.it +padova.it +padua.it +pd.it +palermo.it +pa.it +parma.it +pr.it +pavia.it +pv.it +perugia.it +pg.it +pescara.it +pe.it +pesaro-urbino.it +pesarourbino.it +pu.it +piacenza.it +pc.it +pisa.it +pi.it +pistoia.it +pt.it +pordenone.it +pn.it +potenza.it +pz.it +prato.it +po.it +ragusa.it +rg.it +ravenna.it +ra.it +reggio-calabria.it +reggiocalabria.it +rc.it +reggio-emilia.it +reggioemilia.it +re.it +rieti.it +ri.it +rimini.it +rn.it +roma.it +rome.it +rm.it +rovigo.it +ro.it +salerno.it +sa.it +sassari.it +ss.it +savona.it +sv.it +siena.it +si.it +siracusa.it +sr.it +sondrio.it +so.it +taranto.it +ta.it +teramo.it +te.it +terni.it +tr.it +torino.it +turin.it +to.it +trapani.it +tp.it +trento.it +trentino.it +tn.it +treviso.it +tv.it +trieste.it +ts.it +udine.it +ud.it +varese.it +va.it +venezia.it +venice.it +ve.it +verbania.it +vb.it +vercelli.it +vc.it +verona.it +vr.it +vibo-valentia.it +vibovalentia.it +vv.it +vicenza.it +vi.it +viterbo.it +vt.it // je : http://www.channelisles.net/tandc.shtml je @@ -1231,12 +1297,35 @@ kn kr ac.kr co.kr +es.kr go.kr +hs.kr +kg.kr +mil.kr +ms.kr ne.kr or.kr -re.kr pe.kr -한글.kr utf8 ! +re.kr +sc.kr +// kr geographical names +// http://en.wikipedia.org/wiki/.kr +busan.kr +chungbuk.kr +chungnam.kr +daegu.kr +daejeon.kr +gangwon.kr +gwangju.kr +gyeongbuk.kr +gyeonggi.kr +gyeongnam.kr +incheon.kr +jeju.kr +jeonbuk.kr +jeonnam.kr +seoul.kr +ulsan.kr // kw : http://en.wikipedia.org/wiki/.kw *.kw @@ -1492,7 +1581,7 @@ mil.no stat.no dep.no kommune.no -herad.no +herad.no priv.no // no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html // counties @@ -1732,7 +1821,6 @@ flÃ¥.no folldal.no forsand.no fosnes.no -fredrikstad.no frei.no frogn.no froland.no @@ -1747,7 +1835,7 @@ forde.no førde.no gamvik.no gangaviika.no -gáŋgaviika utf8 ! +gáŋgaviika.no gaular.no gausdal.no gildeskal.no @@ -1788,7 +1876,7 @@ hareid.no harstad.no hasvik.no aknoluokta.no -ákÅ‹oluokta.no utf8 ! +ákÅ‹oluokta.no hattfjelldal.no aarborte.no haugesund.no @@ -1886,7 +1974,7 @@ leka.no leksvik.no lenvik.no leangaviika.no -lea?gaviika.no +leaÅ‹gaviika.no lesja.no levanger.no lier.no @@ -1909,7 +1997,6 @@ lyngdal.no lyngen.no ivgu.no lardal.no -Lærdal lerdal.no lærdal.no lodingen.no @@ -1989,7 +2076,7 @@ notteroy.no nøtterøy.no odda.no oksnes.no -`øksnes.no +øksnes.no oppdal.no oppegard.no oppegÃ¥rd.no @@ -2018,7 +2105,7 @@ oystre-slidre.no øystre-slidre.no porsanger.no porsangu.no -porsáŋgu.no utf8 ! +porsáŋgu.no porsgrunn.no radoy.no radøy.no @@ -2331,7 +2418,7 @@ mil.pl net.pl nieruchomosci.pl nom.pl -org.pl +org.pl pc.pl powiat.pl priv.pl @@ -2486,7 +2573,7 @@ zachpomor.pl zagan.pl zarow.pl zgora.pl -zgorzelec.pl +zgorzelec.pl // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl gdansk.pl @@ -2804,9 +2891,9 @@ idv.tw game.tw ebiz.tw club.tw -網路.tw utf8 ! -組織.tw utf8 ! -商業.tw utf8 ! +網路.tw +組織.tw +商業.tw // tz : http://en.wikipedia.org/wiki/.tz *.tz @@ -2897,6 +2984,7 @@ nsn.us ak.us al.us ar.us +as.us az.us ca.us co.us @@ -2905,6 +2993,7 @@ dc.us de.us fl.us ga.us +gu.us hi.us ia.us id.us @@ -2933,12 +3022,14 @@ oh.us ok.us or.us pa.us +pr.us ri.us sc.us sd.us tn.us tx.us ut.us +vi.us vt.us va.us wa.us diff --git a/other-licenses/branding/firefox/Makefile.in b/other-licenses/branding/firefox/Makefile.in index c19936e91c77..eee448721624 100644 --- a/other-licenses/branding/firefox/Makefile.in +++ b/other-licenses/branding/firefox/Makefile.in @@ -20,7 +20,7 @@ PREF_JS_EXPORTS = $(srcdir)/pref/firefox-branding.js include $(topsrcdir)/config/rules.mk BROWSER_APP_FILES = \ - default.xpm \ + default16.png \ mozicon128.png \ mozicon16.xpm \ mozicon50.xpm \ diff --git a/other-licenses/branding/firefox/default.xpm b/other-licenses/branding/firefox/default.xpm deleted file mode 100644 index ce4a3cdf5320..000000000000 --- a/other-licenses/branding/firefox/default.xpm +++ /dev/null @@ -1,299 +0,0 @@ -/* XPM */ -static char * default_xpm[] = { -"48 48 248 2", -" c None", -". c #7980B8", -"+ c #5269AA", -"@ c #133988", -"# c #155AA7", -"$ c #1181BC", -"% c #13508E", -"& c #2773AF", -"* c #6976B1", -"= c #146CAB", -"- c #1785C4", -"; c #35A7E4", -"> c #5988A8", -", c #1A639C", -"' c #618380", -") c #7F896D", -"! c #576768", -"~ c #414E6D", -"{ c #2882BB", -"] c #36A2DD", -"^ c #41AEE7", -"/ c #2D8FCF", -"( c #2A4D6F", -"_ c #DDC563", -": c #FDFA57", -"< c #F7CC2C", -"[ c #D0A634", -"} c #EEB88A", -"| c #E86918", -"1 c #40A3DD", -"2 c #296599", -"3 c #23568D", -"4 c #164778", -"5 c #16395A", -"6 c #072558", -"7 c #2C3B4D", -"8 c #9D8D2F", -"9 c #F8D801", -"0 c #FAE800", -"a c #F6B704", -"b c #FBD46D", -"c c #A5A5C9", -"d c #062C70", -"e c #061646", -"f c #0A2E62", -"g c #123D74", -"h c #6D6D6C", -"i c #A99269", -"j c #EDB16B", -"k c #BABCA3", -"l c #907241", -"m c #B27A1C", -"n c #F69B08", -"o c #F6A706", -"p c #F7A613", -"q c #E15707", -"r c #E58836", -"s c #AE99A3", -"t c #111A54", -"u c #05122B", -"v c #061538", -"w c #142646", -"x c #17334F", -"y c #4F4B50", -"z c #D28D3D", -"A c #F0AC4C", -"B c #756D57", -"C c #CEA753", -"D c #FDE55B", -"E c #FEFA7A", -"F c #F9E641", -"G c #F9C617", -"H c #FCD9A3", -"I c #E98B66", -"J c #D64804", -"K c #E17B25", -"L c #D86A27", -"M c #685049", -"N c #795B48", -"O c #635B5B", -"P c #E48529", -"Q c #E99737", -"R c #B8832E", -"S c #214357", -"T c #45402F", -"U c #CB8F1C", -"V c #FCF604", -"W c #F7C603", -"X c #FBE5B6", -"Y c #E36743", -"Z c #D63003", -"` c #E99C4C", -" . c #E17919", -".. c #172B5B", -"+. c #202A74", -"@. c #0D223C", -"#. c #7F5A1C", -"$. c #FDE56F", -"%. c #D15D41", -"&. c #B83404", -"*. c #D9782A", -"=. c #E27A06", -"-. c #277BC4", -";. c #624B23", -">. c #FBD659", -",. c #F1E084", -"'. c #DE7317", -"). c #E99725", -"!. c #F6B12B", -"~. c #EEA716", -"{. c #EB9515", -"]. c #E68714", -"^. c #CC590A", -"/. c #192963", -"(. c #66572F", -"_. c #E9A603", -":. c #AC320A", -"<. c #8D564E", -"[. c #4F6E8B", -"}. c #4A9DC9", -"|. c #FEFE92", -"1. c #D95708", -"2. c #4D2B18", -"3. c #E79209", -"4. c #FEFA86", -"5. c #FDE6A6", -"6. c #E6880C", -"7. c #DA6917", -"8. c #A4853C", -"9. c #D47350", -"0. c #CAAE8C", -"a. c #D1B76B", -"b. c #FCE424", -"c. c #F08F0D", -"d. c #FBEA3A", -"e. c #0B345A", -"f. c #836735", -"g. c #AB8B53", -"h. c #FEFD25", -"i. c #B9571B", -"j. c #C15822", -"k. c #B66F38", -"l. c #971703", -"m. c #532725", -"n. c #C09123", -"o. c #FEFD39", -"p. c #F9B517", -"q. c #FAC94B", -"r. c #A52504", -"s. c #38313D", -"t. c #9A8854", -"u. c #FEFC17", -"v. c #F9CA59", -"w. c #D35B23", -"x. c #B92707", -"y. c #113A6F", -"z. c #CC4621", -"A. c #BE4910", -"B. c #CD9750", -"C. c #C12A11", -"D. c #C8470A", -"E. c #C63605", -"F. c #A46F48", -"G. c #C97A36", -"H. c #89978D", -"I. c #0F3C75", -"J. c #A70209", -"K. c #D35615", -"L. c #E0650A", -"M. c #BC7036", -"N. c #0E3468", -"O. c #9A1124", -"P. c #25317F", -"Q. c #FCDB47", -"R. c #9B4967", -"S. c #D77707", -"T. c #CE5D15", -"U. c #A84515", -"V. c #342222", -"W. c #0A2543", -"X. c #A57736", -"Y. c #F9D515", -"Z. c #662817", -"`. c #040B26", -" + c #A06E32", -".+ c #C19471", -"++ c #970314", -"@+ c #D04911", -"#+ c #7E240E", -"$+ c #2D212E", -"%+ c #020935", -"&+ c #6C4538", -"*+ c #875F39", -"=+ c #FFFE6A", -"-+ c #883F67", -";+ c #291B1D", -">+ c #00071F", -",+ c #5C393C", -"'+ c #FEF2AE", -")+ c #FEFD4E", -"!+ c #CC9438", -"~+ c #B50501", -"{+ c #8B4B22", -"]+ c #7D4224", -"^+ c #FFFFC6", -"/+ c #BF9E8E", -"(+ c #762C5A", -"_+ c #C93B10", -":+ c #8B4E30", -"<+ c #543C54", -"[+ c #C66823", -"}+ c #D29A1D", -"|+ c #8E041A", -"1+ c #BC652C", -"2+ c #AE5B2C", -"3+ c #AF9393", -"4+ c #6E447E", -"5+ c #C11E00", -"6+ c #C32907", -"7+ c #FAE217", -"8+ c #650E41", -"9+ c #DF7931", -"0+ c #D86407", -"a+ c #7B0727", -"b+ c #DE9005", -"c+ c #DC8505", -"d+ c #EAB402", -"e+ c #EDC602", -"f+ c #A0776B", -"g+ c #B9140C", -"h+ c #C94617", -"i+ c #D04F22", -"j+ c #9C706E", -"k+ c #91697A", -"l+ c #850520", -"m+ c #79495B", -"n+ c #551D5F", -"o+ c #655191", -"p+ c #560D43", -"q+ c #81142A", -"r+ c #A81615", -"s+ c #A8371E", -"t+ c #8D362F", -"u+ c #632C4A", -"v+ c #563D7B", -"w+ c #453786", -"x+ c #471552", -"y+ c #3C185B", -" ", -" ", -" . + @ # # $ # % @ & * ", -" + @ = $ $ $ - ; ; $ = = = = = @ > ", -" + = $ $ $ $ $ $ ; ; ; - = # # , ' ) ! ~ ~ ", -" + % = = = = & & & { ] ^ ^ ; / = , % ( ! ) _ : < [ } ", -" | @ % % % % , , , , & & 1 ^ ^ ^ / & 2 3 4 5 6 6 7 8 9 0 a b ", -" | | } c d 6 e f g 4 4 h i j k & / ^ ^ ^ ^ { & 2 3 ( l m m n n o a a p ", -" q | r s t e u v w x y z A A i ( 3 / ^ ^ ^ 1 { & & & 2 ~ B C D E F G o n n H ", -" I J | K L M N y x 7 O P Q Q R x S & 1 ^ ^ { { & & & { 2 3 ( 5 T U < V V W n p X b ", -" Y Z J K j j j j j b ` .K Q y ..+./ ^ / & & { & { / ^ 1 & ( 5 w @.#.o 9 9 9 o A $. ", -" %.&.*.j A j A A Q Q K =. . .4 & -.] ^ -.-.& / ; ^ ^ ^ ^ / 3 3 ( ..w ;.n W W a n >.,. ", -" %.'.` ` A ).!.~.{.].=.=.'.^.y -.-.1 ^ ^ ] / ; ; ; ; ^ ^ 1 & 2 3 ( /.w (.n a _.o !.$. ", -" *.Q Q Q ~.~.{.{.].]. .'.'.^.:.<.[.> }.}.; ; ; ; ; ; ; ; ^ ^ { 3 { 2 3 S m n _.n !.|.X ", -" } P Q ~.{.{.{.].{.].]. . .'.1.:.J 1.q q 2.{ ] ; ; ; / ; ; ; ; 1 ] 1 1 { 2 S 3.n 3.n 4.5. ", -" Q ).).{.{.6.].].].K ]. .'.7.7.&.1.J q K i / ] ; ; ; ; ] / ] ] ] ] ] ] / & 8.m n !.o : $. ", -" Q ).].3.].].].].]. . .K '.K K 9.X X } 0.[.$ ] ] / ] ] { = , { / / / / / $ a.[ n $.a V b. ", -" j Q {.{.3.c.].].].]. . .'.| K K ` } j h 5 % - ; / $ { / / , , , { / / / / & i E c.$.d.0 9 ", -" Q ).].3.].].].].K . .'. .K K Q r I 7 e.% = / / - # , = { , , , , / / / -.3 f.E < $.D 9 W b ", -"j Q ).].{.].].].].]. . .'.K P Q Q A g.f @ = / / ; / = , & , , , , , & / -., @ f.h.G $.4.9 W !. ", -"` r ].{.{.6.].].].K .'. .P r Q ` A C @ # = - / / / = , , , , , , % { / { # % l 0 9 4.|.G a !. ", -"` ).].3.].6.].c. . . .K L i.j.j.k.C b % # $ -./ / / -., , , , , 3 % , { = , & R 9 W E |.< o !. ", -"j P ].3.].6.].K . .7.:.l.l.l.m.@.@.( @ # = -./ / / / / & , , 3 % % % % 4 ! & n.W G o.: p.n q. ", -"j K ].c.6.]. . . .'.r.l.l.l.r.s.f f f @ # = -.-./ -./ / 3 , , 3 % % % % 4 a.t.o o W V u.p.!.v. ", -"9.w.=.].]. . . . .7.l.l.r.r.x.N 4 @ @ # & -.-.-.-.{ -./ % 3 % % % @ % 4 y.C q.n n 9 0 V a >._ ", -"9.z.'. .K . .'.7.A.r.r.x.&.&. .O # # 2 & -.-.-.-.-.-.{ & % % 4 % 4 4 @ 4 B.E n n 9 9 0 p 4.j ", -" C.'.'. .K '.'.K D.:.&.&.E.E.7. .F.2 # # 2 h G.r A a.H.{ % 4 4 I.4 I.I., B.|.!.o W 9 9 q.|.j ", -" J.7. .'.'.'.'.'.K.E.E.D.J J L.'.K 7.M.M.'.K '.K r A ,.H.4 4 y.N.y.N.N.3 [ |.q.a a W G 4.$. ", -" O.K.'.'.L. .'.K '.D.Z J J q q '.'.K 7.'.'. . . .7.7.j g.I.y.f f 6 6 P.3 !.E Q.o < a >.|.>. ", -" R.z.w.'.S.'.'.'.| 7.q q q q q &.A.7.'.K '.L T.A.U.V.u W.e.N.6 t e w X.O Y.h.G n v.p.4.|.C ", -" x.L L.'.'.'.'. .7. .q q L.q K.l.l.l.r.r.:.:.Z.`.`.u e t t e e e + + +9 V W n b D 4.4..+ ", -" ++L @+'.'.S.'. .'.'.'.L.L.L.L.D.l.l.r.#+Z.$+@.u %+v e e e %+e &+6.*+n 9 9 a q.4.: =+Q. ", -" -+z.E. .'.'.S.L.'. .L. .7.'.L. .i.;+>+>+u w /.%+%+e e %+%+%+,+ .].c.a W W o '+)+o.)+!+ ", -" J.~+7.'.'.'.'.'.'.S.L. .L.'. .7. .{+v %+/.t %+%+%+%+%+%+]+| L .c._._._.v.^+V u.b./+ ", -" (+~+_+K 1.'.'. .'.'.S.'.'.S.L. .'.'.'.:+<+P.+.t %+%+m.[+'.'.'.'.6.3.3.~.|.4.V V }+ ", -" |+~+@+7.7.'.K '.'.'.'.'.'.S.=.L.'.'.'.'.'.1+2+[+ . .'.'. . .'.=.=.=.d.E d.0 9 3+ ", -" 4+~+5+K.6+7.K P 7. .'.'.'.'.'.'.'.'.'.'. .'.'.7.K 7.K 7. .7.L.L.S.7+o.: 9 9 R ", -" 8+~+5+J 5+K.9+K C.1.'. . .'.'.L.'. .K K P r r r r r K 7.q 0+S.9 V h.Y.9 _. ", -" a+~+6+Z ~+6+r 9+~+E.7.K K 7.K. .'.K K K K K K '.'.'.0+0+b+9 0 V V W a 3+ ", -" ++~+E.6+~+~+z.r C.~+_+w.P 9+K.@+K.7.'.'. . .'.7.0+c+_.d+e+0 0 e+_.f+ ", -" ++~+6+5+~+~+g+z.g+g+g+C.h+%.r L i+@+@+T.T.0+S.c+b+_.d+e+e+e+3.j+ ", -" a+~+~+~+~+~+~+g+g+g+g+g+g+g+_+h+w._+D.^.^.0+S.c+b+d+d+_.'.k+ ", -" 8+J.~+~+~+~+g+g+g+g+g+g+g+g+C.6+&.D.D.^.0+S.S.b+3.].2+ ", -" l+~+~+~+g+~+g+g+g+g+g+g+C.C.6+_+D.D.^.0+S.S.[+m+ ", -" n+a+~+g+g+g+g+g+g+g+g+g+C.6+E._+D.^.0+2+m+ ", -" o+p+q+r+g+g+g+g+g+g+x.C.E.s+t+u+v+ ", -" w+x+x+x+x+x+x+y+w+ ", -" "}; diff --git a/other-licenses/branding/firefox/default16.png b/other-licenses/branding/firefox/default16.png new file mode 100644 index 000000000000..e303b27dca11 Binary files /dev/null and b/other-licenses/branding/firefox/default16.png differ diff --git a/other-licenses/branding/firefox/firefox.ico b/other-licenses/branding/firefox/firefox.ico index b97ce260caa9..f0c2d5b42e5e 100644 Binary files a/other-licenses/branding/firefox/firefox.ico and b/other-licenses/branding/firefox/firefox.ico differ diff --git a/rdf/chrome/src/nsChromeRegistry.cpp b/rdf/chrome/src/nsChromeRegistry.cpp index d960d2bed5df..20a44370c0a3 100644 --- a/rdf/chrome/src/nsChromeRegistry.cpp +++ b/rdf/chrome/src/nsChromeRegistry.cpp @@ -81,6 +81,7 @@ #include "nsLayoutCID.h" #include "prio.h" #include "nsInt64.h" +#include "nsEscape.h" #include "nsIDirectoryService.h" #include "nsILocalFile.h" #include "nsAppDirectoryServiceDefs.h" @@ -388,26 +389,16 @@ SplitURL(nsIURI *aChromeURI, nsCString& aPackage, nsCString& aProvider, nsCStrin } else { // Protect against URIs containing .. that reach up out of the // chrome directory to grant chrome privileges to non-chrome files. - int depth = 0; - PRBool sawSlash = PR_TRUE; // .. at the beginning is suspect as well as /.. - for (const char* p=aFile.get(); *p; p++) { - if (sawSlash) { - if (p[0] == '.' && p[1] == '.'){ - depth--; // we have /.., decrement depth. - } else { - static const char escape[] = "%2E%2E"; - if (PL_strncasecmp(p, escape, sizeof(escape)-1) == 0) - depth--; // we have the HTML-escaped form of /.., decrement depth. - } - } else if (p[0] != '/') { - depth++; // we have /x for some x that is not / - } - sawSlash = (p[0] == '/'); - - if (depth < 0) { - return NS_ERROR_FAILURE; - } + PRInt32 origLen = aFile.Length(); + PRInt32 newLen = nsUnescapeCount(aFile.BeginWriting()); + if (origLen != newLen) { + aFile.SetLength(newLen); + nofile = PR_TRUE; // let caller know path is modified } + + if (aFile.Find(NS_LITERAL_CSTRING("..")) != kNotFound || + aFile.FindChar(':') != kNotFound) + return NS_ERROR_FAILURE; } if (aModified) *aModified = nofile; diff --git a/security/manager/Makefile.in b/security/manager/Makefile.in index 0bc43b0d7f63..f8f63dfbac1f 100644 --- a/security/manager/Makefile.in +++ b/security/manager/Makefile.in @@ -50,6 +50,7 @@ PACKAGE_FILE = psm.pkg ifndef MOZ_NATIVE_NSS PACKAGE_VARS += \ NSS3_LIB \ + NSSUTIL3_LIB \ SMIME3_LIB \ SSL3_LIB \ SOFTOKEN3_LIB \ @@ -66,6 +67,7 @@ LOADABLE_ROOT_MODULE = $(DLL_PREFIX)nssckbi$(DLL_SUFFIX) endif NSS3_LIB = $(DLL_PREFIX)nss3$(DLL_SUFFIX) +NSSUTIL3_LIB = $(DLL_PREFIX)nssutil3$(DLL_SUFFIX) SMIME3_LIB = $(DLL_PREFIX)smime3$(DLL_SUFFIX) SSL3_LIB = $(DLL_PREFIX)ssl3$(DLL_SUFFIX) SOFTOKEN3_LIB = $(DLL_PREFIX)softokn3$(DLL_SUFFIX) @@ -263,6 +265,7 @@ endif $(INSTALL) -m 755 $(DIST)/lib/$(SOFTOKEN3_LIB) $(DIST)/bin $(INSTALL) -m 755 $(DIST)/lib/$(NSSDBM3_LIB) $(DIST)/bin $(INSTALL) -m 755 $(DIST)/lib/$(NSS3_LIB) $(DIST)/bin + $(INSTALL) -m 755 $(DIST)/lib/$(NSSUTIL3_LIB) $(DIST)/bin $(INSTALL) -m 755 $(DIST)/lib/$(SSL3_LIB) $(DIST)/bin $(INSTALL) -m 755 $(DIST)/lib/$(SMIME3_LIB) $(DIST)/bin ifdef HAVE_FREEBL_LIBS @@ -321,6 +324,7 @@ endif $(SYSINSTALL) -m 755 $(DIST)/lib/$(SOFTOKEN3_LIB) $(DESTDIR)$(mozappdir) $(SYSINSTALL) -m 755 $(DIST)/lib/$(NSSDBM3_LIB) $(DESTDIR)$(mozappdir) $(SYSINSTALL) -m 755 $(DIST)/lib/$(NSS3_LIB) $(DESTDIR)$(mozappdir) + $(SYSINSTALL) -m 755 $(DIST)/lib/$(NSSUTIL3_LIB) $(DESTDIR)$(mozappdir) $(SYSINSTALL) -m 755 $(DIST)/lib/$(SSL3_LIB) $(DESTDIR)$(mozappdir) $(SYSINSTALL) -m 755 $(DIST)/lib/$(SMIME3_LIB) $(DESTDIR)$(mozappdir) ifdef HAVE_FREEBL_LIBS diff --git a/security/manager/ssl/src/nsIdentityChecking.cpp b/security/manager/ssl/src/nsIdentityChecking.cpp index 34e34c92e09f..c29b8293c180 100644 --- a/security/manager/ssl/src/nsIdentityChecking.cpp +++ b/security/manager/ssl/src/nsIdentityChecking.cpp @@ -505,14 +505,12 @@ static SECStatus getFirstEVPolicy(CERTCertificate *cert, SECOidTag &outOidTag) PRBool nsNSSSocketInfo::hasCertErrors() { - if (!mSSLStatus || !mSSLStatus->mHaveCertStatus) { - // if the status is unknown, assume the cert is bad :-) + if (!mSSLStatus) { + // if the status is unknown, assume the cert is bad, better safe than sorry return PR_TRUE; } - return mSSLStatus->mIsDomainMismatch || - mSSLStatus->mIsNotValidAtThisTime || - mSSLStatus->mIsUntrusted; + return mSSLStatus->mHaveCertErrorBits; } NS_IMETHODIMP @@ -524,6 +522,7 @@ nsNSSSocketInfo::GetIsExtendedValidation(PRBool* aIsEV) if (!mCert) return NS_OK; + // Never allow bad certs for EV, regardless of overrides. if (hasCertErrors()) return NS_OK; @@ -569,6 +568,15 @@ nsNSSCertificate::hasValidEVOidTag(SECOidTag &resultOidTag, PRBool &validEV) validEV = PR_FALSE; resultOidTag = SEC_OID_UNKNOWN; + PRBool isOCSPEnabled = PR_FALSE; + nsCOMPtr certdb; + certdb = do_GetService(NS_X509CERTDB_CONTRACTID); + if (certdb) + certdb->GetIsOcspOn(&isOCSPEnabled); + // No OCSP, no EV + if (!isOCSPEnabled) + return NS_OK; + SECOidTag oid_tag; SECStatus rv = getFirstEVPolicy(mCert, oid_tag); if (rv != SECSuccess) @@ -585,6 +593,7 @@ nsNSSCertificate::hasValidEVOidTag(SECOidTag &resultOidTag, PRBool &validEV) cvin[1].type = cert_pi_revocationFlags; cvin[1].value.scalar.ul = CERT_REV_FAIL_SOFT_CRL | CERT_REV_FLAG_CRL + | CERT_REV_FLAG_OCSP ; cvin[2].type = cert_pi_end; @@ -690,7 +699,7 @@ nsNSSComponent::CleanupIdentityInfo() if (testEVInfosLoaded) { testEVInfosLoaded = PR_FALSE; if (testEVInfos) { - for (size_t i; iLength(); ++i) { + for (size_t i = 0; iLength(); ++i) { delete testEVInfos->ElementAt(i); } testEVInfos->Clear(); diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 3802a051b658..358239b3c132 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -2547,8 +2547,27 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, /* Get CN and O of the subject and O of the issuer */ char *ccn = CERT_GetCommonName(&serverCert->subject); + charCleaner ccnCleaner(ccn); NS_ConvertUTF8toUTF16 cn(ccn); - if (ccn) PORT_Free(ccn); + + PRInt32 port; + info->GetPort(&port); + char *hostname = SSL_RevealURL(socket); + charCleaner hostnameCleaner(hostname); + + nsString cn_host_port; + if (ccn && strcmp(ccn, hostname) == 0) { + cn_host_port.Append(cn); + cn_host_port.AppendLiteral(":"); + cn_host_port.AppendInt(port); + } + else { + cn_host_port.Append(cn); + cn_host_port.AppendLiteral(" ("); + cn_host_port.AppendLiteral(":"); + cn_host_port.AppendInt(port); + cn_host_port.AppendLiteral(")"); + } char *corg = CERT_GetOrgName(&serverCert->subject); NS_ConvertUTF8toUTF16 org(corg); @@ -2615,7 +2634,7 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, rv = NS_ERROR_NOT_AVAILABLE; } else { - rv = dialogs->ChooseCertificate(info, cn.get(), org.get(), issuer.get(), + rv = dialogs->ChooseCertificate(info, cn_host_port.get(), org.get(), issuer.get(), (const PRUnichar**)certNicknameList, (const PRUnichar**)certDetailsList, CertsToUse, &selectedIndex, &canceled); } @@ -2827,7 +2846,7 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) status->mServerCert = nssCert; } - status->mHaveCertStatus = PR_TRUE; + status->mHaveCertErrorBits = PR_TRUE; status->mIsDomainMismatch = collected_errors & nsICertOverrideService::ERROR_MISMATCH; status->mIsNotValidAtThisTime = collected_errors & nsICertOverrideService::ERROR_TIME; status->mIsUntrusted = collected_errors & nsICertOverrideService::ERROR_UNTRUSTED; diff --git a/security/manager/ssl/src/nsRecentBadCerts.cpp b/security/manager/ssl/src/nsRecentBadCerts.cpp index 753c11dafb16..f87352d00ce9 100644 --- a/security/manager/ssl/src/nsRecentBadCerts.cpp +++ b/security/manager/ssl/src/nsRecentBadCerts.cpp @@ -131,7 +131,7 @@ nsRecentBadCertsService::GetRecentBadCert(const nsAString & aHostNameWithPort, status->mServerCert = new nsNSSCertificate(nssCert); CERT_DestroyCertificate(nssCert); - status->mHaveCertStatus = PR_TRUE; + status->mHaveCertErrorBits = PR_TRUE; status->mIsDomainMismatch = isDomainMismatch; status->mIsNotValidAtThisTime = isNotValidAtThisTime; status->mIsUntrusted = isUntrusted; diff --git a/security/manager/ssl/src/nsSSLStatus.cpp b/security/manager/ssl/src/nsSSLStatus.cpp index 63e842779a21..523d82c2dca8 100644 --- a/security/manager/ssl/src/nsSSLStatus.cpp +++ b/security/manager/ssl/src/nsSSLStatus.cpp @@ -95,10 +95,8 @@ NS_IMETHODIMP nsSSLStatus::GetIsDomainMismatch(PRBool* _result) { NS_ASSERTION(_result, "non-NULL destination required"); - if (!mHaveCertStatus) - return NS_ERROR_NOT_AVAILABLE; - *_result = mIsDomainMismatch; + *_result = mHaveCertErrorBits && mIsDomainMismatch; return NS_OK; } @@ -107,10 +105,8 @@ NS_IMETHODIMP nsSSLStatus::GetIsNotValidAtThisTime(PRBool* _result) { NS_ASSERTION(_result, "non-NULL destination required"); - if (!mHaveCertStatus) - return NS_ERROR_NOT_AVAILABLE; - *_result = mIsNotValidAtThisTime; + *_result = mHaveCertErrorBits && mIsNotValidAtThisTime; return NS_OK; } @@ -119,10 +115,8 @@ NS_IMETHODIMP nsSSLStatus::GetIsUntrusted(PRBool* _result) { NS_ASSERTION(_result, "non-NULL destination required"); - if (!mHaveCertStatus) - return NS_ERROR_NOT_AVAILABLE; - *_result = mIsUntrusted; + *_result = mHaveCertErrorBits && mIsUntrusted; return NS_OK; } @@ -154,7 +148,7 @@ nsSSLStatus::Read(nsIObjectInputStream* stream) rv = stream->ReadBoolean(&mHaveKeyLengthAndCipher); NS_ENSURE_SUCCESS(rv, rv); - rv = stream->ReadBoolean(&mHaveCertStatus); + rv = stream->ReadBoolean(&mHaveCertErrorBits); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -184,7 +178,7 @@ nsSSLStatus::Write(nsIObjectOutputStream* stream) rv = stream->WriteBoolean(mHaveKeyLengthAndCipher); NS_ENSURE_SUCCESS(rv, rv); - rv = stream->WriteBoolean(mHaveCertStatus); + rv = stream->WriteBoolean(mHaveCertErrorBits); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -259,7 +253,7 @@ nsSSLStatus::nsSSLStatus() , mIsNotValidAtThisTime(PR_FALSE) , mIsUntrusted(PR_FALSE) , mHaveKeyLengthAndCipher(PR_FALSE) -, mHaveCertStatus(PR_FALSE) +, mHaveCertErrorBits(PR_FALSE) { } diff --git a/security/manager/ssl/src/nsSSLStatus.h b/security/manager/ssl/src/nsSSLStatus.h index 1eba0d987aa3..e8134d24a6a9 100644 --- a/security/manager/ssl/src/nsSSLStatus.h +++ b/security/manager/ssl/src/nsSSLStatus.h @@ -74,7 +74,7 @@ public: PRBool mIsUntrusted; PRBool mHaveKeyLengthAndCipher; - PRBool mHaveCertStatus; + PRBool mHaveCertErrorBits; }; // 2c3837af-8b85-4a68-b0d8-0aed88985b32 diff --git a/storage/public/mozIStorageService.idl b/storage/public/mozIStorageService.idl index f220fbbe33b8..808459551d80 100644 --- a/storage/public/mozIStorageService.idl +++ b/storage/public/mozIStorageService.idl @@ -46,11 +46,6 @@ interface nsIFile; * a service that can create storage connections (mozIStorageConnection) * to either a well-known profile database or to a specific database file. * - * The implementation of this service using sqlite with the async IO module - * must be created the first time on the main thread. If you want to use it - * from another thread, you should be sure you call getService from the main - * thread before accessing it from another thread. - * * This is the only way to open a database connection. */ [scriptable, uuid(a4a0cad9-e0da-4379-bee4-2feef3dddc7e)] @@ -84,10 +79,6 @@ interface mozIStorageService : nsISupports { * a simple string compare to see if there is already a connection. Opening * a connection to "Foo.sqlite" and "foo.sqlite" will CORRUPT YOUR DATABASE. * - * Opening connections from more than one thread to the same database will - * also CORRUPT YOUR DATABASE. All connections share the same sqlite cache, - * and the cache is not threadsafe. - * * The connection object returned by this function is not threadsafe. You must * use it only from the thread you created it from. * diff --git a/testing/extensions/community/chrome/content/litmusReporter.js b/testing/extensions/community/chrome/content/litmusReporter.js index 56b433bd8477..50048d5306d0 100644 --- a/testing/extensions/community/chrome/content/litmusReporter.js +++ b/testing/extensions/community/chrome/content/litmusReporter.js @@ -62,7 +62,7 @@ function LitmusResults(a) { this.machinename = a.machinename || ''; this.requireField('username', a); this.requireField('password', a); - this.server = a.server || 'http://litmus.mozilla.org/process_test.cgi'; + this.server = a.server || 'https://litmus.mozilla.org/process_test.cgi'; this.action = 'submit'; this.results = new Array(); @@ -97,7 +97,7 @@ LitmusResults.prototype = { var d = ''+"\n"; d += ''+"\n"; + ' "https://litmus.mozilla.org/litmus_results.dtd">'+"\n"; d += '' : '>') +"\n"; diff --git a/testing/extensions/community/chrome/content/prefs.js b/testing/extensions/community/chrome/content/prefs.js index 12baff5f3738..86a2226a2c68 100755 --- a/testing/extensions/community/chrome/content/prefs.js +++ b/testing/extensions/community/chrome/content/prefs.js @@ -173,9 +173,16 @@ var CC_loginManager = Components.classes["@mozilla.org/login-manager;1"]; var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo, "init"); - var newLogin = new nsLoginInfo('chrome://qa', 'Litmus Login', litmus.baseURL, - username, password, null, null); - this.manager().addLogin(newLogin); + + // The LoginManager does not like "null" for username/password fields, + // So we send in the field names from the XUL. + var newLogin = new nsLoginInfo('chrome://qa', 'Litmus Login', litmus.baseURL, + username, password, "username", "password"); + try { + this.manager().addLogin(newLogin); + } catch (err) { + alert("ERROR: " + err); + } }, getPasswordObj: function() { try { diff --git a/testing/extensions/community/chrome/content/qa.xul b/testing/extensions/community/chrome/content/qa.xul index 47ef828bd56b..754d2d87741d 100644 --- a/testing/extensions/community/chrome/content/qa.xul +++ b/testing/extensions/community/chrome/content/qa.xul @@ -36,8 +36,6 @@ - - ***** END LICENSE BLOCK ***** --> - - diff --git a/testing/extensions/community/chrome/content/setup.xul b/testing/extensions/community/chrome/content/setup.xul index 4eca0dbd3bd3..16fe63c9b037 100644 --- a/testing/extensions/community/chrome/content/setup.xul +++ b/testing/extensions/community/chrome/content/setup.xul @@ -75,8 +75,8 @@ - - + + diff --git a/testing/extensions/community/chrome/skin/qa.css b/testing/extensions/community/chrome/skin/qa.css index 2b8d9dadb8bd..5280c5dee7e7 100755 --- a/testing/extensions/community/chrome/skin/qa.css +++ b/testing/extensions/community/chrome/skin/qa.css @@ -38,8 +38,6 @@ @import url(chrome://global/skin/); -@import url(chrome://browser/skin/); - @namespace html "http://www.w3.org/1999/xhtml"; #qa-pass { @@ -103,7 +101,8 @@ html|li { #qa_tabbox #qa-tabbar-qmo { list-style-image: url(qmo-16px.png); - width: 15px; + text-align: center; + width: 24px; } #qa_tabbox #qa-tabbar-spacer { diff --git a/testing/extensions/community/defaults/preferences/qa.js b/testing/extensions/community/defaults/preferences/qa.js index d78ca0bb9836..8368c4b53f3f 100644 --- a/testing/extensions/community/defaults/preferences/qa.js +++ b/testing/extensions/community/defaults/preferences/qa.js @@ -35,9 +35,9 @@ * * ***** END LICENSE BLOCK ***** */ -pref("qa.extension.litmus.url", "http://litmus.mozilla.org/"); -pref("qa.extension.hermes.url", "http://litmus.mozilla.org/hermes/1/"); -pref("qa.extension.bugzilla.url", "http:/bugzilla.mozilla.org/"); +pref("qa.extension.litmus.url", "https://litmus.mozilla.org/"); +pref("qa.extension.hermes.url", "https://litmus.mozilla.org/hermes/1/"); +pref("qa.extension.bugzilla.url", "https:/bugzilla.mozilla.org/"); pref("qa.extension.isFirstTime", true); pref("qa.extension.minNotificationInterval", 5400000); // 90 minutes pref("qa.extension.lastNotificationTime", 0); diff --git a/testing/mochitest/browser-test.js b/testing/mochitest/browser-test.js index c4392877125a..593419704bc1 100644 --- a/testing/mochitest/browser-test.js +++ b/testing/mochitest/browser-test.js @@ -111,31 +111,36 @@ function testScope(aTests) { scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", this.EventUtils); this.tests = aTests; + + var self = this; + this.ok = function test_ok(condition, name, diag) { + self.tests.push(new testResult(condition, name, diag, false)); + } + this.is = function test_is(a, b, name) { + self.ok(a == b, name, "Got " + a + ", expected " + b); + } + this.isnot = function test_isnot(a, b, name) { + self.ok(a != b, name, "Didn't expect " + a + ", but got it"); + } + this.todo = function test_todo(condition, name, diag) { + self.tests.push(new testResult(!condition, name, diag, true)); + } + this.todo_is = function test_todo_is(a, b, name) { + self.todo(a == b, name, "Got " + a + ", expected " + b); + }, + this.todo_isnot = function test_todo_isnot(a, b, name) { + self.todo(a != b, name, "Didn't expect " + a + ", but got it"); + }, + + this.waitForExplicitFinish = function test_WFEF() { + self.done = false; + } + this.finish = function test_finish() { + self.done = true; + } } testScope.prototype = { - ok: function test_ok(condition, name, diag) { - this.tests.push(new testResult(condition, name, diag, false)); - }, - - is: function test_is(a, b, name) { - this.ok(a == b, name, "Got " + a + ", expected " + b); - }, - - isnot: function test_isnot(a, b, name) { - this.ok(a != b, name, "Didn't expect " + a + ", but got it"); - }, - - todo: function test_todo(condition, name, diag) { - this.tests.push(new testResult(!condition, name, diag, true)); - }, - done: true, - waitForExplicitFinish: function test_WFEF() { - this.done = false; - }, - finish: function test_finish() { - this.done = true; - }, EventUtils: {} }; diff --git a/testing/mochitest/runtests.pl.in b/testing/mochitest/runtests.pl.in index 20dcb4d3ca71..acf6f1a691db 100644 --- a/testing/mochitest/runtests.pl.in +++ b/testing/mochitest/runtests.pl.in @@ -189,17 +189,14 @@ sub main { } my $manifest = initializeProfile($app, $do_browser_chrome); - my $serverPid; - if (!$do_browser_chrome) { - $serverPid = startServer($close_when_done); - - # If we're lucky, the server has fully started by now, and all paths are - # ready, etc. However, xpcshell cold start times suck, at least for debug - # builds. We'll try to connect to the server for 30 seconds or until we - # succeed, whichever is first. If we succeed, then we continue with - # execution. If we fail, we try to kill the server and exit with an error. - wait_for_server_startup($serverPid, SERVER_STARTUP_TIMEOUT); - } + my $serverPid = startServer($close_when_done); + + # If we're lucky, the server has fully started by now, and all paths are + # ready, etc. However, xpcshell cold start times suck, at least for debug + # builds. We'll try to connect to the server for 30 seconds or until we + # succeed, whichever is first. If we succeed, then we continue with + # execution. If we fail, we try to kill the server and exit with an error. + wait_for_server_startup($serverPid, SERVER_STARTUP_TIMEOUT); my $url; if ($do_chrome) { @@ -234,9 +231,7 @@ sub main { my $test_start = runTests($url, \%browser_env, \%browser_args); - if (!$do_browser_chrome) { - shutdownServer($serverPid); - } + shutdownServer($serverPid); # print test run times my $test_finish = localtime(); diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js index 2a13d8d7d90e..04f255f61b07 100644 --- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -191,13 +191,18 @@ function _parseModifiers(aEvent) * * If the type is specified, an mouse event of that type is fired. Otherwise, * a mousedown followed by a mouse up is performed. + * + * aWindow is optional, and defaults to the current window object. */ -function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent) +function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow) { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). - getInterface(Components.interfaces.nsIDOMWindowUtils); + if (!aWindow) + aWindow = window; + + var utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor). + getInterface(Components.interfaces.nsIDOMWindowUtils); if (utils) { var button = aEvent.button || 0; var clickCount = aEvent.clickCount || 1; @@ -228,13 +233,18 @@ function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent) * * If the type is specified, a key event of that type is fired. Otherwise, * a keydown, a keypress and then a keyup event are fired in sequence. + * + * aWindow is optional, and defaults to the current window object. */ -function synthesizeKey(aKey, aEvent) +function synthesizeKey(aKey, aEvent, aWindow) { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). - getInterface(Components.interfaces.nsIDOMWindowUtils); + if (!aWindow) + aWindow = window; + + var utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor). + getInterface(Components.interfaces.nsIDOMWindowUtils); if (utils) { var keyCode = 0, charCode = 0; if (aKey.indexOf("VK_") == 0) @@ -312,12 +322,15 @@ function _checkExpectedEvent(aExpectedTarget, aExpectedEvent, aEventHandler, aTe * To test that an event is not fired, use an expected type preceded by an * exclamation mark, such as '!select'. This might be used to test that a * click on a disabled element doesn't fire certain events for instance. + * + * aWindow is optional, and defaults to the current window object. */ function synthesizeMouseExpectEvent(aTarget, aOffsetX, aOffsetY, aEvent, - aExpectedTarget, aExpectedEvent, aTestName) + aExpectedTarget, aExpectedEvent, aTestName, + aWindow) { var eventHandler = _expectEvent(aExpectedTarget, aExpectedEvent, aTestName); - synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent); + synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow); _checkExpectedEvent(aExpectedTarget, aExpectedEvent, eventHandler, aTestName); } @@ -331,10 +344,13 @@ function synthesizeMouseExpectEvent(aTarget, aOffsetX, aOffsetY, aEvent, * * To test that an event is not fired, use an expected type preceded by an * exclamation mark, such as '!select'. + * + * aWindow is optional, and defaults to the current window object. */ -function synthesizeKeyExpectEvent(key, aEvent, aExpectedTarget, aExpectedEvent, aTestName) +function synthesizeKeyExpectEvent(key, aEvent, aExpectedTarget, aExpectedEvent, + aTestName, aWindow) { var eventHandler = _expectEvent(aExpectedTarget, aExpectedEvent, aTestName); - synthesizeKey(key, aEvent); + synthesizeKey(key, aEvent, aWindow); _checkExpectedEvent(aExpectedTarget, aExpectedEvent, eventHandler, aTestName); } diff --git a/testing/mochitest/tests/SimpleTest/SimpleTest.js b/testing/mochitest/tests/SimpleTest/SimpleTest.js index 3fc354745039..36fbbbfe9f2d 100644 --- a/testing/mochitest/tests/SimpleTest/SimpleTest.js +++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js @@ -150,9 +150,11 @@ SimpleTest.toggle = function(el) { /** * Toggle visibility for divs with a specific class. **/ -SimpleTest.toggleByClass = function (cls) { +SimpleTest.toggleByClass = function (cls, evt) { var elems = getElementsByTagAndClassName('div', cls); MochiKit.Base.map(SimpleTest.toggle, elems); + if (evt) + evt.preventDefault(); }; /** diff --git a/testing/mochitest/tests/SimpleTest/TestRunner.js b/testing/mochitest/tests/SimpleTest/TestRunner.js index 31faeae80222..45a480685375 100644 --- a/testing/mochitest/tests/SimpleTest/TestRunner.js +++ b/testing/mochitest/tests/SimpleTest/TestRunner.js @@ -19,11 +19,11 @@ TestRunner.maxTimeouts = 4; // halt testing after too many timeouts * Make sure the tests don't hang indefinitely. **/ TestRunner._numTimeouts = 0; -TestRunner._currentTestStartTime = Date.now(); +TestRunner._currentTestStartTime = new Date().valueOf(); TestRunner._checkForHangs = function() { if (TestRunner._currentTest < TestRunner._urls.length) { - var runtime = (Date.now() - TestRunner._currentTestStartTime) / 1000; + var runtime = (new Date().valueOf() - TestRunner._currentTestStartTime) / 1000; if (runtime >= TestRunner.timeout) { var frameWindow = $('testframe').contentWindow.wrappedJSObject || $('testframe').contentWindow; @@ -105,7 +105,7 @@ TestRunner.runNextTest = function() { $("current-test-path").innerHTML = url; - TestRunner._currentTestStartTime = Date.now(); + TestRunner._currentTestStartTime = new Date().valueOf(); if (TestRunner.logEnabled) TestRunner.logger.log("Running " + url + "..."); @@ -116,10 +116,10 @@ TestRunner.runNextTest = function() { TestRunner._makeIframe("about:blank"); if (TestRunner.logEnabled) { TestRunner.logger.log("SimpleTest FINISHED"); - TestRunner.logger.log("Passed: " + $("pass-count").innerHTML); - TestRunner.logger.log("Failed: " + $("fail-count").innerHTML); - TestRunner.logger.log("Todo: " + $("todo-count").innerHTML); - } + TestRunner.logger.log("Passed: " + $("pass-count").innerHTML); + TestRunner.logger.log("Failed: " + $("fail-count").innerHTML); + TestRunner.logger.log("Todo: " + $("todo-count").innerHTML); + } if (TestRunner.onComplete) TestRunner.onComplete(); } diff --git a/testing/mochitest/tests/browser/browser_fail.js b/testing/mochitest/tests/browser/browser_fail.js index 07e1571e45e7..3d91439ea2cf 100644 --- a/testing/mochitest/tests/browser/browser_fail.js +++ b/testing/mochitest/tests/browser/browser_fail.js @@ -3,4 +3,6 @@ function test() { is(true, false, "fail is"); isnot(true, true, "fail isnot"); todo(true, "fail todo"); + todo_is(true, true, "fail todo_is"); + todo_isnot(true, false, "fail todo_isnot"); } diff --git a/testing/mochitest/tests/browser/browser_pass.js b/testing/mochitest/tests/browser/browser_pass.js index 08dc065c325f..ac35b5e522c0 100644 --- a/testing/mochitest/tests/browser/browser_pass.js +++ b/testing/mochitest/tests/browser/browser_pass.js @@ -1,6 +1,11 @@ function test() { - is(true, true, "pass is"); ok(true, "pass ok"); + is(true, true, "pass is"); isnot(false, true, "pass isnot"); todo(false, "pass todo"); + todo_is(false, true, "pass todo_is"); + todo_isnot(true, true, "pass todo_isnot"); + + var func = is; + func(true, true, "pass indirect is"); } diff --git a/testing/performance/talos/ffprofile_win32.py b/testing/performance/talos/ffprofile_win32.py index 9043703437d7..35dd54645f4e 100644 --- a/testing/performance/talos/ffprofile_win32.py +++ b/testing/performance/talos/ffprofile_win32.py @@ -45,7 +45,13 @@ def MakeDirectoryContentsWritable(dirname): dirname: Name of the directory to make contents writable. """ - for (root, dirs, files) in os.walk(dirname): - os.chmod(root, 0777) - for filename in files: - os.chmod(os.path.join(root, filename), 0777) + try: + for (root, dirs, files) in os.walk(dirname): + os.chmod(root, 0777) + for filename in files: + try: + os.chmod(os.path.join(root, filename), 0777) + except OSError, (errno, strerror): + print 'WARNING: failed to os.chmod(%s): %s : %s' % (os.path.join(root, filename), errno, strerror) + except OSError, (errno, strerror): + print 'WARNING: failed to MakeDirectoryContentsWritable: %s : %s' % (errno, strerror) diff --git a/testing/performance/talos/page_load_test/jss/core-eval-1.html b/testing/performance/talos/page_load_test/jss/core-eval-1.html new file mode 100644 index 000000000000..692fb696b5ae --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-1.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-10.html b/testing/performance/talos/page_load_test/jss/core-eval-10.html new file mode 100644 index 000000000000..f7647bd70879 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-10.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-11.html b/testing/performance/talos/page_load_test/jss/core-eval-11.html new file mode 100644 index 000000000000..210996b2aef3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-11.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-12.html b/testing/performance/talos/page_load_test/jss/core-eval-12.html new file mode 100644 index 000000000000..65a495dfddd1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-12.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-13.html b/testing/performance/talos/page_load_test/jss/core-eval-13.html new file mode 100644 index 000000000000..3b004aa3b7af --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-13.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-14.html b/testing/performance/talos/page_load_test/jss/core-eval-14.html new file mode 100644 index 000000000000..1b73d62c89fe --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-14.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-15.html b/testing/performance/talos/page_load_test/jss/core-eval-15.html new file mode 100644 index 000000000000..a1fb07105e8b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-15.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-16.html b/testing/performance/talos/page_load_test/jss/core-eval-16.html new file mode 100644 index 000000000000..17c311a7d409 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-16.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-2.html b/testing/performance/talos/page_load_test/jss/core-eval-2.html new file mode 100644 index 000000000000..1544e5e08a04 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-2.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-3.html b/testing/performance/talos/page_load_test/jss/core-eval-3.html new file mode 100644 index 000000000000..6e096b2ac495 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-3.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-4.html b/testing/performance/talos/page_load_test/jss/core-eval-4.html new file mode 100644 index 000000000000..5e5880656cbb --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-4.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-5.html b/testing/performance/talos/page_load_test/jss/core-eval-5.html new file mode 100644 index 000000000000..7eab179c40be --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-5.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-6.html b/testing/performance/talos/page_load_test/jss/core-eval-6.html new file mode 100644 index 000000000000..5b3cd137a771 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-6.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-7.html b/testing/performance/talos/page_load_test/jss/core-eval-7.html new file mode 100644 index 000000000000..e7fe918312e3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-7.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-8.html b/testing/performance/talos/page_load_test/jss/core-eval-8.html new file mode 100644 index 000000000000..fb2ba3ca6c42 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-8.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/core-eval-9.html b/testing/performance/talos/page_load_test/jss/core-eval-9.html new file mode 100644 index 000000000000..0f13732c409e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/core-eval-9.html @@ -0,0 +1,57 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/jss.manifest b/testing/performance/talos/page_load_test/jss/jss.manifest new file mode 100644 index 000000000000..c202f3cc71b4 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/jss.manifest @@ -0,0 +1,334 @@ +% http://localhost/page_load_test/jss/core-eval-1.html +% http://localhost/page_load_test/jss/core-eval-10.html +% http://localhost/page_load_test/jss/core-eval-11.html +% http://localhost/page_load_test/jss/core-eval-12.html +% http://localhost/page_load_test/jss/core-eval-13.html +% http://localhost/page_load_test/jss/core-eval-14.html +% http://localhost/page_load_test/jss/core-eval-15.html +% http://localhost/page_load_test/jss/core-eval-16.html +% http://localhost/page_load_test/jss/core-eval-2.html +% http://localhost/page_load_test/jss/core-eval-3.html +% http://localhost/page_load_test/jss/core-eval-4.html +% http://localhost/page_load_test/jss/core-eval-5.html +% http://localhost/page_load_test/jss/core-eval-6.html +% http://localhost/page_load_test/jss/core-eval-7.html +% http://localhost/page_load_test/jss/core-eval-8.html +% http://localhost/page_load_test/jss/core-eval-9.html +% http://localhost/page_load_test/jss/object-array-1.html +% http://localhost/page_load_test/jss/object-array-10.html +% http://localhost/page_load_test/jss/object-array-11.html +% http://localhost/page_load_test/jss/object-array-12.html +% http://localhost/page_load_test/jss/object-array-13.html +% http://localhost/page_load_test/jss/object-array-14.html +% http://localhost/page_load_test/jss/object-array-15.html +% http://localhost/page_load_test/jss/object-array-16.html +% http://localhost/page_load_test/jss/object-array-17.html +% http://localhost/page_load_test/jss/object-array-18.html +% http://localhost/page_load_test/jss/object-array-19.html +% http://localhost/page_load_test/jss/object-array-2.html +% http://localhost/page_load_test/jss/object-array-20.html +% http://localhost/page_load_test/jss/object-array-21.html +% http://localhost/page_load_test/jss/object-array-22.html +% http://localhost/page_load_test/jss/object-array-23.html +% http://localhost/page_load_test/jss/object-array-24.html +% http://localhost/page_load_test/jss/object-array-25.html +% http://localhost/page_load_test/jss/object-array-26.html +% http://localhost/page_load_test/jss/object-array-27.html +% http://localhost/page_load_test/jss/object-array-28.html +% http://localhost/page_load_test/jss/object-array-29.html +% http://localhost/page_load_test/jss/object-array-3.html +% http://localhost/page_load_test/jss/object-array-30.html +% http://localhost/page_load_test/jss/object-array-31.html +% http://localhost/page_load_test/jss/object-array-32.html +% http://localhost/page_load_test/jss/object-array-4.html +% http://localhost/page_load_test/jss/object-array-5.html +% http://localhost/page_load_test/jss/object-array-6.html +% http://localhost/page_load_test/jss/object-array-7.html +% http://localhost/page_load_test/jss/object-array-8.html +% http://localhost/page_load_test/jss/object-array-9.html +% http://localhost/page_load_test/jss/object-regexp-1.html +% http://localhost/page_load_test/jss/object-regexp-10.html +% http://localhost/page_load_test/jss/object-regexp-100.html +% http://localhost/page_load_test/jss/object-regexp-101.html +% http://localhost/page_load_test/jss/object-regexp-102.html +% http://localhost/page_load_test/jss/object-regexp-103.html +% http://localhost/page_load_test/jss/object-regexp-104.html +% http://localhost/page_load_test/jss/object-regexp-105.html +% http://localhost/page_load_test/jss/object-regexp-106.html +% http://localhost/page_load_test/jss/object-regexp-107.html +% http://localhost/page_load_test/jss/object-regexp-108.html +% http://localhost/page_load_test/jss/object-regexp-109.html +% http://localhost/page_load_test/jss/object-regexp-11.html +% http://localhost/page_load_test/jss/object-regexp-110.html +% http://localhost/page_load_test/jss/object-regexp-111.html +% http://localhost/page_load_test/jss/object-regexp-112.html +% http://localhost/page_load_test/jss/object-regexp-113.html +% http://localhost/page_load_test/jss/object-regexp-114.html +% http://localhost/page_load_test/jss/object-regexp-115.html +% http://localhost/page_load_test/jss/object-regexp-116.html +% http://localhost/page_load_test/jss/object-regexp-117.html +% http://localhost/page_load_test/jss/object-regexp-118.html +% http://localhost/page_load_test/jss/object-regexp-119.html +% http://localhost/page_load_test/jss/object-regexp-12.html +% http://localhost/page_load_test/jss/object-regexp-120.html +% http://localhost/page_load_test/jss/object-regexp-121.html +% http://localhost/page_load_test/jss/object-regexp-122.html +% http://localhost/page_load_test/jss/object-regexp-123.html +% http://localhost/page_load_test/jss/object-regexp-124.html +% http://localhost/page_load_test/jss/object-regexp-125.html +% http://localhost/page_load_test/jss/object-regexp-126.html +% http://localhost/page_load_test/jss/object-regexp-127.html +% http://localhost/page_load_test/jss/object-regexp-128.html +% http://localhost/page_load_test/jss/object-regexp-129.html +% http://localhost/page_load_test/jss/object-regexp-13.html +% http://localhost/page_load_test/jss/object-regexp-130.html +% http://localhost/page_load_test/jss/object-regexp-14.html +% http://localhost/page_load_test/jss/object-regexp-15.html +% http://localhost/page_load_test/jss/object-regexp-16.html +% http://localhost/page_load_test/jss/object-regexp-17.html +% http://localhost/page_load_test/jss/object-regexp-18.html +% http://localhost/page_load_test/jss/object-regexp-19.html +% http://localhost/page_load_test/jss/object-regexp-2.html +% http://localhost/page_load_test/jss/object-regexp-20.html +% http://localhost/page_load_test/jss/object-regexp-21.html +% http://localhost/page_load_test/jss/object-regexp-22.html +% http://localhost/page_load_test/jss/object-regexp-23.html +% http://localhost/page_load_test/jss/object-regexp-24.html +% http://localhost/page_load_test/jss/object-regexp-25.html +% http://localhost/page_load_test/jss/object-regexp-26.html +% http://localhost/page_load_test/jss/object-regexp-27.html +% http://localhost/page_load_test/jss/object-regexp-28.html +% http://localhost/page_load_test/jss/object-regexp-29.html +% http://localhost/page_load_test/jss/object-regexp-3.html +% http://localhost/page_load_test/jss/object-regexp-30.html +% http://localhost/page_load_test/jss/object-regexp-31.html +% http://localhost/page_load_test/jss/object-regexp-32.html +% http://localhost/page_load_test/jss/object-regexp-33.html +% http://localhost/page_load_test/jss/object-regexp-34.html +% http://localhost/page_load_test/jss/object-regexp-35.html +% http://localhost/page_load_test/jss/object-regexp-36.html +% http://localhost/page_load_test/jss/object-regexp-37.html +% http://localhost/page_load_test/jss/object-regexp-38.html +% http://localhost/page_load_test/jss/object-regexp-39.html +% http://localhost/page_load_test/jss/object-regexp-4.html +% http://localhost/page_load_test/jss/object-regexp-40.html +% http://localhost/page_load_test/jss/object-regexp-41.html +% http://localhost/page_load_test/jss/object-regexp-42.html +% http://localhost/page_load_test/jss/object-regexp-43.html +% http://localhost/page_load_test/jss/object-regexp-44.html +% http://localhost/page_load_test/jss/object-regexp-45.html +% http://localhost/page_load_test/jss/object-regexp-46.html +% http://localhost/page_load_test/jss/object-regexp-47.html +% http://localhost/page_load_test/jss/object-regexp-48.html +% http://localhost/page_load_test/jss/object-regexp-49.html +% http://localhost/page_load_test/jss/object-regexp-5.html +% http://localhost/page_load_test/jss/object-regexp-50.html +% http://localhost/page_load_test/jss/object-regexp-51.html +% http://localhost/page_load_test/jss/object-regexp-52.html +% http://localhost/page_load_test/jss/object-regexp-53.html +% http://localhost/page_load_test/jss/object-regexp-54.html +% http://localhost/page_load_test/jss/object-regexp-55.html +% http://localhost/page_load_test/jss/object-regexp-56.html +% http://localhost/page_load_test/jss/object-regexp-57.html +% http://localhost/page_load_test/jss/object-regexp-58.html +% http://localhost/page_load_test/jss/object-regexp-59.html +% http://localhost/page_load_test/jss/object-regexp-6.html +% http://localhost/page_load_test/jss/object-regexp-60.html +% http://localhost/page_load_test/jss/object-regexp-61.html +% http://localhost/page_load_test/jss/object-regexp-62.html +% http://localhost/page_load_test/jss/object-regexp-63.html +% http://localhost/page_load_test/jss/object-regexp-64.html +% http://localhost/page_load_test/jss/object-regexp-65.html +% http://localhost/page_load_test/jss/object-regexp-66.html +% http://localhost/page_load_test/jss/object-regexp-67.html +% http://localhost/page_load_test/jss/object-regexp-68.html +% http://localhost/page_load_test/jss/object-regexp-69.html +% http://localhost/page_load_test/jss/object-regexp-7.html +% http://localhost/page_load_test/jss/object-regexp-70.html +% http://localhost/page_load_test/jss/object-regexp-71.html +% http://localhost/page_load_test/jss/object-regexp-72.html +% http://localhost/page_load_test/jss/object-regexp-73.html +% http://localhost/page_load_test/jss/object-regexp-74.html +% http://localhost/page_load_test/jss/object-regexp-75.html +% http://localhost/page_load_test/jss/object-regexp-76.html +% http://localhost/page_load_test/jss/object-regexp-77.html +% http://localhost/page_load_test/jss/object-regexp-78.html +% http://localhost/page_load_test/jss/object-regexp-79.html +% http://localhost/page_load_test/jss/object-regexp-8.html +% http://localhost/page_load_test/jss/object-regexp-80.html +% http://localhost/page_load_test/jss/object-regexp-81.html +% http://localhost/page_load_test/jss/object-regexp-82.html +% http://localhost/page_load_test/jss/object-regexp-83.html +% http://localhost/page_load_test/jss/object-regexp-84.html +% http://localhost/page_load_test/jss/object-regexp-85.html +% http://localhost/page_load_test/jss/object-regexp-86.html +% http://localhost/page_load_test/jss/object-regexp-87.html +% http://localhost/page_load_test/jss/object-regexp-88.html +% http://localhost/page_load_test/jss/object-regexp-89.html +% http://localhost/page_load_test/jss/object-regexp-9.html +% http://localhost/page_load_test/jss/object-regexp-90.html +% http://localhost/page_load_test/jss/object-regexp-91.html +% http://localhost/page_load_test/jss/object-regexp-92.html +% http://localhost/page_load_test/jss/object-regexp-93.html +% http://localhost/page_load_test/jss/object-regexp-94.html +% http://localhost/page_load_test/jss/object-regexp-95.html +% http://localhost/page_load_test/jss/object-regexp-96.html +% http://localhost/page_load_test/jss/object-regexp-97.html +% http://localhost/page_load_test/jss/object-regexp-98.html +% http://localhost/page_load_test/jss/object-regexp-99.html +% http://localhost/page_load_test/jss/object-string-1.html +% http://localhost/page_load_test/jss/object-string-10.html +% http://localhost/page_load_test/jss/object-string-11.html +% http://localhost/page_load_test/jss/object-string-12.html +% http://localhost/page_load_test/jss/object-string-13.html +% http://localhost/page_load_test/jss/object-string-14.html +% http://localhost/page_load_test/jss/object-string-15.html +% http://localhost/page_load_test/jss/object-string-16.html +% http://localhost/page_load_test/jss/object-string-17.html +% http://localhost/page_load_test/jss/object-string-18.html +% http://localhost/page_load_test/jss/object-string-19.html +% http://localhost/page_load_test/jss/object-string-2.html +% http://localhost/page_load_test/jss/object-string-20.html +% http://localhost/page_load_test/jss/object-string-21.html +% http://localhost/page_load_test/jss/object-string-22.html +% http://localhost/page_load_test/jss/object-string-23.html +% http://localhost/page_load_test/jss/object-string-24.html +% http://localhost/page_load_test/jss/object-string-25.html +% http://localhost/page_load_test/jss/object-string-26.html +% http://localhost/page_load_test/jss/object-string-27.html +% http://localhost/page_load_test/jss/object-string-28.html +% http://localhost/page_load_test/jss/object-string-29.html +% http://localhost/page_load_test/jss/object-string-3.html +% http://localhost/page_load_test/jss/object-string-30.html +% http://localhost/page_load_test/jss/object-string-31.html +% http://localhost/page_load_test/jss/object-string-32.html +% http://localhost/page_load_test/jss/object-string-33.html +% http://localhost/page_load_test/jss/object-string-34.html +% http://localhost/page_load_test/jss/object-string-35.html +% http://localhost/page_load_test/jss/object-string-36.html +% http://localhost/page_load_test/jss/object-string-37.html +% http://localhost/page_load_test/jss/object-string-38.html +% http://localhost/page_load_test/jss/object-string-39.html +% http://localhost/page_load_test/jss/object-string-4.html +% http://localhost/page_load_test/jss/object-string-40.html +% http://localhost/page_load_test/jss/object-string-41.html +% http://localhost/page_load_test/jss/object-string-42.html +% http://localhost/page_load_test/jss/object-string-43.html +% http://localhost/page_load_test/jss/object-string-44.html +% http://localhost/page_load_test/jss/object-string-45.html +% http://localhost/page_load_test/jss/object-string-46.html +% http://localhost/page_load_test/jss/object-string-47.html +% http://localhost/page_load_test/jss/object-string-48.html +% http://localhost/page_load_test/jss/object-string-49.html +% http://localhost/page_load_test/jss/object-string-5.html +% http://localhost/page_load_test/jss/object-string-50.html +% http://localhost/page_load_test/jss/object-string-51.html +% http://localhost/page_load_test/jss/object-string-52.html +% http://localhost/page_load_test/jss/object-string-53.html +% http://localhost/page_load_test/jss/object-string-54.html +% http://localhost/page_load_test/jss/object-string-55.html +% http://localhost/page_load_test/jss/object-string-56.html +% http://localhost/page_load_test/jss/object-string-57.html +% http://localhost/page_load_test/jss/object-string-58.html +% http://localhost/page_load_test/jss/object-string-59.html +% http://localhost/page_load_test/jss/object-string-6.html +% http://localhost/page_load_test/jss/object-string-60.html +% http://localhost/page_load_test/jss/object-string-61.html +% http://localhost/page_load_test/jss/object-string-62.html +% http://localhost/page_load_test/jss/object-string-63.html +% http://localhost/page_load_test/jss/object-string-64.html +% http://localhost/page_load_test/jss/object-string-65.html +% http://localhost/page_load_test/jss/object-string-66.html +% http://localhost/page_load_test/jss/object-string-67.html +% http://localhost/page_load_test/jss/object-string-68.html +% http://localhost/page_load_test/jss/object-string-69.html +% http://localhost/page_load_test/jss/object-string-7.html +% http://localhost/page_load_test/jss/object-string-70.html +% http://localhost/page_load_test/jss/object-string-71.html +% http://localhost/page_load_test/jss/object-string-72.html +% http://localhost/page_load_test/jss/object-string-73.html +% http://localhost/page_load_test/jss/object-string-74.html +% http://localhost/page_load_test/jss/object-string-75.html +% http://localhost/page_load_test/jss/object-string-76.html +% http://localhost/page_load_test/jss/object-string-77.html +% http://localhost/page_load_test/jss/object-string-78.html +% http://localhost/page_load_test/jss/object-string-79.html +% http://localhost/page_load_test/jss/object-string-8.html +% http://localhost/page_load_test/jss/object-string-80.html +% http://localhost/page_load_test/jss/object-string-81.html +% http://localhost/page_load_test/jss/object-string-82.html +% http://localhost/page_load_test/jss/object-string-83.html +% http://localhost/page_load_test/jss/object-string-84.html +% http://localhost/page_load_test/jss/object-string-9.html +% http://localhost/page_load_test/jss/real-base64-1.html +% http://localhost/page_load_test/jss/real-base64-2.html +% http://localhost/page_load_test/jss/real-base64-3.html +% http://localhost/page_load_test/jss/real-base64-4.html +% http://localhost/page_load_test/jss/real-base64-5.html +% http://localhost/page_load_test/jss/real-base64-6.html +% http://localhost/page_load_test/jss/real-base64-7.html +% http://localhost/page_load_test/jss/real-base64-8.html +% http://localhost/page_load_test/jss/real-binary-trees-1.html +% http://localhost/page_load_test/jss/real-binary-trees-2.html +% http://localhost/page_load_test/jss/real-binary-trees-3.html +% http://localhost/page_load_test/jss/real-cube-1.html +% http://localhost/page_load_test/jss/real-cube-2.html +% http://localhost/page_load_test/jss/real-cube-3.html +% http://localhost/page_load_test/jss/real-cube-4.html +% http://localhost/page_load_test/jss/real-fannkuch-1.html +% http://localhost/page_load_test/jss/real-fannkuch-2.html +% http://localhost/page_load_test/jss/real-fannkuch-3.html +% http://localhost/page_load_test/jss/real-fannkuch-4.html +% http://localhost/page_load_test/jss/real-fasta-1.html +% http://localhost/page_load_test/jss/real-fasta-10.html +% http://localhost/page_load_test/jss/real-fasta-11.html +% http://localhost/page_load_test/jss/real-fasta-12.html +% http://localhost/page_load_test/jss/real-fasta-2.html +% http://localhost/page_load_test/jss/real-fasta-3.html +% http://localhost/page_load_test/jss/real-fasta-4.html +% http://localhost/page_load_test/jss/real-fasta-5.html +% http://localhost/page_load_test/jss/real-fasta-6.html +% http://localhost/page_load_test/jss/real-fasta-7.html +% http://localhost/page_load_test/jss/real-fasta-8.html +% http://localhost/page_load_test/jss/real-fasta-9.html +% http://localhost/page_load_test/jss/real-morph-1.html +% http://localhost/page_load_test/jss/real-morph-2.html +% http://localhost/page_load_test/jss/real-morph-3.html +% http://localhost/page_load_test/jss/real-morph-4.html +% http://localhost/page_load_test/jss/real-nbody-1.html +% http://localhost/page_load_test/jss/real-nbody-2.html +% http://localhost/page_load_test/jss/real-nbody-3.html +% http://localhost/page_load_test/jss/real-nbody-4.html +% http://localhost/page_load_test/jss/real-nsieve-1.html +% http://localhost/page_load_test/jss/real-nsieve-2.html +% http://localhost/page_load_test/jss/real-nsieve-3.html +% http://localhost/page_load_test/jss/real-nsieve-4.html +% http://localhost/page_load_test/jss/real-nsieve-bits-1.html +% http://localhost/page_load_test/jss/real-nsieve-bits-2.html +% http://localhost/page_load_test/jss/real-nsieve-bits-3.html +% http://localhost/page_load_test/jss/real-nsieve-bits-4.html +% http://localhost/page_load_test/jss/real-packer-1.html +% http://localhost/page_load_test/jss/real-packer-2.html +% http://localhost/page_load_test/jss/real-packer-3.html +% http://localhost/page_load_test/jss/real-packer-4.html +% http://localhost/page_load_test/jss/real-packer-5.html +% http://localhost/page_load_test/jss/real-partial-sums-1.html +% http://localhost/page_load_test/jss/real-partial-sums-2.html +% http://localhost/page_load_test/jss/real-partial-sums-3.html +% http://localhost/page_load_test/jss/real-partial-sums-4.html +% http://localhost/page_load_test/jss/real-recursive-1.html +% http://localhost/page_load_test/jss/real-recursive-10.html +% http://localhost/page_load_test/jss/real-recursive-11.html +% http://localhost/page_load_test/jss/real-recursive-12.html +% http://localhost/page_load_test/jss/real-recursive-2.html +% http://localhost/page_load_test/jss/real-recursive-3.html +% http://localhost/page_load_test/jss/real-recursive-4.html +% http://localhost/page_load_test/jss/real-recursive-5.html +% http://localhost/page_load_test/jss/real-recursive-6.html +% http://localhost/page_load_test/jss/real-recursive-7.html +% http://localhost/page_load_test/jss/real-recursive-8.html +% http://localhost/page_load_test/jss/real-recursive-9.html +% http://localhost/page_load_test/jss/real-spectral-norm-1.html +% http://localhost/page_load_test/jss/real-spectral-norm-2.html +% http://localhost/page_load_test/jss/real-spectral-norm-3.html +% http://localhost/page_load_test/jss/real-spectral-norm-4.html diff --git a/testing/performance/talos/page_load_test/jss/object-array-1.html b/testing/performance/talos/page_load_test/jss/object-array-1.html new file mode 100644 index 000000000000..a6a794931048 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-1.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-10.html b/testing/performance/talos/page_load_test/jss/object-array-10.html new file mode 100644 index 000000000000..ad94336b5c3b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-10.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-11.html b/testing/performance/talos/page_load_test/jss/object-array-11.html new file mode 100644 index 000000000000..10722337f47e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-11.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-12.html b/testing/performance/talos/page_load_test/jss/object-array-12.html new file mode 100644 index 000000000000..343d7812540e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-12.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-13.html b/testing/performance/talos/page_load_test/jss/object-array-13.html new file mode 100644 index 000000000000..f1823356fffa --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-13.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-14.html b/testing/performance/talos/page_load_test/jss/object-array-14.html new file mode 100644 index 000000000000..7248c694f899 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-14.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-15.html b/testing/performance/talos/page_load_test/jss/object-array-15.html new file mode 100644 index 000000000000..9db8b9bda57b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-15.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-16.html b/testing/performance/talos/page_load_test/jss/object-array-16.html new file mode 100644 index 000000000000..10a0490f2446 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-16.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-17.html b/testing/performance/talos/page_load_test/jss/object-array-17.html new file mode 100644 index 000000000000..67b0882822a7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-17.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-18.html b/testing/performance/talos/page_load_test/jss/object-array-18.html new file mode 100644 index 000000000000..56a90aebe5ee --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-18.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-19.html b/testing/performance/talos/page_load_test/jss/object-array-19.html new file mode 100644 index 000000000000..4d7423754f31 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-19.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-2.html b/testing/performance/talos/page_load_test/jss/object-array-2.html new file mode 100644 index 000000000000..bd181eb6a7a2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-2.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-20.html b/testing/performance/talos/page_load_test/jss/object-array-20.html new file mode 100644 index 000000000000..f0650e030330 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-20.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-21.html b/testing/performance/talos/page_load_test/jss/object-array-21.html new file mode 100644 index 000000000000..944ce2d25747 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-21.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-22.html b/testing/performance/talos/page_load_test/jss/object-array-22.html new file mode 100644 index 000000000000..6adcad3fe250 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-22.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-23.html b/testing/performance/talos/page_load_test/jss/object-array-23.html new file mode 100644 index 000000000000..36f9113d0763 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-23.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-24.html b/testing/performance/talos/page_load_test/jss/object-array-24.html new file mode 100644 index 000000000000..19ae8bf4e038 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-24.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-25.html b/testing/performance/talos/page_load_test/jss/object-array-25.html new file mode 100644 index 000000000000..f8f429dfdad4 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-25.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-26.html b/testing/performance/talos/page_load_test/jss/object-array-26.html new file mode 100644 index 000000000000..178134348921 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-26.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-27.html b/testing/performance/talos/page_load_test/jss/object-array-27.html new file mode 100644 index 000000000000..5820fcd649f7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-27.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-28.html b/testing/performance/talos/page_load_test/jss/object-array-28.html new file mode 100644 index 000000000000..5964c76574c0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-28.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-29.html b/testing/performance/talos/page_load_test/jss/object-array-29.html new file mode 100644 index 000000000000..32d5de69bae1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-29.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-3.html b/testing/performance/talos/page_load_test/jss/object-array-3.html new file mode 100644 index 000000000000..226be223ddb6 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-3.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-30.html b/testing/performance/talos/page_load_test/jss/object-array-30.html new file mode 100644 index 000000000000..b30ffad55104 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-30.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-31.html b/testing/performance/talos/page_load_test/jss/object-array-31.html new file mode 100644 index 000000000000..1cd7b990446e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-31.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-32.html b/testing/performance/talos/page_load_test/jss/object-array-32.html new file mode 100644 index 000000000000..02f49b3db5c6 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-32.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-4.html b/testing/performance/talos/page_load_test/jss/object-array-4.html new file mode 100644 index 000000000000..3ce4b31cc395 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-4.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-5.html b/testing/performance/talos/page_load_test/jss/object-array-5.html new file mode 100644 index 000000000000..6699f7fb98e2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-5.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-6.html b/testing/performance/talos/page_load_test/jss/object-array-6.html new file mode 100644 index 000000000000..3ac5c5d6f0e2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-6.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-7.html b/testing/performance/talos/page_load_test/jss/object-array-7.html new file mode 100644 index 000000000000..6ca19592b250 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-7.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-8.html b/testing/performance/talos/page_load_test/jss/object-array-8.html new file mode 100644 index 000000000000..fb890c01288c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-8.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-array-9.html b/testing/performance/talos/page_load_test/jss/object-array-9.html new file mode 100644 index 000000000000..00ba5195eef0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-array-9.html @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-1.html b/testing/performance/talos/page_load_test/jss/object-regexp-1.html new file mode 100644 index 000000000000..369db67530cc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-1.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-10.html b/testing/performance/talos/page_load_test/jss/object-regexp-10.html new file mode 100644 index 000000000000..255a887a5494 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-10.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-100.html b/testing/performance/talos/page_load_test/jss/object-regexp-100.html new file mode 100644 index 000000000000..1a6141c69d2c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-100.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-101.html b/testing/performance/talos/page_load_test/jss/object-regexp-101.html new file mode 100644 index 000000000000..5f17cc585391 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-101.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-102.html b/testing/performance/talos/page_load_test/jss/object-regexp-102.html new file mode 100644 index 000000000000..49035c2ec3b5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-102.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-103.html b/testing/performance/talos/page_load_test/jss/object-regexp-103.html new file mode 100644 index 000000000000..2171e338d0d5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-103.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-104.html b/testing/performance/talos/page_load_test/jss/object-regexp-104.html new file mode 100644 index 000000000000..55b6d042ba7e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-104.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-105.html b/testing/performance/talos/page_load_test/jss/object-regexp-105.html new file mode 100644 index 000000000000..868ab51455c7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-105.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-106.html b/testing/performance/talos/page_load_test/jss/object-regexp-106.html new file mode 100644 index 000000000000..f0ee75a2fc0f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-106.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-107.html b/testing/performance/talos/page_load_test/jss/object-regexp-107.html new file mode 100644 index 000000000000..1eeeba46d213 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-107.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-108.html b/testing/performance/talos/page_load_test/jss/object-regexp-108.html new file mode 100644 index 000000000000..a98856f8b812 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-108.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-109.html b/testing/performance/talos/page_load_test/jss/object-regexp-109.html new file mode 100644 index 000000000000..ad7d323154b9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-109.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-11.html b/testing/performance/talos/page_load_test/jss/object-regexp-11.html new file mode 100644 index 000000000000..bf4c6389867b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-11.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-110.html b/testing/performance/talos/page_load_test/jss/object-regexp-110.html new file mode 100644 index 000000000000..46125a970218 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-110.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-111.html b/testing/performance/talos/page_load_test/jss/object-regexp-111.html new file mode 100644 index 000000000000..c15811142098 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-111.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-112.html b/testing/performance/talos/page_load_test/jss/object-regexp-112.html new file mode 100644 index 000000000000..cb11b883598e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-112.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-113.html b/testing/performance/talos/page_load_test/jss/object-regexp-113.html new file mode 100644 index 000000000000..337e1a29d275 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-113.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-114.html b/testing/performance/talos/page_load_test/jss/object-regexp-114.html new file mode 100644 index 000000000000..809f914d6105 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-114.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-115.html b/testing/performance/talos/page_load_test/jss/object-regexp-115.html new file mode 100644 index 000000000000..65eb40eec0fa --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-115.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-116.html b/testing/performance/talos/page_load_test/jss/object-regexp-116.html new file mode 100644 index 000000000000..0e191ea7e3aa --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-116.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-117.html b/testing/performance/talos/page_load_test/jss/object-regexp-117.html new file mode 100644 index 000000000000..630034b33ecf --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-117.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-118.html b/testing/performance/talos/page_load_test/jss/object-regexp-118.html new file mode 100644 index 000000000000..739d556219a3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-118.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-119.html b/testing/performance/talos/page_load_test/jss/object-regexp-119.html new file mode 100644 index 000000000000..b1329b54575f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-119.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-12.html b/testing/performance/talos/page_load_test/jss/object-regexp-12.html new file mode 100644 index 000000000000..099bea441088 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-12.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-120.html b/testing/performance/talos/page_load_test/jss/object-regexp-120.html new file mode 100644 index 000000000000..7197beef7e8f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-120.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-121.html b/testing/performance/talos/page_load_test/jss/object-regexp-121.html new file mode 100644 index 000000000000..1c059b6b742c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-121.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-122.html b/testing/performance/talos/page_load_test/jss/object-regexp-122.html new file mode 100644 index 000000000000..63ab0441adfb --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-122.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-123.html b/testing/performance/talos/page_load_test/jss/object-regexp-123.html new file mode 100644 index 000000000000..41841200dddb --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-123.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-124.html b/testing/performance/talos/page_load_test/jss/object-regexp-124.html new file mode 100644 index 000000000000..035278365d06 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-124.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-125.html b/testing/performance/talos/page_load_test/jss/object-regexp-125.html new file mode 100644 index 000000000000..b08f5767a53a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-125.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-126.html b/testing/performance/talos/page_load_test/jss/object-regexp-126.html new file mode 100644 index 000000000000..56b1bf6cf1a2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-126.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-127.html b/testing/performance/talos/page_load_test/jss/object-regexp-127.html new file mode 100644 index 000000000000..f4773453d87f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-127.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-128.html b/testing/performance/talos/page_load_test/jss/object-regexp-128.html new file mode 100644 index 000000000000..6b7299ac8bc8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-128.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-129.html b/testing/performance/talos/page_load_test/jss/object-regexp-129.html new file mode 100644 index 000000000000..cb789404cc23 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-129.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-13.html b/testing/performance/talos/page_load_test/jss/object-regexp-13.html new file mode 100644 index 000000000000..8fa51b8eb954 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-13.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-130.html b/testing/performance/talos/page_load_test/jss/object-regexp-130.html new file mode 100644 index 000000000000..fa2e4003837b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-130.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-14.html b/testing/performance/talos/page_load_test/jss/object-regexp-14.html new file mode 100644 index 000000000000..40e1c876bb55 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-14.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-15.html b/testing/performance/talos/page_load_test/jss/object-regexp-15.html new file mode 100644 index 000000000000..fba3496ceea6 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-15.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-16.html b/testing/performance/talos/page_load_test/jss/object-regexp-16.html new file mode 100644 index 000000000000..2bac1a382f7a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-16.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-17.html b/testing/performance/talos/page_load_test/jss/object-regexp-17.html new file mode 100644 index 000000000000..d6af52ae87f1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-17.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-18.html b/testing/performance/talos/page_load_test/jss/object-regexp-18.html new file mode 100644 index 000000000000..923378d61a5b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-18.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-19.html b/testing/performance/talos/page_load_test/jss/object-regexp-19.html new file mode 100644 index 000000000000..4e7c4326b298 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-19.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-2.html b/testing/performance/talos/page_load_test/jss/object-regexp-2.html new file mode 100644 index 000000000000..8325f5bf9ed5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-2.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-20.html b/testing/performance/talos/page_load_test/jss/object-regexp-20.html new file mode 100644 index 000000000000..689b12169030 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-20.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-21.html b/testing/performance/talos/page_load_test/jss/object-regexp-21.html new file mode 100644 index 000000000000..d24085ac84e1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-21.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-22.html b/testing/performance/talos/page_load_test/jss/object-regexp-22.html new file mode 100644 index 000000000000..9bcd178e7165 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-22.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-23.html b/testing/performance/talos/page_load_test/jss/object-regexp-23.html new file mode 100644 index 000000000000..64698f8fed2e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-23.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-24.html b/testing/performance/talos/page_load_test/jss/object-regexp-24.html new file mode 100644 index 000000000000..44cf783afb22 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-24.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-25.html b/testing/performance/talos/page_load_test/jss/object-regexp-25.html new file mode 100644 index 000000000000..ca17c526291c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-25.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-26.html b/testing/performance/talos/page_load_test/jss/object-regexp-26.html new file mode 100644 index 000000000000..bef87dfc1a98 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-26.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-27.html b/testing/performance/talos/page_load_test/jss/object-regexp-27.html new file mode 100644 index 000000000000..a2fb53e25093 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-27.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-28.html b/testing/performance/talos/page_load_test/jss/object-regexp-28.html new file mode 100644 index 000000000000..85c3f24d8e27 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-28.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-29.html b/testing/performance/talos/page_load_test/jss/object-regexp-29.html new file mode 100644 index 000000000000..5d71d41c2b5e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-29.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-3.html b/testing/performance/talos/page_load_test/jss/object-regexp-3.html new file mode 100644 index 000000000000..6a79bf69bb92 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-3.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-30.html b/testing/performance/talos/page_load_test/jss/object-regexp-30.html new file mode 100644 index 000000000000..44d1c6089e1e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-30.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-31.html b/testing/performance/talos/page_load_test/jss/object-regexp-31.html new file mode 100644 index 000000000000..f1964bd579d2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-31.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-32.html b/testing/performance/talos/page_load_test/jss/object-regexp-32.html new file mode 100644 index 000000000000..60fa9d47e64a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-32.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-33.html b/testing/performance/talos/page_load_test/jss/object-regexp-33.html new file mode 100644 index 000000000000..737940b4314e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-33.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-34.html b/testing/performance/talos/page_load_test/jss/object-regexp-34.html new file mode 100644 index 000000000000..4eca6d7e26ed --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-34.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-35.html b/testing/performance/talos/page_load_test/jss/object-regexp-35.html new file mode 100644 index 000000000000..bae7e6ce1474 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-35.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-36.html b/testing/performance/talos/page_load_test/jss/object-regexp-36.html new file mode 100644 index 000000000000..be811e8419c2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-36.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-37.html b/testing/performance/talos/page_load_test/jss/object-regexp-37.html new file mode 100644 index 000000000000..b17484924fe4 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-37.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-38.html b/testing/performance/talos/page_load_test/jss/object-regexp-38.html new file mode 100644 index 000000000000..c42d8f098b6c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-38.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-39.html b/testing/performance/talos/page_load_test/jss/object-regexp-39.html new file mode 100644 index 000000000000..6ba84f4214f1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-39.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-4.html b/testing/performance/talos/page_load_test/jss/object-regexp-4.html new file mode 100644 index 000000000000..792b5ad11ab6 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-4.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-40.html b/testing/performance/talos/page_load_test/jss/object-regexp-40.html new file mode 100644 index 000000000000..8f5bdd48a464 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-40.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-41.html b/testing/performance/talos/page_load_test/jss/object-regexp-41.html new file mode 100644 index 000000000000..b7efa7df10db --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-41.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-42.html b/testing/performance/talos/page_load_test/jss/object-regexp-42.html new file mode 100644 index 000000000000..8e37999b0731 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-42.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-43.html b/testing/performance/talos/page_load_test/jss/object-regexp-43.html new file mode 100644 index 000000000000..02cadc3450b3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-43.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-44.html b/testing/performance/talos/page_load_test/jss/object-regexp-44.html new file mode 100644 index 000000000000..e278207859ca --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-44.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-45.html b/testing/performance/talos/page_load_test/jss/object-regexp-45.html new file mode 100644 index 000000000000..4137b8d180c7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-45.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-46.html b/testing/performance/talos/page_load_test/jss/object-regexp-46.html new file mode 100644 index 000000000000..70868e67861d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-46.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-47.html b/testing/performance/talos/page_load_test/jss/object-regexp-47.html new file mode 100644 index 000000000000..ed043fe2a1d8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-47.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-48.html b/testing/performance/talos/page_load_test/jss/object-regexp-48.html new file mode 100644 index 000000000000..c4d636327496 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-48.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-49.html b/testing/performance/talos/page_load_test/jss/object-regexp-49.html new file mode 100644 index 000000000000..9875ba862bc5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-49.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-5.html b/testing/performance/talos/page_load_test/jss/object-regexp-5.html new file mode 100644 index 000000000000..8d9f0f80f822 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-5.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-50.html b/testing/performance/talos/page_load_test/jss/object-regexp-50.html new file mode 100644 index 000000000000..deeada1612a3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-50.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-51.html b/testing/performance/talos/page_load_test/jss/object-regexp-51.html new file mode 100644 index 000000000000..d962167a1c8a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-51.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-52.html b/testing/performance/talos/page_load_test/jss/object-regexp-52.html new file mode 100644 index 000000000000..74a4779b23b9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-52.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-53.html b/testing/performance/talos/page_load_test/jss/object-regexp-53.html new file mode 100644 index 000000000000..a2868fccdeb9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-53.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-54.html b/testing/performance/talos/page_load_test/jss/object-regexp-54.html new file mode 100644 index 000000000000..3cd61f0f40b2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-54.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-55.html b/testing/performance/talos/page_load_test/jss/object-regexp-55.html new file mode 100644 index 000000000000..a8f2c627c7f5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-55.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-56.html b/testing/performance/talos/page_load_test/jss/object-regexp-56.html new file mode 100644 index 000000000000..01559a07fdba --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-56.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-57.html b/testing/performance/talos/page_load_test/jss/object-regexp-57.html new file mode 100644 index 000000000000..c9d4e050dad2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-57.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-58.html b/testing/performance/talos/page_load_test/jss/object-regexp-58.html new file mode 100644 index 000000000000..4a677251a064 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-58.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-59.html b/testing/performance/talos/page_load_test/jss/object-regexp-59.html new file mode 100644 index 000000000000..083d6ac0612a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-59.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-6.html b/testing/performance/talos/page_load_test/jss/object-regexp-6.html new file mode 100644 index 000000000000..9aab90832072 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-6.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-60.html b/testing/performance/talos/page_load_test/jss/object-regexp-60.html new file mode 100644 index 000000000000..402d4bff1e0a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-60.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-61.html b/testing/performance/talos/page_load_test/jss/object-regexp-61.html new file mode 100644 index 000000000000..cf6d6765fb04 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-61.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-62.html b/testing/performance/talos/page_load_test/jss/object-regexp-62.html new file mode 100644 index 000000000000..23077a733de7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-62.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-63.html b/testing/performance/talos/page_load_test/jss/object-regexp-63.html new file mode 100644 index 000000000000..de9dcc946a81 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-63.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-64.html b/testing/performance/talos/page_load_test/jss/object-regexp-64.html new file mode 100644 index 000000000000..2b25a33b23e8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-64.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-65.html b/testing/performance/talos/page_load_test/jss/object-regexp-65.html new file mode 100644 index 000000000000..bdbe9f437752 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-65.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-66.html b/testing/performance/talos/page_load_test/jss/object-regexp-66.html new file mode 100644 index 000000000000..871481f5a0fe --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-66.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-67.html b/testing/performance/talos/page_load_test/jss/object-regexp-67.html new file mode 100644 index 000000000000..8082daac5928 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-67.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-68.html b/testing/performance/talos/page_load_test/jss/object-regexp-68.html new file mode 100644 index 000000000000..525445057135 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-68.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-69.html b/testing/performance/talos/page_load_test/jss/object-regexp-69.html new file mode 100644 index 000000000000..47b7aaa3b6f5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-69.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-7.html b/testing/performance/talos/page_load_test/jss/object-regexp-7.html new file mode 100644 index 000000000000..28089c178ae7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-7.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-70.html b/testing/performance/talos/page_load_test/jss/object-regexp-70.html new file mode 100644 index 000000000000..2384f3205b04 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-70.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-71.html b/testing/performance/talos/page_load_test/jss/object-regexp-71.html new file mode 100644 index 000000000000..b973ceb6f6de --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-71.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-72.html b/testing/performance/talos/page_load_test/jss/object-regexp-72.html new file mode 100644 index 000000000000..5aaf44d8f17c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-72.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-73.html b/testing/performance/talos/page_load_test/jss/object-regexp-73.html new file mode 100644 index 000000000000..18603d978a5b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-73.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-74.html b/testing/performance/talos/page_load_test/jss/object-regexp-74.html new file mode 100644 index 000000000000..58b8838f6d35 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-74.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-75.html b/testing/performance/talos/page_load_test/jss/object-regexp-75.html new file mode 100644 index 000000000000..cf9bbc30cdc7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-75.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-76.html b/testing/performance/talos/page_load_test/jss/object-regexp-76.html new file mode 100644 index 000000000000..62ab6fa42971 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-76.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-77.html b/testing/performance/talos/page_load_test/jss/object-regexp-77.html new file mode 100644 index 000000000000..cdebd3d698b5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-77.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-78.html b/testing/performance/talos/page_load_test/jss/object-regexp-78.html new file mode 100644 index 000000000000..e3cc06f090ee --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-78.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-79.html b/testing/performance/talos/page_load_test/jss/object-regexp-79.html new file mode 100644 index 000000000000..a89f9a7659b2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-79.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-8.html b/testing/performance/talos/page_load_test/jss/object-regexp-8.html new file mode 100644 index 000000000000..0c4bdc55d462 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-8.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-80.html b/testing/performance/talos/page_load_test/jss/object-regexp-80.html new file mode 100644 index 000000000000..88064d6d605a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-80.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-81.html b/testing/performance/talos/page_load_test/jss/object-regexp-81.html new file mode 100644 index 000000000000..06be61381e4b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-81.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-82.html b/testing/performance/talos/page_load_test/jss/object-regexp-82.html new file mode 100644 index 000000000000..3eb2bac3a1dc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-82.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-83.html b/testing/performance/talos/page_load_test/jss/object-regexp-83.html new file mode 100644 index 000000000000..e44ae10971ba --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-83.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-84.html b/testing/performance/talos/page_load_test/jss/object-regexp-84.html new file mode 100644 index 000000000000..76ec6c1fdba0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-84.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-85.html b/testing/performance/talos/page_load_test/jss/object-regexp-85.html new file mode 100644 index 000000000000..0bba3017554c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-85.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-86.html b/testing/performance/talos/page_load_test/jss/object-regexp-86.html new file mode 100644 index 000000000000..9f8adb06235e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-86.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-87.html b/testing/performance/talos/page_load_test/jss/object-regexp-87.html new file mode 100644 index 000000000000..07cb4d337cf2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-87.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-88.html b/testing/performance/talos/page_load_test/jss/object-regexp-88.html new file mode 100644 index 000000000000..d61e5362e72f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-88.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-89.html b/testing/performance/talos/page_load_test/jss/object-regexp-89.html new file mode 100644 index 000000000000..44da564fea40 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-89.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-9.html b/testing/performance/talos/page_load_test/jss/object-regexp-9.html new file mode 100644 index 000000000000..11fbd9b9043e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-9.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-90.html b/testing/performance/talos/page_load_test/jss/object-regexp-90.html new file mode 100644 index 000000000000..e63c88810770 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-90.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-91.html b/testing/performance/talos/page_load_test/jss/object-regexp-91.html new file mode 100644 index 000000000000..f6f437b833fc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-91.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-92.html b/testing/performance/talos/page_load_test/jss/object-regexp-92.html new file mode 100644 index 000000000000..4bc05c884ad2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-92.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-93.html b/testing/performance/talos/page_load_test/jss/object-regexp-93.html new file mode 100644 index 000000000000..877c48a5bf9f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-93.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-94.html b/testing/performance/talos/page_load_test/jss/object-regexp-94.html new file mode 100644 index 000000000000..f25513e4c7e2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-94.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-95.html b/testing/performance/talos/page_load_test/jss/object-regexp-95.html new file mode 100644 index 000000000000..53a5e610db52 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-95.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-96.html b/testing/performance/talos/page_load_test/jss/object-regexp-96.html new file mode 100644 index 000000000000..4433156a4181 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-96.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-97.html b/testing/performance/talos/page_load_test/jss/object-regexp-97.html new file mode 100644 index 000000000000..a12a692988e3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-97.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-98.html b/testing/performance/talos/page_load_test/jss/object-regexp-98.html new file mode 100644 index 000000000000..3ce82fd92c07 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-98.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-regexp-99.html b/testing/performance/talos/page_load_test/jss/object-regexp-99.html new file mode 100644 index 000000000000..49528ebb070f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-regexp-99.html @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-1.html b/testing/performance/talos/page_load_test/jss/object-string-1.html new file mode 100644 index 000000000000..605a551609ff --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-1.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-10.html b/testing/performance/talos/page_load_test/jss/object-string-10.html new file mode 100644 index 000000000000..3cdae9f35612 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-10.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-11.html b/testing/performance/talos/page_load_test/jss/object-string-11.html new file mode 100644 index 000000000000..1c9e56a5ef67 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-11.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-12.html b/testing/performance/talos/page_load_test/jss/object-string-12.html new file mode 100644 index 000000000000..1983531e455f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-12.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-13.html b/testing/performance/talos/page_load_test/jss/object-string-13.html new file mode 100644 index 000000000000..b2d0ef45ec98 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-13.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-14.html b/testing/performance/talos/page_load_test/jss/object-string-14.html new file mode 100644 index 000000000000..5cea33c67ffd --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-14.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-15.html b/testing/performance/talos/page_load_test/jss/object-string-15.html new file mode 100644 index 000000000000..12fd17cccff1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-15.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-16.html b/testing/performance/talos/page_load_test/jss/object-string-16.html new file mode 100644 index 000000000000..bbfe63269ca0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-16.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-17.html b/testing/performance/talos/page_load_test/jss/object-string-17.html new file mode 100644 index 000000000000..ad9ec78ed06d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-17.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-18.html b/testing/performance/talos/page_load_test/jss/object-string-18.html new file mode 100644 index 000000000000..c2aa9926c234 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-18.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-19.html b/testing/performance/talos/page_load_test/jss/object-string-19.html new file mode 100644 index 000000000000..bec074ca4ebc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-19.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-2.html b/testing/performance/talos/page_load_test/jss/object-string-2.html new file mode 100644 index 000000000000..9171c62fcc6a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-2.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-20.html b/testing/performance/talos/page_load_test/jss/object-string-20.html new file mode 100644 index 000000000000..764dc394fe68 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-20.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-21.html b/testing/performance/talos/page_load_test/jss/object-string-21.html new file mode 100644 index 000000000000..2c1ff165c20b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-21.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-22.html b/testing/performance/talos/page_load_test/jss/object-string-22.html new file mode 100644 index 000000000000..0d26d3e390ac --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-22.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-23.html b/testing/performance/talos/page_load_test/jss/object-string-23.html new file mode 100644 index 000000000000..f643887c2606 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-23.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-24.html b/testing/performance/talos/page_load_test/jss/object-string-24.html new file mode 100644 index 000000000000..be52dd68ff50 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-24.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-25.html b/testing/performance/talos/page_load_test/jss/object-string-25.html new file mode 100644 index 000000000000..fa539600d51e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-25.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-26.html b/testing/performance/talos/page_load_test/jss/object-string-26.html new file mode 100644 index 000000000000..6d872da300f2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-26.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-27.html b/testing/performance/talos/page_load_test/jss/object-string-27.html new file mode 100644 index 000000000000..cec72bc44e8e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-27.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-28.html b/testing/performance/talos/page_load_test/jss/object-string-28.html new file mode 100644 index 000000000000..d5e2e55b7433 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-28.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-29.html b/testing/performance/talos/page_load_test/jss/object-string-29.html new file mode 100644 index 000000000000..57308e6c8d85 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-29.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-3.html b/testing/performance/talos/page_load_test/jss/object-string-3.html new file mode 100644 index 000000000000..02d2f13fc49e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-3.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-30.html b/testing/performance/talos/page_load_test/jss/object-string-30.html new file mode 100644 index 000000000000..f5003c9b0c0a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-30.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-31.html b/testing/performance/talos/page_load_test/jss/object-string-31.html new file mode 100644 index 000000000000..c5a4f30f295d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-31.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-32.html b/testing/performance/talos/page_load_test/jss/object-string-32.html new file mode 100644 index 000000000000..49ab56fe0b49 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-32.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-33.html b/testing/performance/talos/page_load_test/jss/object-string-33.html new file mode 100644 index 000000000000..864bb48f2140 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-33.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-34.html b/testing/performance/talos/page_load_test/jss/object-string-34.html new file mode 100644 index 000000000000..4dbab684b9ca --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-34.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-35.html b/testing/performance/talos/page_load_test/jss/object-string-35.html new file mode 100644 index 000000000000..4609c7c382f0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-35.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-36.html b/testing/performance/talos/page_load_test/jss/object-string-36.html new file mode 100644 index 000000000000..d430ff539f46 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-36.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-37.html b/testing/performance/talos/page_load_test/jss/object-string-37.html new file mode 100644 index 000000000000..e40ac1f3cf8f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-37.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-38.html b/testing/performance/talos/page_load_test/jss/object-string-38.html new file mode 100644 index 000000000000..c212a543b148 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-38.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-39.html b/testing/performance/talos/page_load_test/jss/object-string-39.html new file mode 100644 index 000000000000..9a53d7304558 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-39.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-4.html b/testing/performance/talos/page_load_test/jss/object-string-4.html new file mode 100644 index 000000000000..d6caf6743834 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-4.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-40.html b/testing/performance/talos/page_load_test/jss/object-string-40.html new file mode 100644 index 000000000000..de8f850245fc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-40.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-41.html b/testing/performance/talos/page_load_test/jss/object-string-41.html new file mode 100644 index 000000000000..69b31151beea --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-41.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-42.html b/testing/performance/talos/page_load_test/jss/object-string-42.html new file mode 100644 index 000000000000..1310820e5d57 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-42.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-43.html b/testing/performance/talos/page_load_test/jss/object-string-43.html new file mode 100644 index 000000000000..076ca358fd18 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-43.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-44.html b/testing/performance/talos/page_load_test/jss/object-string-44.html new file mode 100644 index 000000000000..dc8534953f1e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-44.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-45.html b/testing/performance/talos/page_load_test/jss/object-string-45.html new file mode 100644 index 000000000000..0224f815ba32 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-45.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-46.html b/testing/performance/talos/page_load_test/jss/object-string-46.html new file mode 100644 index 000000000000..a3d6172b39f5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-46.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-47.html b/testing/performance/talos/page_load_test/jss/object-string-47.html new file mode 100644 index 000000000000..750a5a705ae7 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-47.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-48.html b/testing/performance/talos/page_load_test/jss/object-string-48.html new file mode 100644 index 000000000000..4d2baba22dc1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-48.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-49.html b/testing/performance/talos/page_load_test/jss/object-string-49.html new file mode 100644 index 000000000000..86523648105f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-49.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-5.html b/testing/performance/talos/page_load_test/jss/object-string-5.html new file mode 100644 index 000000000000..3b2f02f59633 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-5.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-50.html b/testing/performance/talos/page_load_test/jss/object-string-50.html new file mode 100644 index 000000000000..d562b14d17b8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-50.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-51.html b/testing/performance/talos/page_load_test/jss/object-string-51.html new file mode 100644 index 000000000000..3cdf314b09d1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-51.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-52.html b/testing/performance/talos/page_load_test/jss/object-string-52.html new file mode 100644 index 000000000000..a3cb4df55abc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-52.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-53.html b/testing/performance/talos/page_load_test/jss/object-string-53.html new file mode 100644 index 000000000000..1d67f8dd47d5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-53.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-54.html b/testing/performance/talos/page_load_test/jss/object-string-54.html new file mode 100644 index 000000000000..274d035c7293 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-54.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-55.html b/testing/performance/talos/page_load_test/jss/object-string-55.html new file mode 100644 index 000000000000..3b015e5d39c8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-55.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-56.html b/testing/performance/talos/page_load_test/jss/object-string-56.html new file mode 100644 index 000000000000..730a274ff624 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-56.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-57.html b/testing/performance/talos/page_load_test/jss/object-string-57.html new file mode 100644 index 000000000000..9198a5eba760 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-57.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-58.html b/testing/performance/talos/page_load_test/jss/object-string-58.html new file mode 100644 index 000000000000..bdf951713a0f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-58.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-59.html b/testing/performance/talos/page_load_test/jss/object-string-59.html new file mode 100644 index 000000000000..b2f7c0e1cc6a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-59.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-6.html b/testing/performance/talos/page_load_test/jss/object-string-6.html new file mode 100644 index 000000000000..e707decd5857 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-6.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-60.html b/testing/performance/talos/page_load_test/jss/object-string-60.html new file mode 100644 index 000000000000..955cc8b5fffa --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-60.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-61.html b/testing/performance/talos/page_load_test/jss/object-string-61.html new file mode 100644 index 000000000000..329d1ead2173 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-61.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-62.html b/testing/performance/talos/page_load_test/jss/object-string-62.html new file mode 100644 index 000000000000..5b8d32dadbea --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-62.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-63.html b/testing/performance/talos/page_load_test/jss/object-string-63.html new file mode 100644 index 000000000000..9740cc1e87c0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-63.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-64.html b/testing/performance/talos/page_load_test/jss/object-string-64.html new file mode 100644 index 000000000000..1021ee21f9e3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-64.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-65.html b/testing/performance/talos/page_load_test/jss/object-string-65.html new file mode 100644 index 000000000000..0768409d5131 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-65.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-66.html b/testing/performance/talos/page_load_test/jss/object-string-66.html new file mode 100644 index 000000000000..d4bfb5b5ef27 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-66.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-67.html b/testing/performance/talos/page_load_test/jss/object-string-67.html new file mode 100644 index 000000000000..8c594d2bf6ad --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-67.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-68.html b/testing/performance/talos/page_load_test/jss/object-string-68.html new file mode 100644 index 000000000000..6b154816b9b0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-68.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-69.html b/testing/performance/talos/page_load_test/jss/object-string-69.html new file mode 100644 index 000000000000..b6f197f02fed --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-69.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-7.html b/testing/performance/talos/page_load_test/jss/object-string-7.html new file mode 100644 index 000000000000..2e925ba5271e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-7.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-70.html b/testing/performance/talos/page_load_test/jss/object-string-70.html new file mode 100644 index 000000000000..f6d726f6f74a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-70.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-71.html b/testing/performance/talos/page_load_test/jss/object-string-71.html new file mode 100644 index 000000000000..dbe0528840b2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-71.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-72.html b/testing/performance/talos/page_load_test/jss/object-string-72.html new file mode 100644 index 000000000000..4a6a8eeda8b3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-72.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-73.html b/testing/performance/talos/page_load_test/jss/object-string-73.html new file mode 100644 index 000000000000..4beee5b25e42 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-73.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-74.html b/testing/performance/talos/page_load_test/jss/object-string-74.html new file mode 100644 index 000000000000..984d4bad516f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-74.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-75.html b/testing/performance/talos/page_load_test/jss/object-string-75.html new file mode 100644 index 000000000000..9b891e76b1d0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-75.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-76.html b/testing/performance/talos/page_load_test/jss/object-string-76.html new file mode 100644 index 000000000000..0f12f61521c1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-76.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-77.html b/testing/performance/talos/page_load_test/jss/object-string-77.html new file mode 100644 index 000000000000..083946a0d194 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-77.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-78.html b/testing/performance/talos/page_load_test/jss/object-string-78.html new file mode 100644 index 000000000000..e6889ddf32b0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-78.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-79.html b/testing/performance/talos/page_load_test/jss/object-string-79.html new file mode 100644 index 000000000000..d592db5790c9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-79.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-8.html b/testing/performance/talos/page_load_test/jss/object-string-8.html new file mode 100644 index 000000000000..ee4f72e7fdb3 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-8.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-80.html b/testing/performance/talos/page_load_test/jss/object-string-80.html new file mode 100644 index 000000000000..e24d658b6efe --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-80.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-81.html b/testing/performance/talos/page_load_test/jss/object-string-81.html new file mode 100644 index 000000000000..26184ba3cc70 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-81.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-82.html b/testing/performance/talos/page_load_test/jss/object-string-82.html new file mode 100644 index 000000000000..1de01676ef52 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-82.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-83.html b/testing/performance/talos/page_load_test/jss/object-string-83.html new file mode 100644 index 000000000000..10b1a090f1d9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-83.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-84.html b/testing/performance/talos/page_load_test/jss/object-string-84.html new file mode 100644 index 000000000000..a96aafc6875b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-84.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/object-string-9.html b/testing/performance/talos/page_load_test/jss/object-string-9.html new file mode 100644 index 000000000000..26d278bfc77f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/object-string-9.html @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-1.html b/testing/performance/talos/page_load_test/jss/real-base64-1.html new file mode 100644 index 000000000000..a76cb1d013cd --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-1.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-2.html b/testing/performance/talos/page_load_test/jss/real-base64-2.html new file mode 100644 index 000000000000..feee45daf922 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-2.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-3.html b/testing/performance/talos/page_load_test/jss/real-base64-3.html new file mode 100644 index 000000000000..a0ef197eb9dd --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-3.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-4.html b/testing/performance/talos/page_load_test/jss/real-base64-4.html new file mode 100644 index 000000000000..78e197cc5cc0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-4.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-5.html b/testing/performance/talos/page_load_test/jss/real-base64-5.html new file mode 100644 index 000000000000..c34dc620c417 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-5.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-6.html b/testing/performance/talos/page_load_test/jss/real-base64-6.html new file mode 100644 index 000000000000..298db1584f6d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-6.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-7.html b/testing/performance/talos/page_load_test/jss/real-base64-7.html new file mode 100644 index 000000000000..a89b8fa30444 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-7.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-base64-8.html b/testing/performance/talos/page_load_test/jss/real-base64-8.html new file mode 100644 index 000000000000..13f0fb500bdf --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-base64-8.html @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-binary-trees-1.html b/testing/performance/talos/page_load_test/jss/real-binary-trees-1.html new file mode 100644 index 000000000000..ee90411eb63f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-binary-trees-1.html @@ -0,0 +1,66 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-binary-trees-2.html b/testing/performance/talos/page_load_test/jss/real-binary-trees-2.html new file mode 100644 index 000000000000..c94bf885b92d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-binary-trees-2.html @@ -0,0 +1,66 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-binary-trees-3.html b/testing/performance/talos/page_load_test/jss/real-binary-trees-3.html new file mode 100644 index 000000000000..f6380f9c3c79 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-binary-trees-3.html @@ -0,0 +1,66 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-cube-1.html b/testing/performance/talos/page_load_test/jss/real-cube-1.html new file mode 100644 index 000000000000..a00693b9efb9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-cube-1.html @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-cube-2.html b/testing/performance/talos/page_load_test/jss/real-cube-2.html new file mode 100644 index 000000000000..e81b27850ccf --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-cube-2.html @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-cube-3.html b/testing/performance/talos/page_load_test/jss/real-cube-3.html new file mode 100644 index 000000000000..8f3bf8ca3c7e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-cube-3.html @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-cube-4.html b/testing/performance/talos/page_load_test/jss/real-cube-4.html new file mode 100644 index 000000000000..cc84b757ab0e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-cube-4.html @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fannkuch-1.html b/testing/performance/talos/page_load_test/jss/real-fannkuch-1.html new file mode 100644 index 000000000000..859ddebe66c9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fannkuch-1.html @@ -0,0 +1,84 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fannkuch-2.html b/testing/performance/talos/page_load_test/jss/real-fannkuch-2.html new file mode 100644 index 000000000000..77deb91fc593 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fannkuch-2.html @@ -0,0 +1,84 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fannkuch-3.html b/testing/performance/talos/page_load_test/jss/real-fannkuch-3.html new file mode 100644 index 000000000000..02ae920b4ed2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fannkuch-3.html @@ -0,0 +1,84 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fannkuch-4.html b/testing/performance/talos/page_load_test/jss/real-fannkuch-4.html new file mode 100644 index 000000000000..0de252c3395e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fannkuch-4.html @@ -0,0 +1,84 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-1.html b/testing/performance/talos/page_load_test/jss/real-fasta-1.html new file mode 100644 index 000000000000..4bdc51ecbbd8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-1.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-10.html b/testing/performance/talos/page_load_test/jss/real-fasta-10.html new file mode 100644 index 000000000000..91f56e8a8d42 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-10.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-11.html b/testing/performance/talos/page_load_test/jss/real-fasta-11.html new file mode 100644 index 000000000000..b8f0167c4e6f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-11.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-12.html b/testing/performance/talos/page_load_test/jss/real-fasta-12.html new file mode 100644 index 000000000000..c443423d1479 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-12.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-2.html b/testing/performance/talos/page_load_test/jss/real-fasta-2.html new file mode 100644 index 000000000000..78414e6253f5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-2.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-3.html b/testing/performance/talos/page_load_test/jss/real-fasta-3.html new file mode 100644 index 000000000000..225b713830c2 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-3.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-4.html b/testing/performance/talos/page_load_test/jss/real-fasta-4.html new file mode 100644 index 000000000000..e164ac3957bb --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-4.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-5.html b/testing/performance/talos/page_load_test/jss/real-fasta-5.html new file mode 100644 index 000000000000..8ed3130de2f9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-5.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-6.html b/testing/performance/talos/page_load_test/jss/real-fasta-6.html new file mode 100644 index 000000000000..987dbaf93a88 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-6.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-7.html b/testing/performance/talos/page_load_test/jss/real-fasta-7.html new file mode 100644 index 000000000000..cb450f1ef23b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-7.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-8.html b/testing/performance/talos/page_load_test/jss/real-fasta-8.html new file mode 100644 index 000000000000..998d1debb7d1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-8.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-fasta-9.html b/testing/performance/talos/page_load_test/jss/real-fasta-9.html new file mode 100644 index 000000000000..b86b8f333784 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-fasta-9.html @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-morph-1.html b/testing/performance/talos/page_load_test/jss/real-morph-1.html new file mode 100644 index 000000000000..4766abd819ce --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-morph-1.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-morph-2.html b/testing/performance/talos/page_load_test/jss/real-morph-2.html new file mode 100644 index 000000000000..e28ea746f299 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-morph-2.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-morph-3.html b/testing/performance/talos/page_load_test/jss/real-morph-3.html new file mode 100644 index 000000000000..8152bd50557b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-morph-3.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-morph-4.html b/testing/performance/talos/page_load_test/jss/real-morph-4.html new file mode 100644 index 000000000000..d7f4ee0ef1bc --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-morph-4.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nbody-1.html b/testing/performance/talos/page_load_test/jss/real-nbody-1.html new file mode 100644 index 000000000000..addb8fab018c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nbody-1.html @@ -0,0 +1,183 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nbody-2.html b/testing/performance/talos/page_load_test/jss/real-nbody-2.html new file mode 100644 index 000000000000..5c3b19b951af --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nbody-2.html @@ -0,0 +1,183 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nbody-3.html b/testing/performance/talos/page_load_test/jss/real-nbody-3.html new file mode 100644 index 000000000000..345891e326b9 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nbody-3.html @@ -0,0 +1,183 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nbody-4.html b/testing/performance/talos/page_load_test/jss/real-nbody-4.html new file mode 100644 index 000000000000..9e2d50625683 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nbody-4.html @@ -0,0 +1,183 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-1.html b/testing/performance/talos/page_load_test/jss/real-nsieve-1.html new file mode 100644 index 000000000000..122b19bfe1db --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-1.html @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-2.html b/testing/performance/talos/page_load_test/jss/real-nsieve-2.html new file mode 100644 index 000000000000..c78218d97ab5 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-2.html @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-3.html b/testing/performance/talos/page_load_test/jss/real-nsieve-3.html new file mode 100644 index 000000000000..335d4b328df0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-3.html @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-4.html b/testing/performance/talos/page_load_test/jss/real-nsieve-4.html new file mode 100644 index 000000000000..a3e0737455a0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-4.html @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-bits-1.html b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-1.html new file mode 100644 index 000000000000..18c817fdc910 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-1.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-bits-2.html b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-2.html new file mode 100644 index 000000000000..143f0652c66a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-2.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-bits-3.html b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-3.html new file mode 100644 index 000000000000..9ab08d965c8c --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-3.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-nsieve-bits-4.html b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-4.html new file mode 100644 index 000000000000..2afb2ddcc398 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-nsieve-bits-4.html @@ -0,0 +1,44 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-packer-1.html b/testing/performance/talos/page_load_test/jss/real-packer-1.html new file mode 100644 index 000000000000..8805ae930785 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-packer-1.html @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-packer-2.html b/testing/performance/talos/page_load_test/jss/real-packer-2.html new file mode 100644 index 000000000000..30d65ca00382 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-packer-2.html @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-packer-3.html b/testing/performance/talos/page_load_test/jss/real-packer-3.html new file mode 100644 index 000000000000..cde5dc78e503 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-packer-3.html @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-packer-4.html b/testing/performance/talos/page_load_test/jss/real-packer-4.html new file mode 100644 index 000000000000..422bcc2a814f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-packer-4.html @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-packer-5.html b/testing/performance/talos/page_load_test/jss/real-packer-5.html new file mode 100644 index 000000000000..f9444598b9d1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-packer-5.html @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-partial-sums-1.html b/testing/performance/talos/page_load_test/jss/real-partial-sums-1.html new file mode 100644 index 000000000000..6e76be74ccf1 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-partial-sums-1.html @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-partial-sums-2.html b/testing/performance/talos/page_load_test/jss/real-partial-sums-2.html new file mode 100644 index 000000000000..0f88dd33328a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-partial-sums-2.html @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-partial-sums-3.html b/testing/performance/talos/page_load_test/jss/real-partial-sums-3.html new file mode 100644 index 000000000000..a9c652add010 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-partial-sums-3.html @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-partial-sums-4.html b/testing/performance/talos/page_load_test/jss/real-partial-sums-4.html new file mode 100644 index 000000000000..6f3dc77cab4b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-partial-sums-4.html @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-1.html b/testing/performance/talos/page_load_test/jss/real-recursive-1.html new file mode 100644 index 000000000000..e32d875c0e54 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-1.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-10.html b/testing/performance/talos/page_load_test/jss/real-recursive-10.html new file mode 100644 index 000000000000..4aaee1460d34 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-10.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-11.html b/testing/performance/talos/page_load_test/jss/real-recursive-11.html new file mode 100644 index 000000000000..0618176a3e8f --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-11.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-12.html b/testing/performance/talos/page_load_test/jss/real-recursive-12.html new file mode 100644 index 000000000000..04485b4e1258 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-12.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-2.html b/testing/performance/talos/page_load_test/jss/real-recursive-2.html new file mode 100644 index 000000000000..3a7b3b69bdeb --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-2.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-3.html b/testing/performance/talos/page_load_test/jss/real-recursive-3.html new file mode 100644 index 000000000000..91c8f0e58595 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-3.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-4.html b/testing/performance/talos/page_load_test/jss/real-recursive-4.html new file mode 100644 index 000000000000..6ee76cea093a --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-4.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-5.html b/testing/performance/talos/page_load_test/jss/real-recursive-5.html new file mode 100644 index 000000000000..2a550bf18717 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-5.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-6.html b/testing/performance/talos/page_load_test/jss/real-recursive-6.html new file mode 100644 index 000000000000..66677a9bd8f0 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-6.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-7.html b/testing/performance/talos/page_load_test/jss/real-recursive-7.html new file mode 100644 index 000000000000..620a0df4809d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-7.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-8.html b/testing/performance/talos/page_load_test/jss/real-recursive-8.html new file mode 100644 index 000000000000..04ea4b7e8a2b --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-8.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-recursive-9.html b/testing/performance/talos/page_load_test/jss/real-recursive-9.html new file mode 100644 index 000000000000..d640b3f73dd8 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-recursive-9.html @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-spectral-norm-1.html b/testing/performance/talos/page_load_test/jss/real-spectral-norm-1.html new file mode 100644 index 000000000000..6afb26fae24d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-spectral-norm-1.html @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-spectral-norm-2.html b/testing/performance/talos/page_load_test/jss/real-spectral-norm-2.html new file mode 100644 index 000000000000..5724cb2edc18 --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-spectral-norm-2.html @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-spectral-norm-3.html b/testing/performance/talos/page_load_test/jss/real-spectral-norm-3.html new file mode 100644 index 000000000000..3e4c83785e6d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-spectral-norm-3.html @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/real-spectral-norm-4.html b/testing/performance/talos/page_load_test/jss/real-spectral-norm-4.html new file mode 100644 index 000000000000..5c754f62f34e --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/real-spectral-norm-4.html @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/testing/performance/talos/page_load_test/jss/runner.js b/testing/performance/talos/page_load_test/jss/runner.js new file mode 100644 index 000000000000..c00524a6573d --- /dev/null +++ b/testing/performance/talos/page_load_test/jss/runner.js @@ -0,0 +1,172 @@ +(function(){ + + // Figure out if we need to stagger the tests, or not + var doDelay = typeof window != "undefined" && window.location && window.location.search == "?delay"; + + // Get the output pre (if it exists, and if we're embedded in a runner page) + var pre = typeof document != "undefined" && document.getElementsByTagName && + document.getElementsByTagName("pre")[0]; + + // The number of iterations to do + // and the number of seconds to wait for a timeout + var numTests = 100, timeout = !doDelay ? 20000 : 4500; + + var title, testName, summary = 0, queue = []; + + // Initialize a batch of tests + // name = The name of the test collection + this.startTest = function(name){ + testName = name; + + if ( typeof onlyName == "undefined" ) + log([ "__start_report", testName ]); + }; + + // End the tests and finalize the report + this.endTest = function(){ + // Save the summary output until all the test are complete + queue.push(function(){ + if ( typeof onlyName == "undefined" ) { + log([ "__summarystats", summary ]); + log([ "__end_report" ]); + + // Log the time to the special Talos function, if it exists + } else if ( typeof tpRecordTime != "undefined" ) + tpRecordTime( summary ); + + // Otherwise, we're only interested in the results from a single function + else + log([ "__start_report" + summary + "__end_report" ]); + + // Force an application quit (for the Mozilla perf test runner) + if ( typeof goQuitApplication != "undefined" ) + goQuitApplication(); + }); + + // Start running the first test + dequeue(); + }; + + // Run a new test + // name = The unique name of the test + // num = The 'length' of the test (length of string, # of tests, etc.) + // fn = A function holding the test to run + this.test = function(name, num, fn){ + // Done't run the test if we're limiting to just one + if ( typeof onlyName == "undefined" || (name == onlyName && num == onlyNum) ) { + // Don't execute the test immediately + queue.push(function(){ + doTest( name, num, fn ); + }); + } + }; + + // The actual testing function (only to be called via the queue control) + function doTest(name, num, fn){ + title = name; + var times = [], start, diff, sum = 0, min = -1, max = -1, + median, std, mean; + + if ( !fn ) { + fn = num; + num = ''; + } + + // run tests + try { + // We need to let the test time out + var testStart = (new Date()).getTime(); + + for ( var i = 0; i < numTests; i++ ) { + start = (new Date()).getTime(); + fn(); + var cur = (new Date()).getTime(); + diff = cur - start; + + // Make Sum + sum += diff; + + // Make Min + if ( min == -1 || diff < min ) + min = diff; + + // Make Max + if ( max == -1 || diff > max ) + max = diff; + + // For making Median and Variance + times.push( diff ); + + // Check to see if the test has run for too long + if ( timeout > 0 && cur - testStart > timeout ) + break; + } + } catch( e ) { + if ( typeof onlyName == "undefined" ) + return log( [ title, num, NaN, NaN, NaN, NaN, NaN ] ); + else + return log( [ "__FAIL" + e + "__FAIL" ] ); + } + + // Make Mean + mean = sum / times.length; + + // Keep a running summary going + summary += mean; + + // Make Median + times = times.sort(function(a,b){ + return a - b; + }); + + if ( times.length % 2 == 0 ) + median = (times[(times.length/2)-1] + times[times.length/2]) / 2; + else + median = times[(times.length/2)]; + + // Make Variance + var variance = 0; + for ( var i = 0; i < times.length; i++ ) + variance += Math.pow(times[i] - mean, 2); + variance /= times.length - 1; + + // Make Standard Deviation + std = Math.sqrt( variance ); + + if ( typeof onlyName == "undefined" ) + log( [ title, num, median, mean, min, max, std ] ); + + // Execute the next test + dequeue(); + }; + + // Remove the next test from the queue and execute it + function dequeue(){ + // If we're in a browser, and the user wants to delay the tests, + // then we should throw it in a setTimeout + if ( doDelay && typeof setTimeout != "undefined" ) + setTimeout(function(){ + queue.shift()(); + }, 13); + + // Otherwise execute the test immediately + else + queue.shift()(); + } + + // Log the results + function log( arr ) { + // If we're in an embedded runner, output to the output pre + if ( pre ) + pre.innerHTML += arr.join(":") + "\n"; + + // Otherwise, just document.write out the results + else if ( typeof document != "undefined" && document.write && !doDelay ) + document.write( arr.join(":") + "\n" ); + + // Otherwise, we're probably in a shell of some sort + else if ( typeof window == "undefined" && typeof print != "undefined" ) + print( arr.join(":") ); + } + +})(); diff --git a/testing/performance/talos/page_load_test/sunspider/3d-cube.html b/testing/performance/talos/page_load_test/sunspider/3d-cube.html new file mode 100644 index 000000000000..773b58548ea3 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/3d-cube.html @@ -0,0 +1,383 @@ + + + + +SunSpider 3d-cube + + + + +

3d-cube

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/3d-morph.html b/testing/performance/talos/page_load_test/sunspider/3d-morph.html new file mode 100644 index 000000000000..fb1b392e202e --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/3d-morph.html @@ -0,0 +1,100 @@ + + + + +SunSpider 3d-morph + + + + +

3d-morph

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/3d-raytrace.html b/testing/performance/talos/page_load_test/sunspider/3d-raytrace.html new file mode 100644 index 000000000000..81fd675aa98a --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/3d-raytrace.html @@ -0,0 +1,487 @@ + + + + +SunSpider 3d-raytrace + + + + +

3d-raytrace

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/access-binary-trees.html b/testing/performance/talos/page_load_test/sunspider/access-binary-trees.html new file mode 100644 index 000000000000..4e86dd69eb6b --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/access-binary-trees.html @@ -0,0 +1,96 @@ + + + + +SunSpider access-binary-trees + + + + +

access-binary-trees

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/access-fannkuch.html b/testing/performance/talos/page_load_test/sunspider/access-fannkuch.html new file mode 100644 index 000000000000..aaa88ef48998 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/access-fannkuch.html @@ -0,0 +1,112 @@ + + + + +SunSpider access-fannkuch + + + + +

access-fannkuch

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/access-nbody.html b/testing/performance/talos/page_load_test/sunspider/access-nbody.html new file mode 100644 index 000000000000..eb9bba38e1a4 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/access-nbody.html @@ -0,0 +1,215 @@ + + + + +SunSpider access-nbody + + + + +

access-nbody

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/access-nsieve.html b/testing/performance/talos/page_load_test/sunspider/access-nsieve.html new file mode 100644 index 000000000000..88c213da9a26 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/access-nsieve.html @@ -0,0 +1,84 @@ + + + + +SunSpider access-nsieve + + + + +

access-nsieve

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/bitops-3bit-bits-in-byte.html b/testing/performance/talos/page_load_test/sunspider/bitops-3bit-bits-in-byte.html new file mode 100644 index 000000000000..4b3cf2e4fb0a --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/bitops-3bit-bits-in-byte.html @@ -0,0 +1,78 @@ + + + + +SunSpider bitops-3bit-bits-in-byte + + + + +

bitops-3bit-bits-in-byte

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/bitops-bits-in-byte.html b/testing/performance/talos/page_load_test/sunspider/bitops-bits-in-byte.html new file mode 100644 index 000000000000..3269c2291754 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/bitops-bits-in-byte.html @@ -0,0 +1,67 @@ + + + + +SunSpider bitops-bits-in-byte + + + + +

bitops-bits-in-byte

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/bitops-bitwise-and.html b/testing/performance/talos/page_load_test/sunspider/bitops-bitwise-and.html new file mode 100644 index 000000000000..c0b76eb05749 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/bitops-bitwise-and.html @@ -0,0 +1,74 @@ + + + + +SunSpider bitops-bitwise-and + + + + +

bitops-bitwise-and

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/bitops-nsieve-bits.html b/testing/performance/talos/page_load_test/sunspider/bitops-nsieve-bits.html new file mode 100644 index 000000000000..4ac81959c20e --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/bitops-nsieve-bits.html @@ -0,0 +1,78 @@ + + + + +SunSpider bitops-nsieve-bits + + + + +

bitops-nsieve-bits

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/controlflow-recursive.html b/testing/performance/talos/page_load_test/sunspider/controlflow-recursive.html new file mode 100644 index 000000000000..05566e00569a --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/controlflow-recursive.html @@ -0,0 +1,71 @@ + + + + +SunSpider controlflow-recursive + + + + +

controlflow-recursive

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/crypto-aes.html b/testing/performance/talos/page_load_test/sunspider/crypto-aes.html new file mode 100644 index 000000000000..e134281b09dd --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/crypto-aes.html @@ -0,0 +1,468 @@ + + + + +SunSpider crypto-aes + + + + +

crypto-aes

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/crypto-md5.html b/testing/performance/talos/page_load_test/sunspider/crypto-md5.html new file mode 100644 index 000000000000..a2f2090d6def --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/crypto-md5.html @@ -0,0 +1,332 @@ + + + + +SunSpider crypto-md5 + + + + +

crypto-md5

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/crypto-sha1.html b/testing/performance/talos/page_load_test/sunspider/crypto-sha1.html new file mode 100644 index 000000000000..b914525b58a7 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/crypto-sha1.html @@ -0,0 +1,270 @@ + + + + +SunSpider crypto-sha1 + + + + +

crypto-sha1

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/date-format-tofte.html b/testing/performance/talos/page_load_test/sunspider/date-format-tofte.html new file mode 100644 index 000000000000..06be7bae316e --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/date-format-tofte.html @@ -0,0 +1,345 @@ + + + + +SunSpider date-format-tofte + + + + +

date-format-tofte

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/date-format-xparb.html b/testing/performance/talos/page_load_test/sunspider/date-format-xparb.html new file mode 100644 index 000000000000..0e8b14f71454 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/date-format-xparb.html @@ -0,0 +1,463 @@ + + + + +SunSpider date-format-xparb + + + + +

date-format-xparb

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/math-cordic.html b/testing/performance/talos/page_load_test/sunspider/math-cordic.html new file mode 100644 index 000000000000..dab76204150b --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/math-cordic.html @@ -0,0 +1,141 @@ + + + + +SunSpider math-cordic + + + + +

math-cordic

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/math-partial-sums.html b/testing/performance/talos/page_load_test/sunspider/math-partial-sums.html new file mode 100644 index 000000000000..a73b8b0d8539 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/math-partial-sums.html @@ -0,0 +1,79 @@ + + + + +SunSpider math-partial-sums + + + + +

math-partial-sums

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/math-spectral-norm.html b/testing/performance/talos/page_load_test/sunspider/math-spectral-norm.html new file mode 100644 index 000000000000..bacf488eac98 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/math-spectral-norm.html @@ -0,0 +1,97 @@ + + + + +SunSpider math-spectral-norm + + + + +

math-spectral-norm

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/regexp-dna.html b/testing/performance/talos/page_load_test/sunspider/regexp-dna.html new file mode 100644 index 000000000000..737283312e60 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/regexp-dna.html @@ -0,0 +1,1758 @@ + + + + +SunSpider regexp-dna + + + + +

regexp-dna

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/string-base64.html b/testing/performance/talos/page_load_test/sunspider/string-base64.html new file mode 100644 index 000000000000..2a1dd94bb35e --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/string-base64.html @@ -0,0 +1,181 @@ + + + + +SunSpider string-base64 + + + + +

string-base64

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/string-fasta.html b/testing/performance/talos/page_load_test/sunspider/string-fasta.html new file mode 100644 index 000000000000..a4e67efa5cee --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/string-fasta.html @@ -0,0 +1,131 @@ + + + + +SunSpider string-fasta + + + + +

string-fasta

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/string-tagcloud.html b/testing/performance/talos/page_load_test/sunspider/string-tagcloud.html new file mode 100644 index 000000000000..3f5d6e78cbdc --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/string-tagcloud.html @@ -0,0 +1,311 @@ + + + + +SunSpider string-tagcloud + + + + +

string-tagcloud

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/string-unpack-code.html b/testing/performance/talos/page_load_test/sunspider/string-unpack-code.html new file mode 100644 index 000000000000..68686f0898f7 --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/string-unpack-code.html @@ -0,0 +1,113 @@ + + + + +SunSpider string-unpack-code + + + + +

string-unpack-code

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/string-validate-input.html b/testing/performance/talos/page_load_test/sunspider/string-validate-input.html new file mode 100644 index 000000000000..9d0771c6233d --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/string-validate-input.html @@ -0,0 +1,134 @@ + + + + +SunSpider string-validate-input + + + + +

string-validate-input

+
+
+ + + + + diff --git a/testing/performance/talos/page_load_test/sunspider/sunspider.css b/testing/performance/talos/page_load_test/sunspider/sunspider.css new file mode 100644 index 000000000000..7a1797987c0a --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/sunspider.css @@ -0,0 +1,31 @@ + +body { font-family: sans-serif; + margin: 20px; + background-color: #D9D5A1; + color: #1B0636 } + +h2 { background-color: #4E8AB9; + margin: -20px -20px 0px -20px; + padding: 30px 20px 30px 20px; + color: yellow; + border-bottom: 2px solid #360D6B; + zoom: 1.0 /* I CAN HAS LAYOUT? (ie hack) */ } + +dt { font-weight: bold } + +dd { margin-bottom: 1em; margin-top: 0.5em } + +:link { color: #1363A1 } +:visited { color: #5113A1 } + +#testframe { margin-top: 20px; + width: 80%; + height: 500px; + border: 2px solid #360D6B } + +#logo { float: left; + position: relative; + bottom: 0.33em; + padding-right: 20px; + margin-bottom: -40px; + font-size: 3em } diff --git a/testing/performance/talos/page_load_test/sunspider/sunspider.manifest b/testing/performance/talos/page_load_test/sunspider/sunspider.manifest new file mode 100644 index 000000000000..0fa7249e8d4f --- /dev/null +++ b/testing/performance/talos/page_load_test/sunspider/sunspider.manifest @@ -0,0 +1,26 @@ +http://localhost/page_load_test/sunspider/3d-cube.html +http://localhost/page_load_test/sunspider/3d-morph.html +http://localhost/page_load_test/sunspider/3d-raytrace.html +http://localhost/page_load_test/sunspider/access-binary-trees.html +http://localhost/page_load_test/sunspider/access-fannkuch.html +http://localhost/page_load_test/sunspider/access-nbody.html +http://localhost/page_load_test/sunspider/access-nsieve.html +http://localhost/page_load_test/sunspider/bitops-3bit-bits-in-byte.html +http://localhost/page_load_test/sunspider/bitops-bits-in-byte.html +http://localhost/page_load_test/sunspider/bitops-bitwise-and.html +http://localhost/page_load_test/sunspider/bitops-nsieve-bits.html +http://localhost/page_load_test/sunspider/controlflow-recursive.html +http://localhost/page_load_test/sunspider/crypto-aes.html +http://localhost/page_load_test/sunspider/crypto-md5.html +http://localhost/page_load_test/sunspider/crypto-sha1.html +http://localhost/page_load_test/sunspider/date-format-tofte.html +http://localhost/page_load_test/sunspider/date-format-xparb.html +http://localhost/page_load_test/sunspider/math-cordic.html +http://localhost/page_load_test/sunspider/math-partial-sums.html +http://localhost/page_load_test/sunspider/math-spectral-norm.html +http://localhost/page_load_test/sunspider/regexp-dna.html +http://localhost/page_load_test/sunspider/string-base64.html +http://localhost/page_load_test/sunspider/string-fasta.html +http://localhost/page_load_test/sunspider/string-tagcloud.html +http://localhost/page_load_test/sunspider/string-unpack-code.html +http://localhost/page_load_test/sunspider/string-validate-input.html diff --git a/testing/performance/talos/sample.config b/testing/performance/talos/sample.config index 88d66a4cd93e..2d74bb23783c 100755 --- a/testing/performance/talos/sample.config +++ b/testing/performance/talos/sample.config @@ -115,4 +115,16 @@ tests : cycles : 1 win_counters: [] unix_counters : [] + tjss: + url: '-tp page_load_test/jss/jss.manifest -tpchrome -tpformat tinderbox -tpcycles 1' + resolution : 1 + cycles : 1 + win_counters : [] + unix_counters : [] + tsspider: + url: '-tp page_load_test/sunspider/sunspider.manifest -tpchrome -tpformat tinderbox -tpcycles 5' + resolution : 1 + cycles : 1 + win_counters : [] + unix_counters : [] diff --git a/testing/release/common/check_updates.sh b/testing/release/common/check_updates.sh index 5f55a1efd770..143a395e7a27 100755 --- a/testing/release/common/check_updates.sh +++ b/testing/release/common/check_updates.sh @@ -41,7 +41,8 @@ check_updates () { if [ -d source/$platform_dirname ]; then cd source/$platform_dirname; cp $updater ../../update - ../../update/updater ../../update 0 + # FIXME remove once fix in 401608 has shipped + ../../update/updater ../../update 0 blah blah cd ../.. else echo "FAIL: no dir in source/$platform_dirname" diff --git a/toolkit/components/downloads/public/nsIDownload.idl b/toolkit/components/downloads/public/nsIDownload.idl index 771564f0a9c5..d88060d3ea78 100644 --- a/toolkit/components/downloads/public/nsIDownload.idl +++ b/toolkit/components/downloads/public/nsIDownload.idl @@ -54,7 +54,7 @@ interface nsIMIMEInfo; * nsIDownloadManager::DOWNLOAD_FAILED * nsIDownloadManager::DOWNLOAD_CANCELED */ -[scriptable, uuid(4ee8befe-b05a-4ca2-9b30-6c47a9c4a622)] +[scriptable, uuid(c891111e-92a6-47b8-bc46-874ebb61ac9d)] interface nsIDownload : nsITransfer { /** @@ -133,6 +133,13 @@ interface nsIDownload : nsITransfer { * and can be null. */ readonly attribute nsIURI referrer; + + /** + * Indicates if the download can be resumed after being paused or not. This + * is only the case if the download is over HTTP/1.1 or FTP and if the + * server supports it. + */ + readonly attribute boolean resumable; }; %{C++ diff --git a/toolkit/components/downloads/src/nsDownloadManager.cpp b/toolkit/components/downloads/src/nsDownloadManager.cpp index 915a58f98e43..20785e1fdd89 100644 --- a/toolkit/components/downloads/src/nsDownloadManager.cpp +++ b/toolkit/components/downloads/src/nsDownloadManager.cpp @@ -25,6 +25,7 @@ * Shawn Wilsher * Srirang G Doddihal * Edward Lee + * Graeme McCutcheon * * 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 @@ -92,6 +93,7 @@ #define PREF_BDM_SHOWALERTONCOMPLETE "browser.download.manager.showAlertOnComplete" #define PREF_BDM_SHOWALERTINTERVAL "browser.download.manager.showAlertInterval" #define PREF_BDM_RETENTION "browser.download.manager.retention" +#define PREF_BDM_QUITBEHAVIOR "browser.download.manager.quitBehavior" #define PREF_BDM_CLOSEWHENDONE "browser.download.manager.closeWhenDone" #define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs" #define PREF_BH_DELETETEMPFILEONEXIT "browser.helperApps.deleteTempFileOnExit" @@ -214,7 +216,7 @@ nsDownloadManager::RemoveAllDownloads() nsRefPtr dl = mCurrentDownloads[0]; nsresult result; - if (dl->IsRealPaused()) + if (dl->IsPaused() && GetQuitBehavior() != QUIT_AND_CANCEL) result = mCurrentDownloads.RemoveObject(dl); else result = CancelDownload(dl->mID); @@ -896,6 +898,28 @@ nsDownloadManager::GetRetentionBehavior() return val; } +enum nsDownloadManager::QuitBehavior +nsDownloadManager::GetQuitBehavior() +{ + // We use 0 as the default, which is "remember and resume the download" + nsresult rv; + nsCOMPtr pref = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, QUIT_AND_RESUME); + + PRInt32 val; + rv = pref->GetIntPref(PREF_BDM_QUITBEHAVIOR, &val); + NS_ENSURE_SUCCESS(rv, QUIT_AND_RESUME); + + switch (val) { + case 1: + return QUIT_AND_PAUSE; + case 2: + return QUIT_AND_CANCEL; + default: + return QUIT_AND_RESUME; + } +} + nsresult nsDownloadManager::GetDownloadFromDB(PRUint32 aID, nsDownload **retVal) { @@ -1617,10 +1641,7 @@ nsDownloadManager::Observe(nsISupports *aSubject, const PRUnichar *aData) { // Count active downloads that aren't real-paused - PRInt32 currDownloadCount = 0; - for (PRInt32 i = mCurrentDownloads.Count() - 1; i >= 0; --i) - if (!mCurrentDownloads[i]->IsRealPaused()) - currDownloadCount++; + PRInt32 currDownloadCount = mCurrentDownloads.Count(); nsresult rv; if (strcmp(aTopic, "oncancel") == 0) { @@ -1633,14 +1654,17 @@ nsDownloadManager::Observe(nsISupports *aSubject, if (dl2) return CancelDownload(id); } else if (strcmp(aTopic, "quit-application") == 0) { - // Try to pause all downloads and mark them as auto-resume - (void)PauseAllDownloads(PR_TRUE); + // Try to pause all downloads and, if appropriate, mark them as auto-resume + // unless user has specified that downloads should be canceled + enum QuitBehavior behavior = GetQuitBehavior(); + if (behavior != QUIT_AND_CANCEL) + (void)PauseAllDownloads(PRBool(behavior != QUIT_AND_PAUSE)); // Remove downloads to break cycles and cancel downloads (void)RemoveAllDownloads(); - // Now that active downloads have been canceled, remove all downloads if - // the user's retention policy specifies it. + // Now that active downloads have been canceled, remove all completed or + // aborted downloads if the user's retention policy specifies it. if (GetRetentionBehavior() == 1) CleanUp(); } else if (strcmp(aTopic, "quit-application-requested") == 0 && @@ -1743,6 +1767,7 @@ nsDownload::nsDownload() : mDownloadState(nsIDownloadManager::DOWNLOAD_NOTSTARTE mLastUpdate(PR_Now() - (PRUint32)gUpdateInterval), mResumedAt(-1), mSpeed(0), + mHasMultipleFiles(PR_FALSE), mAutoResume(DONT_RESUME) { } @@ -1985,6 +2010,10 @@ nsDownload::OnProgressChange64(nsIWebProgress *aWebProgress, mDownloadManager->NotifyListenersOnProgressChange( aWebProgress, aRequest, currBytes, maxBytes, currBytes, maxBytes, this); + // If the maximums are different, then there must be more than one file + if (aMaxSelfProgress != aMaxTotalProgress) + mHasMultipleFiles = PR_TRUE; + return NS_OK; } @@ -2040,10 +2069,9 @@ nsDownload::OnStateChange(nsIWebProgress *aWebProgress, // We don't want to lose access to our member variables nsRefPtr kungFuDeathGrip = this; - // We need to update mDownloadState before updating the dialog, because - // that will close and call CancelDownload if it was the last open window. - - if (aStateFlags & STATE_START) { + // Check if we're starting a request; the NETWORK flag is necessary to not + // pick up the START of *each* file but only for the whole request + if ((aStateFlags & STATE_START) && (aStateFlags & STATE_IS_NETWORK)) { nsresult rv; nsCOMPtr channel = do_QueryInterface(aRequest, &rv); if (NS_SUCCEEDED(rv)) { @@ -2058,17 +2086,21 @@ nsDownload::OnStateChange(nsIWebProgress *aWebProgress, (void)SetState(nsIDownloadManager::DOWNLOAD_BLOCKED); } } - } else if ((aStateFlags & STATE_STOP) && IsFinishable()) { + } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK) && + IsFinishable()) { + // We got both STOP and NETWORK so that means the whole request is done + // (and not just a single file if there are multiple files) if (NS_SUCCEEDED(aStatus)) { // We can't completely trust the bytes we've added up because we might be // missing on some/all of the progress updates (especially from cache). - // Our best bet is the file itself, but if for some reason it's gone, the - // next best is what we've calculated. + // Our best bet is the file itself, but if for some reason it's gone or + // if we have multiple files, the next best is what we've calculated. PRInt64 fileSize; nsCOMPtr file; // We need a nsIFile clone to deal with file size caching issues. :( nsCOMPtr clone; - if (NS_SUCCEEDED(GetTargetFile(getter_AddRefs(file))) && + if (!mHasMultipleFiles && + NS_SUCCEEDED(GetTargetFile(getter_AddRefs(file))) && NS_SUCCEEDED(file->Clone(getter_AddRefs(clone))) && NS_SUCCEEDED(clone->GetFileSize(&fileSize)) && fileSize > 0) { mCurrBytes = mMaxBytes = fileSize; @@ -2234,6 +2266,13 @@ nsDownload::GetReferrer(nsIURI **referrer) return NS_OK; } +NS_IMETHODIMP +nsDownload::GetResumable(PRBool *resumable) +{ + *resumable = IsResumable(); + return NS_OK; +} + //////////////////////////////////////////////////////////////////////////////// //// nsDownload Helper Functions @@ -2401,13 +2440,10 @@ nsDownload::SetProgressBytes(PRInt64 aCurrBytes, PRInt64 aMaxBytes) nsresult nsDownload::Pause() { - nsresult rv = NS_ERROR_FAILURE; - if (IsResumable()) - rv = Cancel(); - else if (mRequest) - rv = mRequest->Suspend(); - else - NS_NOTREACHED("We don't have a resumable download or a request to suspend??"); + if (!IsResumable()) + return NS_ERROR_UNEXPECTED; + + nsresult rv = Cancel(); NS_ENSURE_SUCCESS(rv, rv); return SetState(nsIDownloadManager::DOWNLOAD_PAUSED); @@ -2429,21 +2465,9 @@ nsDownload::Cancel() nsresult nsDownload::Resume() { - nsresult rv = NS_ERROR_FAILURE; - if (IsResumable()) - rv = RealResume(); - else if (mRequest) - rv = mRequest->Resume(); - else - NS_NOTREACHED("We don't have a resumable download or a request to resume??"); - NS_ENSURE_SUCCESS(rv, rv); + if (!IsPaused() || !IsResumable()) + return NS_ERROR_UNEXPECTED; - return SetState(nsIDownloadManager::DOWNLOAD_DOWNLOADING); -} - -nsresult -nsDownload::RealResume() -{ nsresult rv; nsCOMPtr wbp = do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv); @@ -2511,7 +2535,7 @@ nsDownload::RealResume() return rv; } - return NS_OK; + return SetState(nsIDownloadManager::DOWNLOAD_DOWNLOADING); } PRBool @@ -2532,12 +2556,6 @@ nsDownload::WasResumed() return mResumedAt != -1; } -PRBool -nsDownload::IsRealPaused() -{ - return IsPaused() && IsResumable(); -} - PRBool nsDownload::ShouldAutoResume() { diff --git a/toolkit/components/downloads/src/nsDownloadManager.h b/toolkit/components/downloads/src/nsDownloadManager.h index 0388c5cbd106..35af44170e17 100644 --- a/toolkit/components/downloads/src/nsDownloadManager.h +++ b/toolkit/components/downloads/src/nsDownloadManager.h @@ -197,6 +197,27 @@ protected: PRInt32 GetRetentionBehavior(); + /** + * Type to indicate possible behaviors for active downloads across sessions. + * + * Possible values are: + * QUIT_AND_RESUME - downloads should be auto-resumed + * QUIT_AND_PAUSE - downloads should be paused + * QUIT_AND_CANCEL - downloads should be cancelled + */ + enum QuitBehavior { + QUIT_AND_RESUME = 0, + QUIT_AND_PAUSE = 1, + QUIT_AND_CANCEL = 2 + }; + + /** + * Indicates user-set behavior for active downloads across sessions, + * + * @return value of user-set pref for active download behavior + */ + enum QuitBehavior GetQuitBehavior(); + private: nsCOMArray mListeners; nsCOMPtr mBundle; @@ -276,15 +297,10 @@ protected: nsresult Cancel(); /** - * Resume the download. Works for both real-paused and fake-paused. + * Resume the download. */ nsresult Resume(); - /** - * Resume the real-paused download. Let Resume decide if this should get used. - */ - nsresult RealResume(); - /** * Download is not transferring? */ @@ -300,11 +316,6 @@ protected: */ PRBool WasResumed(); - /** - * Download is real-paused? (not fake-paused by stalling the channel) - */ - PRBool IsRealPaused(); - /** * Indicates if the download should try to automatically resume or not. */ @@ -378,6 +389,8 @@ private: PRInt64 mResumedAt; double mSpeed; + PRBool mHasMultipleFiles; + /** * Track various states of the download trying to auto-resume when starting * the download manager or restoring from a crash. diff --git a/toolkit/components/downloads/src/nsDownloadManagerUI.js b/toolkit/components/downloads/src/nsDownloadManagerUI.js index 77a133b52b1f..de58b57edcbe 100644 --- a/toolkit/components/downloads/src/nsDownloadManagerUI.js +++ b/toolkit/components/downloads/src/nsDownloadManagerUI.js @@ -89,7 +89,7 @@ nsDownloadManagerUI.prototype = { getService(Ci.nsIWindowWatcher); ww.openWindow(window, DOWNLOAD_MANAGER_URL, - null, + "Download:Manager", "chrome,dialog=no,resizable", params); }, diff --git a/toolkit/components/microformats/src/Microformats.js b/toolkit/components/microformats/src/Microformats.js index 392d0197e872..9a3975e0f9b7 100644 --- a/toolkit/components/microformats/src/Microformats.js +++ b/toolkit/components/microformats/src/Microformats.js @@ -372,7 +372,27 @@ var Microformats = { * @return A string with the telephone number */ telGetter: function(propnode, parentnode) { - /* Special case - if this node is a value, use the parent node to get all the values */ + var pairs = {"a":"href", "object":"data", "area":"href"}; + var name = propnode.nodeName.toLowerCase(); + if (pairs.hasOwnProperty(name)) { + var protocol; + if (propnode[pairs[name]].indexOf("tel:") == 0) { + protocol = "tel:"; + } + if (propnode[pairs[name]].indexOf("fax:") == 0) { + protocol = "fax:"; + } + if (propnode[pairs[name]].indexOf("modem:") == 0) { + protocol = "modem:"; + } + if (protocol) { + if (propnode[pairs[name]].indexOf('?') > 0) { + return unescape(propnode[pairs[name]].substring(protocol.length, propnode[pairs[name]].indexOf('?'))); + } else { + return unescape(propnode[pairs[name]].substring(protocol.length)); + } + } + } if (Microformats.matchClass(propnode, "value")) { return Microformats.parser.textGetter(parentnode, parentnode); } else { @@ -464,7 +484,11 @@ var Microformats = { */ datatypeHelper: function(prop, node, parentnode) { var result; - switch (prop.datatype) { + var datatype = prop.datatype; + if (prop.implied) { + datatype = prop.subproperties[prop.implied].datatype; + } + switch (datatype) { case "dateTime": result = Microformats.parser.dateTimeGetter(node, parentnode); break; @@ -501,13 +525,15 @@ var Microformats = { } default: result = Microformats.parser.textGetter(node, parentnode); - if ((prop.implied) && (result)) { - var temp = result; - result = {}; - result[prop.implied] = temp; - } break; } + /* This handles the case where one property implies another property */ + /* For instance, org by itself is actually org.organization-name */ + if ((prop.implied) && (result)) { + var temp = result; + result = {}; + result[prop.implied] = temp; + } if (result && prop.values) { var validType = false; for (let value in prop.values) { diff --git a/toolkit/components/microformats/tests/test_Microformats_hCard.html b/toolkit/components/microformats/tests/test_Microformats_hCard.html index 6316747ce183..568478744915 100644 --- a/toolkit/components/microformats/tests/test_Microformats_hCard.html +++ b/toolkit/components/microformats/tests/test_Microformats_hCard.html @@ -775,14 +775,12 @@ function test_hCard() { isnot(hcard.tel[2].type[13], "invalid", "21-tel - type"); is(hcard.tel[3].value, "+1 415 555 1234", "21-tel - tel"); is(hcard.tel[3].type[0], "home", "21-tel - type"); -// is(hcard.tel[4].value, "+1.415.555.1235", "21-tel - tel"); -// is(hcard.tel[5].value, "+1.415.555.1236", "21-tel - tel"); -// is(hcard.tel[6].value, "+1.415.555.1237", "21-tel - tel"); -// is(hcard.tel[7].value, "+1.415.555.1238", "21-tel - tel"); -// is(hcard.tel[8].value, "+1.415.555.1239", "21-tel - tel"); -// is(hcard.tel[9].value, "+1.415.555.1240", "21-tel - tel"); -// is(hcard.tel[9].value, "+1.415.555.1241", "21-tel - tel"); -// is(hcard.tel[9].value, "+1.415.555.1242", "21-tel - tel"); + is(hcard.tel[4].value, "+1.415.555.1235", "21-tel - tel"); + is(hcard.tel[5].value, "+1.415.555.1236", "21-tel - tel"); + is(hcard.tel[6].value, "+1.415.555.1238", "21-tel - tel"); + is(hcard.tel[7].value, "+1.415.555.1239", "21-tel - tel"); + is(hcard.tel[8].value, "+1.415.555.1241", "21-tel - tel"); + is(hcard.tel[9].value, "+1.415.555.1242", "21-tel - tel"); hcard = new hCard(document.getElementById("22-adr")); diff --git a/toolkit/components/passwordmgr/test/unit/head_storage_legacy_1.js b/toolkit/components/passwordmgr/test/unit/head_storage_legacy_1.js index f71eac4b035d..e909bc4b564a 100644 --- a/toolkit/components/passwordmgr/test/unit/head_storage_legacy_1.js +++ b/toolkit/components/passwordmgr/test/unit/head_storage_legacy_1.js @@ -143,6 +143,8 @@ const LoginTest = { createInstance(Ci.nsILocalFile); inputFile.initWithPath(aPathName); inputFile.append(aFileName); + if (inputFile.fileSize == 0) + return 0; var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); @@ -151,7 +153,7 @@ const LoginTest = { var lineStream = inputStream.QueryInterface(Ci.nsILineInputStream); var line = { value : null }; - var lineCount = 1; + var lineCount = 1; // Empty files were dealt with above. while (lineStream.readLine(line)) lineCount++; diff --git a/toolkit/components/places/public/nsILivemarkService.idl b/toolkit/components/places/public/nsILivemarkService.idl index fbee1496f7e3..d3963a52f0d9 100644 --- a/toolkit/components/places/public/nsILivemarkService.idl +++ b/toolkit/components/places/public/nsILivemarkService.idl @@ -42,9 +42,16 @@ interface nsIURI; interface nsINavBookmarksService; -[scriptable, uuid(602e3a71-2d10-4d8f-80c2-6db302b5c89d)] +[scriptable, uuid(7879747e-8871-4a7b-9032-5c4fff1d6017)] interface nsILivemarkService : nsISupports { + /** + * Starts the livemark refresh timer. + * Being able to manually control this allows activity such + * as bookmarks import to occur without kicking off HTTP traffic. + */ + void start(); + /** * Creates a new livemark * @param folder The id of the parent folder @@ -154,3 +161,7 @@ interface nsILivemarkService : nsISupports */ void reloadLivemarkFolder(in long long folderID); }; + +%{C++ +#define LMANNO_FEEDURI "livemark/feedURI" +%} diff --git a/toolkit/components/places/public/nsINavHistoryService.idl b/toolkit/components/places/public/nsINavHistoryService.idl index 1f516e4a1d2e..fc2e3a284e95 100644 --- a/toolkit/components/places/public/nsINavHistoryService.idl +++ b/toolkit/components/places/public/nsINavHistoryService.idl @@ -85,6 +85,7 @@ interface nsINavHistoryResultNode : nsISupports const unsigned long RESULT_TYPE_FOLDER = 6; // nsINavHistoryQueryResultNode const unsigned long RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode const unsigned long RESULT_TYPE_DAY = 8; // nsINavHistoryContainerResultNode + const unsigned long RESULT_TYPE_FOLDER_SHORTCUT = 9; // nsINavHistoryQueryResultNode readonly attribute unsigned long type; /** @@ -393,7 +394,7 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode * generated this node, this item will report it has no children and never try * to populate itself. */ -[scriptable, uuid(dcd6a2b7-3d50-4c78-b1cb-2f0f18ac5864)] +[scriptable, uuid(ea17745a-1852-4155-a98f-d1dd1763b3df)] interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode { /** @@ -408,6 +409,12 @@ interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode * Only valid for RESULT_TYPE_QUERY nodes. */ readonly attribute nsINavHistoryQueryOptions queryOptions; + + /** + * For both simple folder nodes and simple-folder-query nodes, this is set + * to the concrete itemId of the folder. Otherwise, this is set to -1. + */ + readonly attribute long long folderItemId; }; /** diff --git a/toolkit/components/places/src/Makefile.in b/toolkit/components/places/src/Makefile.in index 62e11379127c..39bc84b00fd7 100644 --- a/toolkit/components/places/src/Makefile.in +++ b/toolkit/components/places/src/Makefile.in @@ -85,7 +85,6 @@ CPPSRCS = \ nsAnnotationService.cpp \ nsFaviconService.cpp \ nsNavHistory.cpp \ - nsNavHistoryAutoComplete.cpp \ nsNavHistoryExpire.cpp \ nsNavHistoryQuery.cpp \ nsNavHistoryResult.cpp \ @@ -95,6 +94,12 @@ CPPSRCS = \ nsPlacesModule.cpp \ $(NULL) +ifdef MOZ_XUL +CPPSRCS += \ + nsNavHistoryAutoComplete.cpp \ + $(NULL) +endif + EXTRA_DSO_LDOPTS += \ $(DEPTH)/db/morkreader/$(LIB_PREFIX)morkreader_s.$(LIB_SUFFIX) \ $(MOZ_UNICHARUTIL_LIBS) \ diff --git a/toolkit/components/places/src/nsAnnotationService.cpp b/toolkit/components/places/src/nsAnnotationService.cpp index 93b9f127074a..f5680a3bc85f 100644 --- a/toolkit/components/places/src/nsAnnotationService.cpp +++ b/toolkit/components/places/src/nsAnnotationService.cpp @@ -1691,7 +1691,7 @@ nsAnnotationService::CopyItemAnnotations(PRInt64 aSourceItemId, PRInt64 aDestItemId, PRBool aOverwriteDest) { - // XXX: Implment Me! + // XXX: Implement Me! return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/toolkit/components/places/src/nsFaviconService.cpp b/toolkit/components/places/src/nsFaviconService.cpp index f5edfac38abd..91ee438c4b0b 100644 --- a/toolkit/components/places/src/nsFaviconService.cpp +++ b/toolkit/components/places/src/nsFaviconService.cpp @@ -59,14 +59,12 @@ #include "nsNetUtil.h" #include "nsReadableUtils.h" #include "nsStreamUtils.h" +#include "nsStringStream.h" #include "mozStorageHelper.h" -// This is the maximum favicon size that we will bother storing. Most icons -// are about 4K. Some people add 32x32 versions at different bit depths, -// making them much bigger. It would be nice if could extract just the 16x16 -// version that we need. Instead, we'll just store everything below this -// sanity threshold. -#define MAX_FAVICON_SIZE 32768 +// For favicon optimization +#include "imgITools.h" +#include "imgIContainer.h" #define FAVICON_BUFFER_INCREMENT 8192 @@ -553,6 +551,24 @@ nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData, PRTime aExpiration) { nsresult rv; + PRUint32 dataLen = aDataLen; + const PRUint8* data = aData; + const nsACString* mimeType = &aMimeType; + nsCString newData, newMimeType; + + // If the page provided a large image for the favicon (eg, a highres image + // or a multiresolution .ico file), we don't want to store more data than + // needed. An uncompressed 16x16 RGBA image is 1024 bytes, and almost all + // sensible 16x16 icons are under 1024 bytes. + if (aDataLen > 1024) { + rv = OptimizeFaviconImage(aData, aDataLen, aMimeType, newData, newMimeType); + if (NS_SUCCEEDED(rv) && newData.Length() < aDataLen) { + data = reinterpret_cast(const_cast(newData.get())), + dataLen = newData.Length(); + mimeType = &newMimeType; + } + } + mozIStorageStatement* statement; { // this block forces the scoper to reset our statement: necessary for the @@ -583,9 +599,9 @@ nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData, mozStorageStatementScoper scoper(statement); // the insert and update statements share all but the 0th parameter - rv = statement->BindBlobParameter(1, aData, aDataLen); + rv = statement->BindBlobParameter(1, data, dataLen); NS_ENSURE_SUCCESS(rv, rv); - rv = statement->BindUTF8StringParameter(2, aMimeType); + rv = statement->BindUTF8StringParameter(2, *mimeType); NS_ENSURE_SUCCESS(rv, rv); rv = statement->BindInt64Parameter(3, aExpiration); NS_ENSURE_SUCCESS(rv, rv); @@ -800,6 +816,48 @@ nsFaviconService::GetFaviconSpecForIconString(const nsCString& aSpec, nsACString } +// nsFaviconService::OptimizeFaviconImage +// +// Given a blob of data (a image file already read into a buffer), optimize +// its size by recompressing it as a 16x16 PNG. +nsresult +nsFaviconService::OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen, + const nsACString& aMimeType, + nsACString& aNewData, + nsACString& aNewMimeType) +{ + nsresult rv; + + + nsCOMPtr imgtool = do_CreateInstance("@mozilla.org/image/tools;1"); + + nsCOMPtr stream; + rv = NS_NewByteInputStream(getter_AddRefs(stream), + reinterpret_cast(aData), aDataLen, + NS_ASSIGNMENT_DEPEND); + NS_ENSURE_SUCCESS(rv, rv); + + // decode image + nsCOMPtr container; + rv = imgtool->DecodeImageData(stream, aMimeType, getter_AddRefs(container)); + NS_ENSURE_SUCCESS(rv, rv); + + aNewMimeType.AssignLiteral("image/png"); + + // scale and recompress + nsCOMPtr iconStream; + rv = imgtool->EncodeScaledImage(container, aNewMimeType, 16, 16, + getter_AddRefs(iconStream)); + NS_ENSURE_SUCCESS(rv, rv); + + // Read the stream into a new buffer. + rv = NS_ConsumeStream(iconStream, PR_UINT32_MAX, aNewData); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + + NS_IMPL_ISUPPORTS4(FaviconLoadListener, nsIRequestObserver, nsIStreamListener, @@ -926,9 +984,6 @@ FaviconLoadListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext nsIInputStream *aInputStream, PRUint32 aOffset, PRUint32 aCount) { - if (aOffset + aCount > MAX_FAVICON_SIZE) - return NS_ERROR_FAILURE; // too big - nsCString buffer; nsresult rv = NS_ConsumeStream(aInputStream, aCount, buffer); if (rv != NS_BASE_STREAM_WOULD_BLOCK && NS_FAILED(rv)) diff --git a/toolkit/components/places/src/nsFaviconService.h b/toolkit/components/places/src/nsFaviconService.h index 5a15590d5c46..fd8970fb75a9 100644 --- a/toolkit/components/places/src/nsFaviconService.h +++ b/toolkit/components/places/src/nsFaviconService.h @@ -87,6 +87,9 @@ public: nsresult GetFaviconLinkForIconString(const nsCString& aIcon, nsIURI** aOutput); void GetFaviconSpecForIconString(const nsCString& aIcon, nsACString& aOutput); + static nsresult OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen, + const nsACString& aMimeType, + nsACString& aNewData, nsACString& aNewMimeType); NS_DECL_ISUPPORTS NS_DECL_NSIFAVICONSERVICE diff --git a/toolkit/components/places/src/nsLivemarkService.js b/toolkit/components/places/src/nsLivemarkService.js index 33b861502f0d..ece6c50e2524 100644 --- a/toolkit/components/places/src/nsLivemarkService.js +++ b/toolkit/components/places/src/nsLivemarkService.js @@ -147,8 +147,6 @@ function LivemarkService() { new G_ObserverServiceObserver('xpcom-shutdown', BindToObject(this._shutdown, this), true /*only once*/); - new G_Alarm(BindToObject(this._fireTimer, this), LIVEMARK_TIMEOUT, - true /* repeat */); if (IS_CONTRACTID in Cc) this._idleService = Cc[IS_CONTRACTID].getService(Ci.nsIIdleService); @@ -183,6 +181,14 @@ LivemarkService.prototype = { return this.__history; }, + _updateTimer: null, + start: function LS_start() { + if (this._updateTimer) + return; + this._updateTimer = new G_Alarm(BindToObject(this._fireTimer, this), + LIVEMARK_TIMEOUT, true /* repeat */); + }, + // returns new length of _livemarks _pushLivemark: function LS__pushLivemark(folderId, feedURI) { return this._livemarks.push({folderId: folderId, feedURI: feedURI}); @@ -204,6 +210,12 @@ LivemarkService.prototype = { if (livemark.loadGroup) livemark.loadGroup.cancel(NS_BINDING_ABORTED); } + + // kill timer + if (this._updateTimer) { + this._updateTimer.cancel(); + this._updateTimer = null; + } }, _fireTimer: function LS__fireTimer() { diff --git a/toolkit/components/places/src/nsNavBookmarks.cpp b/toolkit/components/places/src/nsNavBookmarks.cpp index 0fc6612cbfbe..7fb522e1cdeb 100644 --- a/toolkit/components/places/src/nsNavBookmarks.cpp +++ b/toolkit/components/places/src/nsNavBookmarks.cpp @@ -50,6 +50,7 @@ #include "nsAutoLock.h" #include "nsIUUIDGenerator.h" #include "prprf.h" +#include "nsILivemarkService.h" const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ID = 0; const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Type = 1; @@ -796,8 +797,6 @@ nsNavBookmarks::AdjustIndices(PRInt64 aFolder, { NS_ASSERTION(aStartIndex <= aEndIndex, "start index must be <= end index"); - mozIStorageConnection *dbConn = DBConn(); - nsCAutoString buffer; buffer.AssignLiteral("UPDATE moz_bookmarks SET position = position + "); buffer.AppendInt(aDelta); @@ -910,6 +909,43 @@ nsNavBookmarks::InsertBookmark(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex, NS_ENSURE_SUCCESS(rv, rv); *aNewBookmarkId = rowId; + // XXX + // 0n import / fx 2 migration, is the frecency work going to slow us down? + // We might want to skip this stuff, as well as the frecency work + // caused by GetUrlIdFor() which calls InternalAddNewPage(). + // If we do skip this, after import, we will + // need to call FixInvalidFrecenciesForExcludedPlaces(). + // We might need to call it anyways, if items aren't properly annotated + // as livemarks feeds yet. + + nsCAutoString url; + rv = aItem->GetSpec(url); + NS_ENSURE_SUCCESS(rv, rv); + + // prevent place: queries from showing up in the URL bar autocomplete results + PRBool isBookmark = !IsQueryURI(url); + + if (isBookmark) { + // if it is a livemark item (the parent is a livemark), + // we pass in false for isBookmark. otherwise, unvisited livemark + // items will appear in URL autocomplete before we visit them. + PRBool parentIsLivemark; + nsCOMPtr lms = + do_GetService(NS_LIVEMARKSERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = lms->IsLivemark(aFolder, &parentIsLivemark); + NS_ENSURE_SUCCESS(rv, rv); + + isBookmark = !parentIsLivemark; + } + + // when we created the moz_place entry for the new bookmark + // (a side effect of calling GetUrlIdFor()) frecency -1; + // now we re-calculate the frecency for this moz_place entry. + rv = History()->UpdateFrecency(childID, isBookmark); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetItemLastModified(aFolder, PR_Now()); NS_ENSURE_SUCCESS(rv, rv); @@ -1004,6 +1040,17 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId) rv = UpdateBookmarkHashOnRemove(placeId); NS_ENSURE_SUCCESS(rv, rv); + // XXX is this too expensive when updating livemarks? + // UpdateBookmarkHashOnRemove() does a sanity check using + // IsBookmarkedInDatabase(), so it might not have actually + // removed the bookmark. should we have a boolean out param + // for if we actually removed it, and use that to decide if we call + // UpdateFrecency() and the rest of this code? + if (itemType == TYPE_BOOKMARK) { + rv = History()->UpdateFrecency(placeId, PR_FALSE /* isBookmark */); + NS_ENSURE_SUCCESS(rv, rv); + } + ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, OnItemRemoved(aItemId, folderId, childIndex)) @@ -2012,6 +2059,7 @@ nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId, aOptions->ExcludeQueries()) || (nodeType != nsINavHistoryResultNode::RESULT_TYPE_QUERY && nodeType != nsINavHistoryResultNode::RESULT_TYPE_FOLDER && + nodeType != nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT && aOptions->ExcludeItems())) { continue; } @@ -2144,6 +2192,19 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI *aNewURI) rv = transaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); + // upon changing the uri for a bookmark, update the frecency for the new place + // no need to check if this is a livemark, because... + rv = History()->UpdateFrecency(placeId, PR_TRUE /* isBookmark */); + NS_ENSURE_SUCCESS(rv, rv); + +#if 0 + // upon changing the uri for a bookmark, update the frecency for the old place + // XXX todo, we need to get the oldPlaceId (fk) before changing it above + // and then here, we need to determine if that oldPlaceId is still a bookmark (and not a livemark) + rv = History()->UpdateFrecency(oldPlaceId, PR_FALSE /* isBookmark */); + NS_ENSURE_SUCCESS(rv, rv); +#endif + nsCAutoString spec; rv = aNewURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); diff --git a/toolkit/components/places/src/nsNavHistory.cpp b/toolkit/components/places/src/nsNavHistory.cpp index 07f0b6282051..f9e788f668cd 100644 --- a/toolkit/components/places/src/nsNavHistory.cpp +++ b/toolkit/components/places/src/nsNavHistory.cpp @@ -85,6 +85,9 @@ #include "nsAppDirectoryServiceDefs.h" #include "nsAutoLock.h" #include "nsIIdleService.h" +#include "nsILivemarkService.h" + +#include "nsMathUtils.h" // for NS_ceilf() // Microsecond timeout for "recent" events such as typed and bookmark following. // If you typed it more than this time ago, it's not recent. @@ -109,7 +112,29 @@ #define PREF_BROWSER_HISTORY_EXPIRE_SITES "history_expire_sites" #define PREF_AUTOCOMPLETE_ONLY_TYPED "urlbar.matchOnlyTyped" #define PREF_AUTOCOMPLETE_ENABLED "urlbar.autocomplete.enabled" +#define PREF_AUTOCOMPLETE_MAX_RICH_RESULTS "urlbar.maxRichResults" #define PREF_DB_CACHE_PERCENTAGE "history_cache_percentage" +#define PREF_FRECENCY_NUM_VISITS "places.frecency.numVisits" +#define PREF_FRECENCY_UPDATE_IDLE_TIME "places.frecency.updateIdleTime" +#define PREF_FRECENCY_FIRST_BUCKET_CUTOFF "places.frecency.firstBucketCutoff" +#define PREF_FRECENCY_SECOND_BUCKET_CUTOFF "places.frecency.secondBucketCutoff" +#define PREF_FRECENCY_THIRD_BUCKET_CUTOFF "places.frecency.thirdBucketCutoff" +#define PREF_FRECENCY_FOURTH_BUCKET_CUTOFF "places.frecency.fourthBucketCutoff" +#define PREF_FRECENCY_FIRST_BUCKET_WEIGHT "places.frecency.firstBucketWeight" +#define PREF_FRECENCY_SECOND_BUCKET_WEIGHT "places.frecency.secondBucketWeight" +#define PREF_FRECENCY_THIRD_BUCKET_WEIGHT "places.frecency.thirdBucketWeight" +#define PREF_FRECENCY_FOURTH_BUCKET_WEIGHT "places.frecency.fourthBucketWeight" +#define PREF_FRECENCY_DEFAULT_BUCKET_WEIGHT "places.frecency.defaultBucketWeight" +#define PREF_FRECENCY_EMBED_VISIT_BONUS "places.frecency.embedVisitBonus" +#define PREF_FRECENCY_LINK_VISIT_BONUS "places.frecency.linkVisitBonus" +#define PREF_FRECENCY_TYPED_VISIT_BONUS "places.frecency.typedVisitBonus" +#define PREF_FRECENCY_BOOKMARK_VISIT_BONUS "places.frecency.bookmarkVisitBonus" +#define PREF_FRECENCY_DOWNLOAD_VISIT_BONUS "places.frecency.downloadVisitBonus" +#define PREF_FRECENCY_PERM_REDIRECT_VISIT_BONUS "places.frecency.permRedirectVisitBonus" +#define PREF_FRECENCY_TEMP_REDIRECT_VISIT_BONUS "places.frecency.tempRedirectVisitBonus" +#define PREF_FRECENCY_DEFAULT_VISIT_BONUS "places.frecency.defaultVisitBonus" +#define PREF_FRECENCY_UNVISITED_BOOKMARK_BONUS "places.frecency.unvisitedBookmarkBonus" +#define PREF_FRECENCY_UNVISITED_TYPED_BONUS "places.frecency.unvisitedTypedBonus" #define PREF_BROWSER_IMPORT_BOOKMARKS "browser.places.importBookmarksHTML" #define PREF_BROWSER_IMPORT_DEFAULTS "browser.places.importDefaults" #define PREF_BROWSER_CREATEDSMARTBOOKMARKS "browser.places.createdSmartBookmarks" @@ -156,11 +181,7 @@ #endif // LAZY_ADD -// check idle timer every 5 minutes -#define IDLE_TIMER_TIMEOUT (300 * PR_MSEC_PER_SEC) - -// *** CURRENTLY DISABLED *** -// Perform vacuum after 15 minutes of idle time, repeating. +// Perform "long idle" tasks after 15 minutes of idle time, repeating. // 15 minutes = 900 seconds = 900000 milliseconds #define LONG_IDLE_TIME_IN_MSECS (900000) @@ -168,12 +189,22 @@ // 5 minutes = 300 seconds = 300000 milliseconds #define EXPIRE_IDLE_TIME_IN_MSECS (300000) +// Number of records to update frecency for when idle. +// Amount is low, since we're doing work often (see mFrecencyUpdateIdleTime), +// the idea being to constantly keep the first few chunks up to date. +#define COUNT_TO_RECALCULATE_FRECENCY_ON_IDLE 10 + // Amount of items to expire at idle time. #define MAX_EXPIRE_RECORDS_ON_IDLE 200 // Limit the number of items in the history for performance reasons #define EXPIRATION_CAP_SITES 40000 +// DB migration types +#define DB_MIGRATION_NONE 0 +#define DB_MIGRATION_CREATED 1 +#define DB_MIGRATION_UPDATED 2 + NS_IMPL_ADDREF(nsNavHistory) NS_IMPL_RELEASE(nsNavHistory) @@ -185,8 +216,10 @@ NS_INTERFACE_MAP_BEGIN(nsNavHistory) NS_INTERFACE_MAP_ENTRY(nsIBrowserHistory) NS_INTERFACE_MAP_ENTRY(nsIObserver) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +#ifdef MOZ_XUL NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteSearch) NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteSimpleResultListener) +#endif NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINavHistoryService) NS_INTERFACE_MAP_END @@ -256,6 +289,7 @@ const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1; const PRInt32 nsNavHistory::kAutoCompleteIndex_FaviconURL = 2; const PRInt32 nsNavHistory::kAutoCompleteIndex_ItemId = 3; const PRInt32 nsNavHistory::kAutoCompleteIndex_ParentId = 4; +const PRInt32 nsNavHistory::kAutoCompleteIndex_BookmarkTitle = 5; static nsDataHashtable* gTldTypes; static const char* gQuitApplicationMessage = "quit-application"; @@ -276,6 +310,7 @@ nsNavHistory::nsNavHistory() : mNowValid(PR_FALSE), mExpireDaysMax(0), mExpireSites(0), mAutoCompleteOnlyTyped(PR_FALSE), + mAutoCompleteMaxResults(25), mBatchLevel(0), mLock(nsnull), mBatchHasTransaction(PR_FALSE), @@ -321,19 +356,22 @@ nsNavHistory::Init() mLock = PR_NewLock(); NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY); + // prefs + LoadPrefs(PR_TRUE); + // init db file rv = InitDBFile(PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); // init db and statements - PRBool doImport; - rv = InitDB(&doImport); + PRInt16 migrationType; + rv = InitDB(&migrationType); if (NS_FAILED(rv)) { // if unable to initialize the db, force-re-initialize it: // InitDBFile will backup the old db and create a new one. rv = InitDBFile(PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); - rv = InitDB(&doImport); + rv = InitDB(&migrationType); } NS_ENSURE_SUCCESS(rv, rv); @@ -342,8 +380,10 @@ nsNavHistory::Init() NS_ENSURE_SUCCESS(rv, rv); #endif +#ifdef MOZ_XUL rv = InitAutoComplete(); NS_ENSURE_SUCCESS(rv, rv); +#endif // extract the last session ID so we know where to pick up. There is no index // over sessions so the naive statement "SELECT MAX(session) FROM @@ -392,8 +432,8 @@ nsNavHistory::Init() mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - // prefs - LoadPrefs(); + // initialize idle timer + InitializeIdleTimer(); // recent events hash tables NS_ENSURE_TRUE(mRecentTyped.Init(128), NS_ERROR_OUT_OF_MEMORY); @@ -412,6 +452,7 @@ nsNavHistory::Init() nsCOMPtr pbi = do_QueryInterface(mPrefBranch); if (pbi) { pbi->AddObserver(PREF_AUTOCOMPLETE_ONLY_TYPED, this, PR_FALSE); + pbi->AddObserver(PREF_AUTOCOMPLETE_MAX_RICH_RESULTS, this, PR_FALSE); pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX, this, PR_FALSE); pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN, this, PR_FALSE); pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_SITES, this, PR_FALSE); @@ -420,7 +461,7 @@ nsNavHistory::Init() observerService->AddObserver(this, gQuitApplicationMessage, PR_FALSE); observerService->AddObserver(this, gXpcomShutdown, PR_FALSE); - if (doImport) { + if (migrationType == DB_MIGRATION_CREATED) { nsCOMPtr historyFile; rv = NS_GetSpecialDirectory(NS_APP_HISTORY_50_FILE, getter_AddRefs(historyFile)); @@ -429,6 +470,12 @@ nsNavHistory::Init() } } + // In case we've either imported or done a migration from a pre-frecency build, + // calculate the first cutoff period's frecencies now. + // Swallow errors here to not block initialization. + if (migrationType != DB_MIGRATION_NONE) + (void)RecalculateFrecencies(); + // Don't add code that can fail here! Do it up above, before we add our // observers. @@ -553,11 +600,11 @@ nsNavHistory::InitDBFile(PRBool aForceInit) #define PLACES_SCHEMA_VERSION 6 nsresult -nsNavHistory::InitDB(PRBool *aDoImport) +nsNavHistory::InitDB(PRInt16 *aMadeChanges) { nsresult rv; PRBool tableExists; - *aDoImport = PR_FALSE; + *aMadeChanges = DB_MIGRATION_NONE; // IMPORTANT NOTE: // setting page_size must happen first, see bug #401985 for details @@ -570,16 +617,6 @@ nsNavHistory::InitDB(PRBool *aDoImport) rv = mDBConn->ExecuteSimpleSQL(pageSizePragma); NS_ENSURE_SUCCESS(rv, rv); - if (!mIdleTimer) { - mIdleTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mIdleTimer->InitWithFuncCallback(IdleTimerCallback, this, - IDLE_TIMER_TIMEOUT, - nsITimer::TYPE_REPEATING_SLACK); - NS_ENSURE_SUCCESS(rv, rv); - } - mozStorageTransaction transaction(mDBConn, PR_FALSE); // Initialize the other places services' database tables. We do this before @@ -663,10 +700,6 @@ nsNavHistory::InitDB(PRBool *aDoImport) rv = UpdateSchemaVersion(); NS_ENSURE_SUCCESS(rv, rv); } - else { - rv = EnsureCurrentSchema(mDBConn); - NS_ENSURE_SUCCESS(rv, rv); - } // Get the page size. This may be different than was set above if the database // file already existed and has a different page size. @@ -710,7 +743,7 @@ nsNavHistory::InitDB(PRBool *aDoImport) // moz_places if (!tableExists) { - *aDoImport = PR_TRUE; + *aMadeChanges = DB_MIGRATION_CREATED; rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_places (" "id INTEGER PRIMARY KEY, " "url LONGVARCHAR, " @@ -719,7 +752,8 @@ nsNavHistory::InitDB(PRBool *aDoImport) "visit_count INTEGER DEFAULT 0, " "hidden INTEGER DEFAULT 0 NOT NULL, " "typed INTEGER DEFAULT 0 NOT NULL, " - "favicon_id INTEGER)")); + "favicon_id INTEGER, " + "frecency INTEGER DEFAULT -1 NOT NULL)")); NS_ENSURE_SUCCESS(rv, rv); rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( @@ -738,6 +772,10 @@ nsNavHistory::InitDB(PRBool *aDoImport) rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "CREATE INDEX moz_places_visitcount ON moz_places (visit_count)")); NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX moz_places_frecencyindex ON moz_places (frecency)")); + NS_ENSURE_SUCCESS(rv, rv); } // moz_historyvisits @@ -769,6 +807,12 @@ nsNavHistory::InitDB(PRBool *aDoImport) NS_ENSURE_SUCCESS(rv, rv); } + PRBool migrated = PR_FALSE; + rv = EnsureCurrentSchema(mDBConn, &migrated); + NS_ENSURE_SUCCESS(rv, rv); + if (migrated && *aMadeChanges != DB_MIGRATION_CREATED) + *aMadeChanges = DB_MIGRATION_UPDATED; + rv = transaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); @@ -782,6 +826,29 @@ nsNavHistory::InitDB(PRBool *aDoImport) return NS_OK; } +nsresult +nsNavHistory::InitializeIdleTimer() +{ + if (mIdleTimer) { + mIdleTimer->Cancel(); + mIdleTimer = nsnull; + } + nsresult rv; + mIdleTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 idleTimerTimeout = PR_MIN(LONG_IDLE_TIME_IN_MSECS, + EXPIRE_IDLE_TIME_IN_MSECS); + if (mFrecencyUpdateIdleTime) + idleTimerTimeout = PR_MIN(idleTimerTimeout, mFrecencyUpdateIdleTime); + + rv = mIdleTimer->InitWithFuncCallback(IdleTimerCallback, this, + idleTimerTimeout, + nsITimer::TYPE_REPEATING_SLACK); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + // nsNavHistory::UpdateSchemaVersion // // Called by the individual services' InitTables() @@ -852,8 +919,8 @@ nsNavHistory::InitStatements() // mDBAddNewPage (see InternalAddNewPage) rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "INSERT OR REPLACE INTO moz_places " - "(url, title, rev_host, hidden, typed, visit_count) " - "VALUES (?1, ?2, ?3, ?4, ?5, ?6)"), + "(url, title, rev_host, hidden, typed, visit_count, frecency) " + "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"), getter_AddRefs(mDBAddNewPage)); NS_ENSURE_SUCCESS(rv, rv); @@ -922,6 +989,92 @@ nsNavHistory::InitStatements() getter_AddRefs(mFoldersWithAnnotationQuery)); NS_ENSURE_SUCCESS(rv, rv); + // mDBVisitsForFrecency + // NOTE: we are not limiting to visits with "visit_type NOT IN (0,4)" + // because if we do that, mDBVisitsForFrecency would return no visits + // for places with only embed (or undefined) visits. That would + // cause use to estimate a frecency based on what information we do have, + // see CalculateFrecencyInternal(). that would result in a + // non-zero frecency for a place with only + // embedded visits, instead of a frecency of 0. + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT visit_date, visit_type FROM moz_historyvisits " + "WHERE place_id = ?1 ORDER BY visit_date DESC LIMIT ") + + nsPrintfCString("%d", mNumVisitsForFrecency), + getter_AddRefs(mDBVisitsForFrecency)); + NS_ENSURE_SUCCESS(rv, rv); + + // find places with invalid frecencies (frecency = -1) + // invalid frecencies can happen in these scenarios: + // 1) we've done "clear private data" + // 2) we've expired or deleted visits + // 3) we've migrated from an older version, before global frecency + // + // from older versions, unmigrated bookmarks might be hidden, + // so we can't exclude hidden places (by doing "WHERE hidden <> 1") + // from our query, as we want to calculate the frecency for those + // places and unhide them (if they are not livemark items and not + // place: queries.) + // + // Note, we are not limiting ourselves to places with visits + // because we may not have any if the place is a bookmark and + // we expired or deleted all the visits. + // we sort by visit count (even though it might not be correct + // as those visits could have been removed or expired.) + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT id, visit_count, hidden, typed, frecency, url " + "FROM moz_places WHERE frecency = -1 " + "ORDER BY visit_count DESC LIMIT ") + + nsPrintfCString("%d", COUNT_TO_RECALCULATE_FRECENCY_ON_IDLE), + getter_AddRefs(mDBInvalidFrecencies)); + NS_ENSURE_SUCCESS(rv, rv); + + // this query is designed to find places with high frecency and + // an "old" max visit_date. + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT h.id, h.visit_count, h.hidden, h.typed, h.frecency, h.url " + "FROM moz_places h WHERE " + SQL_STR_FRAGMENT_MAX_VISIT_DATE( "h.id" ) + " < ?1 ORDER BY h.frecency DESC LIMIT ") + + nsPrintfCString("%d", COUNT_TO_RECALCULATE_FRECENCY_ON_IDLE), + getter_AddRefs(mDBOldFrecencies)); + NS_ENSURE_SUCCESS(rv, rv); + + // mDBUpdateFrecencyAndHidden + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "UPDATE moz_places SET frecency = ?2, hidden = ?3 WHERE id = ?1"), + getter_AddRefs(mDBUpdateFrecencyAndHidden)); + NS_ENSURE_SUCCESS(rv, rv); + + // mDBGetPlaceVisitStats + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT typed, hidden, frecency FROM moz_places WHERE id = ?1"), + getter_AddRefs(mDBGetPlaceVisitStats)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT b.parent FROM moz_places h JOIN moz_bookmarks b " + " on b.fk = h.id WHERE b.type = 1 and h.id = ?1"), + getter_AddRefs(mDBGetBookmarkParentsForPlace)); + NS_ENSURE_SUCCESS(rv, rv); + + // when calculating frecency, we want the visit count to be + // all the visits. + rv = mDBConn->CreateStatement( + NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_historyvisits " + "WHERE place_id = ?1"), + getter_AddRefs(mDBVisitCountForFrecency)); + NS_ENSURE_SUCCESS(rv, rv); + + // this query is used to calculate the visit_count column + // which we use in the UI. to the end user, we should not count + // embedded (or undefined) visits. + rv = mDBConn->CreateStatement( + NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_historyvisits " + "WHERE visit_type NOT IN(0,4) AND place_id = ?1"), + getter_AddRefs(mDBTrueVisitCount)); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } @@ -1034,7 +1187,7 @@ nsNavHistory::MigrateV6Up(mozIStorageConnection* aDBConn) } nsresult -nsNavHistory::EnsureCurrentSchema(mozIStorageConnection* aDBConn) +nsNavHistory::EnsureCurrentSchema(mozIStorageConnection* aDBConn, PRBool* aDidMigrate) { // We need to do a one-time change of the moz_historyvisits.pageindex // to speed up finding last visit date when joinin with moz_places. @@ -1045,6 +1198,7 @@ nsNavHistory::EnsureCurrentSchema(mozIStorageConnection* aDBConn) NS_ENSURE_SUCCESS(rv, rv); if (oldIndexExists) { + *aDidMigrate = PR_TRUE; // wrap in a transaction for safety and performance mozStorageTransaction pageindexTransaction(aDBConn, PR_FALSE); @@ -1062,6 +1216,44 @@ nsNavHistory::EnsureCurrentSchema(mozIStorageConnection* aDBConn) rv = pageindexTransaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); } + + // for existing profiles, we may not have a frecency column + nsCOMPtr statement; + rv = aDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT frecency FROM moz_places"), getter_AddRefs(statement)); + + if (NS_FAILED(rv)) { + *aDidMigrate = PR_TRUE; + // wrap in a transaction for safety and performance + mozStorageTransaction frecencyTransaction(aDBConn, PR_FALSE); + + // add frecency column to moz_places, default to -1 + // so that all the frecencies are invalid and we'll + // recalculate them on idle. + rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "ALTER TABLE moz_places ADD frecency INTEGER DEFAULT -1 NOT NULL")); + NS_ENSURE_SUCCESS(rv, rv); + + // create index for the frecency column + // XXX multi column index with typed, and visit_count? + rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX IF NOT EXISTS " + "moz_places_frecencyindex ON moz_places (frecency)")); + NS_ENSURE_SUCCESS(rv, rv); + + // XXX todo + // forcibly call the "on idle" timer here to do a little work + // but the rest will happen on idle. + + // for place: items and unvisited livemark items, we need to set + // the frecency to 0 so that they don't show up in url bar autocomplete + rv = FixInvalidFrecenciesForExcludedPlaces(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = frecencyTransaction.Commit(); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; } @@ -1093,6 +1285,9 @@ nsNavHistory::CleanUpOnQuit() rv = mDBConn->ExecuteSimpleSQL( NS_LITERAL_CSTRING("DROP INDEX IF EXISTS moz_places_visitcount")); NS_ENSURE_SUCCESS(rv, rv); + rv = mDBConn->ExecuteSimpleSQL( + NS_LITERAL_CSTRING("DROP INDEX IF EXISTS moz_places_frecencyindex")); + NS_ENSURE_SUCCESS(rv, rv); // 2. remove any duplicate URIs rv = RemoveDuplicateURIs(); @@ -1112,7 +1307,8 @@ nsNavHistory::CleanUpOnQuit() "visit_count INTEGER DEFAULT 0, " "hidden INTEGER DEFAULT 0 NOT NULL, " "typed INTEGER DEFAULT 0 NOT NULL, " - "favicon_id INTEGER)")); + "favicon_id INTEGER, " + "frecency INTEGER DEFAULT -1 NOT NULL)")); NS_ENSURE_SUCCESS(rv, rv); // 5. recreate the indexes @@ -1130,11 +1326,14 @@ nsNavHistory::CleanUpOnQuit() rv = mDBConn->ExecuteSimpleSQL( NS_LITERAL_CSTRING("CREATE INDEX moz_places_visitcount ON moz_places (visit_count)")); NS_ENSURE_SUCCESS(rv, rv); + rv = mDBConn->ExecuteSimpleSQL( + NS_LITERAL_CSTRING("CREATE INDEX moz_places_frecencyindex ON moz_places (frecency)")); + NS_ENSURE_SUCCESS(rv, rv); // 6. copy all data into moz_places rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "INSERT INTO moz_places " - "SELECT id, url, title, rev_host, visit_count, hidden, typed, favicon_id " + "SELECT id, url, title, rev_host, visit_count, hidden, typed, favicon_id, frecency " "FROM moz_places_backup")); NS_ENSURE_SUCCESS(rv, rv); @@ -1248,7 +1447,7 @@ nsNavHistory::GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID, statementResetter.Abandon(); nsString voidString; voidString.SetIsVoid(PR_TRUE); - return InternalAddNewPage(aURI, voidString, PR_TRUE, PR_FALSE, 0, aEntryID); + return InternalAddNewPage(aURI, voidString, PR_TRUE, PR_FALSE, 0, PR_TRUE, aEntryID); } else { // Doesn't exist: don't do anything, entry ID was already set to 0 above return NS_OK; @@ -1267,7 +1466,9 @@ nsNavHistory::GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID, nsresult nsNavHistory::InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle, PRBool aHidden, PRBool aTyped, - PRInt32 aVisitCount, PRInt64* aPageID) + PRInt32 aVisitCount, + PRBool aCalculateFrecency, + PRInt64* aPageID) { mozStorageStatementScoper scoper(mDBAddNewPage); nsresult rv = BindStatementURI(mDBAddNewPage, 0, aURI); @@ -1309,6 +1510,22 @@ nsNavHistory::InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle, rv = mDBAddNewPage->BindInt32Parameter(5, aVisitCount); NS_ENSURE_SUCCESS(rv, rv); + nsCAutoString url; + rv = aURI->GetSpec(url); + NS_ENSURE_SUCCESS(rv, rv); + + // frecency + PRInt32 frecency = -1; + if (aCalculateFrecency) { + rv = CalculateFrecency(-1 /* no page id, since this page doesn't exist */, + aTyped, aVisitCount, url, + &frecency); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = mDBAddNewPage->BindInt32Parameter(6, frecency); + NS_ENSURE_SUCCESS(rv, rv); + rv = mDBAddNewPage->Execute(); NS_ENSURE_SUCCESS(rv, rv); @@ -1321,7 +1538,6 @@ nsNavHistory::InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle, return NS_OK; } - // nsNavHistory::InternalAddVisit // // Just a wrapper for inserting a new visit in the DB. @@ -1435,7 +1651,7 @@ PRBool nsNavHistory::IsURIStringVisited(const nsACString& aURIString) // nsNavHistory::LoadPrefs nsresult -nsNavHistory::LoadPrefs() +nsNavHistory::LoadPrefs(PRBool aInitializing) { if (! mPrefBranch) return NS_OK; @@ -1446,14 +1662,65 @@ nsNavHistory::LoadPrefs() &mExpireSites))) mExpireSites = EXPIRATION_CAP_SITES; +#ifdef MOZ_XUL PRBool oldCompleteOnlyTyped = mAutoCompleteOnlyTyped; mPrefBranch->GetBoolPref(PREF_AUTOCOMPLETE_ONLY_TYPED, &mAutoCompleteOnlyTyped); - if (oldCompleteOnlyTyped != mAutoCompleteOnlyTyped) { + mPrefBranch->GetBoolPref(PREF_AUTOCOMPLETE_MAX_RICH_RESULTS, + &mAutoCompleteMaxResults); + if (!aInitializing && oldCompleteOnlyTyped != mAutoCompleteOnlyTyped) { // update the autocomplete statements if the option has changed. nsresult rv = CreateAutoCompleteQueries(); NS_ENSURE_SUCCESS(rv, rv); } +#endif + + // get the frecency prefs + nsCOMPtr prefs(do_GetService("@mozilla.org/preferences-service;1")); + if (prefs) { + prefs->GetIntPref(PREF_FRECENCY_NUM_VISITS, + &mNumVisitsForFrecency); + prefs->GetIntPref(PREF_FRECENCY_UPDATE_IDLE_TIME, + &mFrecencyUpdateIdleTime); + prefs->GetIntPref(PREF_FRECENCY_FIRST_BUCKET_CUTOFF, + &mFirstBucketCutoffInDays); + prefs->GetIntPref(PREF_FRECENCY_SECOND_BUCKET_CUTOFF, + &mSecondBucketCutoffInDays); + prefs->GetIntPref(PREF_FRECENCY_THIRD_BUCKET_CUTOFF, + &mThirdBucketCutoffInDays); + prefs->GetIntPref(PREF_FRECENCY_FOURTH_BUCKET_CUTOFF, + &mFourthBucketCutoffInDays); + prefs->GetIntPref(PREF_FRECENCY_EMBED_VISIT_BONUS, + &mEmbedVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_LINK_VISIT_BONUS, + &mLinkVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_TYPED_VISIT_BONUS, + &mTypedVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_BOOKMARK_VISIT_BONUS, + &mBookmarkVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_DOWNLOAD_VISIT_BONUS, + &mDownloadVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_PERM_REDIRECT_VISIT_BONUS, + &mPermRedirectVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_TEMP_REDIRECT_VISIT_BONUS, + &mTempRedirectVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_DEFAULT_VISIT_BONUS, + &mDefaultVisitBonus); + prefs->GetIntPref(PREF_FRECENCY_UNVISITED_BOOKMARK_BONUS, + &mUnvisitedBookmarkBonus); + prefs->GetIntPref(PREF_FRECENCY_UNVISITED_TYPED_BONUS, + &mUnvisitedTypedBonus); + prefs->GetIntPref(PREF_FRECENCY_FIRST_BUCKET_WEIGHT, + &mFirstBucketWeight); + prefs->GetIntPref(PREF_FRECENCY_SECOND_BUCKET_WEIGHT, + &mSecondBucketWeight); + prefs->GetIntPref(PREF_FRECENCY_THIRD_BUCKET_WEIGHT, + &mThirdBucketWeight); + prefs->GetIntPref(PREF_FRECENCY_FOURTH_BUCKET_WEIGHT, + &mFourthBucketWeight); + prefs->GetIntPref(PREF_FRECENCY_DEFAULT_BUCKET_WEIGHT, + &mDefaultWeight); + } return NS_OK; } @@ -1792,6 +2059,62 @@ nsNavHistory::GetHasHistoryEntries(PRBool* aHasEntries) return dbSelectStatement->ExecuteStep(aHasEntries); } +nsresult +nsNavHistory::FixInvalidFrecenciesForExcludedPlaces() +{ + // for every moz_place that has an invalid frecency (-1) and + // begins with "place:" or is an unvisited child of a livemark feed, + // set frecency to 0 so that it is excluded from url bar autocomplete. + nsCOMPtr dbUpdateStatement; + nsresult rv = mDBConn->CreateStatement( + NS_LITERAL_CSTRING("UPDATE moz_places SET frecency = 0 WHERE id IN (" + "SELECT h.id FROM moz_places h JOIN moz_bookmarks b ON h.id = b.fk " + "WHERE frecency = -1 " + // place is not a livemark feed item + "AND (b.parent IN (" + "SELECT annos.item_id FROM moz_anno_attributes attrs " + "JOIN moz_items_annos annos ON attrs.id = annos.anno_attribute_id " + "WHERE attrs.name = ?1) " + // place has no visits (that are not invalid or embedded) + "AND (SELECT visit_date FROM moz_historyvisits " + "WHERE place_id = h.id AND visit_type NOT IN (0,4) LIMIT 1) is null) " + "OR SUBSTR(h.url,0,6) = 'place:')"), + getter_AddRefs(dbUpdateStatement)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = dbUpdateStatement->BindUTF8StringParameter(0, NS_LITERAL_CSTRING(LMANNO_FEEDURI)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = dbUpdateStatement->Execute(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +nsNavHistory::CalculateVisitCount(PRInt64 aPlaceId, PRBool aForFrecency, PRInt32 *aVisitCount) +{ + nsCOMPtr dbSelectStatement = + aForFrecency ? mDBVisitCountForFrecency : mDBTrueVisitCount; + + mozStorageStatementScoper scope(dbSelectStatement); + + nsresult rv = dbSelectStatement->BindInt64Parameter(0, aPlaceId); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasVisits = PR_TRUE; + rv = dbSelectStatement->ExecuteStep(&hasVisits); + NS_ENSURE_SUCCESS(rv, rv); + + if (hasVisits) { + rv = dbSelectStatement->GetInt32(0, aVisitCount); + NS_ENSURE_SUCCESS(rv, rv); + } + else + *aVisitCount = 0; + + return NS_OK; +} // nsNavHistory::MarkPageAsFollowedBookmark // @@ -1811,9 +2134,10 @@ nsNavHistory::MarkPageAsFollowedBookmark(nsIURI* aURI) return NS_OK; nsCAutoString uriString; - aURI->GetSpec(uriString); + nsresult rv = aURI->GetSpec(uriString); + NS_ENSURE_SUCCESS(rv, rv); - // if URL is already in the queue, then we need to remove the old one + // if URL is already in the bookmark queue, then we need to remove the old one PRInt64 unusedEventTime; if (mRecentBookmark.Get(uriString, &unusedEventTime)) mRecentBookmark.Remove(uriString); @@ -1837,10 +2161,8 @@ nsNavHistory::MarkPageAsFollowedBookmark(nsIURI* aURI) nsresult nsNavHistory::CanAddURI(nsIURI* aURI, PRBool* canAdd) { - nsresult rv; - - nsCString scheme; - rv = aURI->GetScheme(scheme); + nsCAutoString scheme; + nsresult rv = aURI->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, rv); // first check the most common cases (HTTP, HTTPS) to allow in to avoid most @@ -1896,6 +2218,8 @@ nsNavHistory::SetPageDetails(nsIURI* aURI, const nsAString& aTitle, rv = statement->BindInt64Parameter(0, pageID); NS_ENSURE_SUCCESS(rv, rv); + // XXX should we be calculating / setting frecency here? + // for the titles, be careful to interpret isVoid as NULL SQL command so that // we can tell the difference between "set to empty" and "unset" if (aTitle.IsVoid()) @@ -1931,11 +2255,9 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI, PRInt32 aTransitionType, PRBool aIsRedirect, PRInt64 aSessionID, PRInt64* aVisitID) { - nsresult rv; - // Filter out unwanted URIs, silently failing PRBool canAdd = PR_FALSE; - rv = CanAddURI(aURI, &canAdd); + nsresult rv = CanAddURI(aURI, &canAdd); NS_ENSURE_SUCCESS(rv, rv); if (!canAdd) { *aVisitID = 0; @@ -1961,8 +2283,8 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI, rv = mDBGetPageVisitStats->ExecuteStep(&alreadyVisited); PRInt64 pageID = 0; - PRBool hidden; - PRBool typed; + PRBool hidden; // XXX fix me, this should not be a PRBool, as we later do BindInt32Parameter() + PRBool typed; // XXX fix me, this should not be a PRBool, as we later do BindInt32Parameter() PRBool newItem = PR_FALSE; // used to send out notifications at the end if (alreadyVisited) { // Update the existing entry... @@ -1999,26 +2321,39 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI, // the history UI (sidebar, history menu, url bar autocomplete, etc) hidden = oldHiddenState; if (hidden && (!aIsRedirect || aTransitionType == TRANSITION_TYPED) && - aTransitionType != nsINavHistoryService::TRANSITION_EMBED) + aTransitionType != TRANSITION_EMBED) hidden = PR_FALSE; // unhide typed = oldTypedState || (aTransitionType == TRANSITION_TYPED); - // some items may have a visit count of 0 which will not count for link + PRInt32 trueVisitCount = 0; + + // we can't trust the visit_count in the moz_places, because... + rv = CalculateVisitCount(pageID, PR_FALSE /* not for frecency */, + &trueVisitCount); + + // some items may have a true visit count of 0 which will not count for link // visiting, so be sure to note this transition - if (oldVisitCount == 0) + if (trueVisitCount == 0) newItem = PR_TRUE; // update with new stats mozStorageStatementScoper updateScoper(mDBUpdatePageVisitStats); rv = mDBUpdatePageVisitStats->BindInt64Parameter(0, pageID); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBUpdatePageVisitStats->BindInt32Parameter(1, oldVisitCount + 1); + + // only increment the visit_count if the transition was not EMBED + // XXX what about TRANSITION_DOWNLOAD? (bug 412217) + if (aTransitionType != TRANSITION_EMBED) + trueVisitCount++; + + rv = mDBUpdatePageVisitStats->BindInt32Parameter(1, trueVisitCount); NS_ENSURE_SUCCESS(rv, rv); rv = mDBUpdatePageVisitStats->BindInt32Parameter(2, hidden); NS_ENSURE_SUCCESS(rv, rv); rv = mDBUpdatePageVisitStats->BindInt32Parameter(3, typed); NS_ENSURE_SUCCESS(rv, rv); + rv = mDBUpdatePageVisitStats->Execute(); NS_ENSURE_SUCCESS(rv, rv); } else { @@ -2039,7 +2374,7 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI, // set as visited once, no title nsString voidString; voidString.SetIsVoid(PR_TRUE); - rv = InternalAddNewPage(aURI, voidString, hidden, typed, 1, &pageID); + rv = InternalAddNewPage(aURI, voidString, hidden, typed, 1, PR_TRUE, &pageID); NS_ENSURE_SUCCESS(rv, rv); } @@ -2057,18 +2392,23 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI, rv = InternalAddVisit(pageID, referringVisitID, aSessionID, aTime, aTransitionType, aVisitID); + transaction.Commit(); + + // Update frecency (*after* the visit info is in the db) + // Swallow errors here, since if we've gotten this far, it's more + // important to notify the observers below. + (void)UpdateFrecency(pageID, PR_FALSE); // Notify observers: The hidden detection code must match that in // GetQueryResults to maintain consistency. // FIXME bug 325241: make a way to observe hidden URLs - transaction.Commit(); if (! hidden && aTransitionType != TRANSITION_EMBED) { ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver, OnVisit(aURI, *aVisitID, aTime, aSessionID, referringVisitID, aTransitionType)); } - // Normally docshell send the link visited observer notification for us (this + // Normally docshell sends the link visited observer notification for us (this // will tell all the documents to update their visited link coloring). // However, for redirects (since we implement nsIGlobalHistory3) and downloads // (since we implement nsIDownloadHistory) this will not happen and we need to @@ -2798,6 +3138,32 @@ nsNavHistory::RemovePage(nsIURI *aURI) rv = statement->Execute(); NS_ENSURE_SUCCESS(rv, rv); } + else { + // because the moz_place was annotated (or it was a bookmark), + // we didn't delete it, but we did delete the moz_visits + // so we need to reset the frecency. Note, we don't + // reset the visit_count, as we use that in our "on idle" + // query to figure out which places to recalcuate frecency first. + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "UPDATE moz_places SET frecency = -1 WHERE id = ?1"), + getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); + rv = statement->BindInt64Parameter(0, placeId); + NS_ENSURE_SUCCESS(rv, rv); + rv = statement->Execute(); + NS_ENSURE_SUCCESS(rv, rv); + + // placeId could have a livemark item, so setting the frecency to -1 + // would cause it to show up in the url bar autocomplete + // call FixInvalidFrecenciesForExcludedPlaces() to handle that scenario + // XXX this might be dog slow, further degrading delete perf. + rv = FixInvalidFrecenciesForExcludedPlaces(); + NS_ENSURE_SUCCESS(rv, rv); + + // XXX todo + // forcibly call the "on idle" timer here to do a little work + // but the rest will happen on idle. + } // Observers: Be sure to finish transaction before calling observers. Note also // that we always call the observers even though we aren't sure something @@ -2954,6 +3320,29 @@ nsNavHistory::RemovePagesFromHost(const nsACString& aHost, PRBool aEntireDomain) NS_LITERAL_CSTRING(")")); NS_ENSURE_SUCCESS(rv, rv); + // reset the frecency for the places we did not delete. Note, we don't + // reset the visit_count, as we use that in our "on idle" + // query to figure out which places to recalcuate frecency first. + if (!deletedPlaceIdsBookmarked.IsEmpty() || + !deletedPlaceIdsWithAnno.IsEmpty()) { + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "UPDATE moz_places SET frecency = -1 WHERE id IN (") + + deletedPlaceIdsBookmarked + + NS_LITERAL_CSTRING(") OR id IN (") + deletedPlaceIdsWithAnno + + NS_LITERAL_CSTRING(")")); + NS_ENSURE_SUCCESS(rv, rv); + + // the places could be livemark items, so setting the frecency to -1 + // would cause them show up in the url bar autocomplete + // call FixInvalidFrecenciesForExcludedPlaces() to handle that scenario + rv = FixInvalidFrecenciesForExcludedPlaces(); + NS_ENSURE_SUCCESS(rv, rv); + + // XXX todo + // forcibly call the "on idle" timer here to do a little work + // but the rest will happen on idle. + } + transaction.Commit(); // notify observers @@ -3089,7 +3478,8 @@ nsNavHistory::MarkPageAsTyped(nsIURI *aURI) return NS_OK; nsCAutoString uriString; - aURI->GetSpec(uriString); + nsresult rv = aURI->GetSpec(uriString); + NS_ENSURE_SUCCESS(rv, rv); // if URL is already in the typed queue, then we need to remove the old one PRInt64 unusedEventTime; @@ -3490,6 +3880,12 @@ nsNavHistory::OnIdle() rv = idleService->GetIdleTime(&idleTime); NS_ENSURE_SUCCESS(rv, rv); + // If we've been idle for more than mFrecencyUpdateIdleTime + // recalculate some frecency values. A value of zero indicates that + // frecency recalculation on idle is disabled. + if (mFrecencyUpdateIdleTime && idleTime > mFrecencyUpdateIdleTime) + (void)RecalculateFrecencies(); + // If we've been idle for more than EXPIRE_IDLE_TIME_IN_MSECS // keep the expiration engine chugging along. // Note: This is done prior to a possible vacuum, to optimize space reduction @@ -3602,7 +3998,7 @@ nsNavHistory::Observe(nsISupports *aSubject, const char *aTopic, PRInt32 oldDaysMin = mExpireDaysMin; PRInt32 oldDaysMax = mExpireDaysMax; PRInt32 oldVisits = mExpireSites; - LoadPrefs(); + LoadPrefs(PR_FALSE); if (oldDaysMin != mExpireDaysMin || oldDaysMax != mExpireDaysMax || oldVisits != mExpireSites) mExpire.OnExpirationChanged(); @@ -5119,7 +5515,8 @@ nsNavHistory::AddPageWithVisit(nsIURI *aURI, } PRInt64 pageID; - rv = InternalAddNewPage(aURI, aTitle, aHidden, aTyped, aVisitCount, &pageID); + // we don't want to calculate frecency here for each uri we import + rv = InternalAddNewPage(aURI, aTitle, aHidden, aTyped, aVisitCount, PR_FALSE, &pageID); NS_ENSURE_SUCCESS(rv, rv); if (aLastVisitDate != -1) { @@ -5594,3 +5991,347 @@ nsresult BindStatementURI(mozIStorageStatement* statement, PRInt32 index, NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } + +nsresult +nsNavHistory::UpdateFrecency(PRInt64 aPlaceId, PRBool aIsBookmarked) +{ + mozStorageStatementScoper statsScoper(mDBGetPlaceVisitStats); + nsresult rv = mDBGetPlaceVisitStats->BindInt64Parameter(0, aPlaceId); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasResults = PR_FALSE; + rv = mDBGetPlaceVisitStats->ExecuteStep(&hasResults); + NS_ENSURE_SUCCESS(rv, rv); + + if (!hasResults) { + NS_WARNING("attempting to update frecency for a bogus place"); + // before I added the check for itemType == TYPE_BOOKMARK + // I hit this with aPlaceId of 0 (on import) + return NS_OK; + } + + PRInt32 typed = 0; + rv = mDBGetPlaceVisitStats->GetInt32(0, &typed); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 hidden = 0; + rv = mDBGetPlaceVisitStats->GetInt32(1, &hidden); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 oldFrecency = 0; + rv = mDBGetPlaceVisitStats->GetInt32(2, &oldFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 visitCountForFrecency = 0; + + // because visit_count excludes visit with visit_type NOT IN(0,4) + // we can't use it for calculating frecency, so we must + // calculate it. + rv = CalculateVisitCount(aPlaceId, PR_TRUE /* for frecency */, + &visitCountForFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 newFrecency = 0; + rv = CalculateFrecencyInternal(aPlaceId, typed, visitCountForFrecency, + aIsBookmarked, &newFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + // save ourselves the UPDATE if the frecency hasn't changed + // One way this can happen is with livemarks. + // when we added the livemark, the frecency was 0. + // On refresh, when we remove and then add the livemark items, + // the frecency (for a given moz_places) will not have changed + // (if we've never visited that place). + if (newFrecency == oldFrecency) + return NS_OK; + + mozStorageStatementScoper updateScoper(mDBUpdateFrecencyAndHidden); + rv = mDBUpdateFrecencyAndHidden->BindInt64Parameter(0, aPlaceId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBUpdateFrecencyAndHidden->BindInt32Parameter(1, newFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + // if we calculated a non-zero frecency we should unhide this place + // so that previously hidden (non-livebookmark item) bookmarks + // will now appear in autocomplete + // if we calculated a zero frecency, we re-use the old hidden value. + rv = mDBUpdateFrecencyAndHidden->BindInt32Parameter(2, + newFrecency ? 0 /* not hidden */ : hidden); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBUpdateFrecencyAndHidden->Execute(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +nsNavHistory::CalculateFrecencyInternal(PRInt64 aPlaceId, PRInt32 aTyped, PRInt32 aVisitCount, PRBool aIsBookmarked, PRInt32 *aFrecency) +{ + PRTime normalizedNow = NormalizeTimeRelativeToday(GetNow()); + + float pointsForSampledVisits = 0.0; + + if (aPlaceId != -1) { + PRInt32 numSampledVisits = 0; + + mozStorageStatementScoper scoper(mDBVisitsForFrecency); + nsresult rv = mDBVisitsForFrecency->BindInt64Parameter(0, aPlaceId); + NS_ENSURE_SUCCESS(rv, rv); + + // mDBVisitsForFrecency is limited by the browser.frecency.numVisits pref + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(mDBVisitsForFrecency->ExecuteStep(&hasMore)) + && hasMore) { + numSampledVisits++; + + PRInt32 visitType = mDBVisitsForFrecency->AsInt32(1); + + PRInt32 bonus = 0; + + switch (visitType) { + case nsINavHistoryService::TRANSITION_EMBED: + bonus = mEmbedVisitBonus; + break; + case nsINavHistoryService::TRANSITION_LINK: + bonus = mLinkVisitBonus; + break; + case nsINavHistoryService::TRANSITION_TYPED: + bonus = mTypedVisitBonus; + break; + case nsINavHistoryService::TRANSITION_BOOKMARK: + bonus = mBookmarkVisitBonus; + break; + case nsINavHistoryService::TRANSITION_DOWNLOAD: + bonus = mDownloadVisitBonus; + break; + case nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT: + bonus = mPermRedirectVisitBonus; + break; + case nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY: + bonus = mTempRedirectVisitBonus; + break; + default: + // 0 == undefined (see bug #375777 for details) + if (visitType) + NS_WARNING("new transition but no weight for frecency"); + bonus = mDefaultVisitBonus; + break; + } + + // if bonus was zero, we can skip the work to determine the weight + if (bonus) { + PRTime visitDate = mDBVisitsForFrecency->AsInt64(0); + PRInt64 ageInDays = GetAgeInDays(normalizedNow, visitDate); + + PRInt32 weight = 0; + + if (ageInDays <= mFirstBucketCutoffInDays) + weight = mFirstBucketWeight; + else if (ageInDays <= mSecondBucketCutoffInDays) + weight = mSecondBucketWeight; + else if (ageInDays <= mThirdBucketCutoffInDays) + weight = mThirdBucketWeight; + else if (ageInDays <= mFourthBucketCutoffInDays) + weight = mFourthBucketWeight; + else + weight = mDefaultWeight; + + pointsForSampledVisits += weight * (bonus / 100.0); + } + } + + if (numSampledVisits) { + // fix for bug #412219 + if (!pointsForSampledVisits) { + // For URIs with zero points in the sampled recent visits + // but "browsing" type visits outside the sampling range, + // set frecency to -1, so that they're still shown in autocomplete. + PRInt32 trueVisitCount = 0; + rv = CalculateVisitCount(aPlaceId, PR_FALSE /* not for frecency */, + &trueVisitCount); + if (NS_SUCCEEDED(rv) && trueVisitCount) + *aFrecency = -1; + else + *aFrecency = 0; + } + else { + // Estimate frecency using the last few visits. + // Use NS_ceilf() so that we don't round down to 0, which + // would cause us to completely ignore the place during autocomplete. + *aFrecency = (PRInt32) NS_ceilf(aVisitCount * NS_ceilf(pointsForSampledVisits) / numSampledVisits); + } + +#ifdef DEBUG_FRECENCY + printf("CalculateFrecency() for place %lld: %d = %d * %f / %d\n", aPlaceId, *aFrecency, aVisitCount, pointsForSampledVisits, numSampledVisits); +#endif + + return NS_OK; + } + } + + // XXX the code below works well for guessing the frecency on import, and we'll correct later once we have + // visits. + // what if we don't have visits and we never visit? we could end up with a really high value + // that keeps coming up in ac results? only do this on import? something to figure out. + PRInt32 bonus = 0; + + // not the same logic above, as a single visit could not be both + // a bookmark visit and a typed visit. but when estimating a frecency + // for a place that doesn't have any visits, this will make it so + // something bookmarked and typed will have a higher frecency than + // something just typed or just bookmarked. + if (aIsBookmarked) + bonus += mUnvisitedBookmarkBonus; + if (aTyped) + bonus += mUnvisitedTypedBonus; + + // assume "now" as our ageInDays, so use the first bucket. + // note, when we recalculate "old frecencies" (see mDBOldFrecencies) + // this frecency value could be off by an order of + // (mFirstBucketWeight / mDefaultBucketWeight) + pointsForSampledVisits = mFirstBucketWeight * (bonus / (float)100.0); + + // for a unvisited bookmark, produce a non-zero frecency + // so that unvisited bookmarks show up in URL bar autocomplete + if (!aVisitCount && aIsBookmarked) + aVisitCount = 1; + + // use NS_ceilf() so that we don't round down to 0, which + // would cause us to completely ignore the place during autocomplete + *aFrecency = (PRInt32) NS_ceilf(aVisitCount * NS_ceilf(pointsForSampledVisits)); +#ifdef DEBUG_FRECENCY + printf("CalculateFrecency() for unvisited: frecency %d = %f points (b: %d, t: %d) * visit count %d\n", *aFrecency, pointsForSampledVisits, aIsBookmarked, aTyped, aVisitCount); +#endif + return NS_OK; +} + +nsresult +nsNavHistory::CalculateFrecency(PRInt64 aPlaceId, PRInt32 aTyped, PRInt32 aVisitCount, nsCAutoString &aURL, PRInt32 *aFrecency) +{ + *aFrecency = 0; + + nsresult rv; + + nsCOMPtr lms = + do_GetService(NS_LIVEMARKSERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool isBookmark = PR_FALSE; + + // determine if the place is a (non-livemark item) bookmark and prevent + // place: queries from showing up in the URL bar autocomplete results + if (!IsQueryURI(aURL) && aPlaceId != -1) { + mozStorageStatementScoper scope(mDBGetBookmarkParentsForPlace); + + rv = mDBGetBookmarkParentsForPlace->BindInt64Parameter(0, aPlaceId); + NS_ENSURE_SUCCESS(rv, rv); + + // this query can return multiple parent folders because + // it is possible for the user to bookmark something that + // is also a livemark item + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(mDBGetBookmarkParentsForPlace->ExecuteStep(&hasMore)) + && hasMore) { + PRInt64 folderId; + rv = mDBGetBookmarkParentsForPlace->GetInt64(0, &folderId); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool parentIsLivemark; + rv = lms->IsLivemark(folderId, &parentIsLivemark); + NS_ENSURE_SUCCESS(rv, rv); + + // we found one parent that is not a livemark feed, so we can stop + if (!parentIsLivemark) { + isBookmark = PR_TRUE; + break; + } + } + } + + rv = CalculateFrecencyInternal(aPlaceId, aTyped, aVisitCount, + isBookmark, aFrecency); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + +nsresult +nsNavHistory::RecalculateFrecencies() +{ + mozStorageTransaction transaction(mDBConn, PR_TRUE); + + nsresult rv = RecalculateFrecenciesInternal(mDBInvalidFrecencies, -1); + NS_ENSURE_SUCCESS(rv, rv); + + // if the last visit date was "recent" (in the top bucket) + // don't bother recalculating as it was recalculated recently + // and we are looking for "older" places. + PRTime startOfFirstBucket = GetNow() - + (USECS_PER_DAY * (mFirstBucketCutoffInDays + 1)); + + rv = RecalculateFrecenciesInternal(mDBOldFrecencies, startOfFirstBucket); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + +nsresult +nsNavHistory::RecalculateFrecenciesInternal(mozIStorageStatement *aStatement, PRInt64 aBindParameter) +{ + nsresult rv; + + mozStorageStatementScoper scoper(aStatement); + if (aBindParameter != -1) { + rv = aStatement->BindInt64Parameter(0, aBindParameter); + NS_ENSURE_SUCCESS(rv, rv); + } + + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(aStatement->ExecuteStep(&hasMore)) && hasMore) { + PRInt64 placeId = aStatement->AsInt64(0); + // for frecency, we don't use visit_count, aStatement->AsInt32(1) + PRInt32 hidden = aStatement->AsInt32(2); + PRInt32 typed = aStatement->AsInt32(3); + PRInt32 oldFrecency = aStatement->AsInt32(4); + + nsCAutoString url; + aStatement->GetUTF8String(5, url); + + PRInt32 newFrecency = 0; + PRInt32 visitCountForFrecency = 0; + + // because visit_count excludes visit with visit_type NOT IN(0,4) + // we can't use it for calculating frecency so we must calculate it. + rv = CalculateVisitCount(placeId, PR_TRUE /* for frecency */, + &visitCountForFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + rv = CalculateFrecency(placeId, typed, visitCountForFrecency, + url, &newFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + // save ourselves the UPDATE if the frecency hasn't changed + if (newFrecency == oldFrecency) + continue; + + mozStorageStatementScoper updateScoper(mDBUpdateFrecencyAndHidden); + rv = mDBUpdateFrecencyAndHidden->BindInt64Parameter(0, placeId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBUpdateFrecencyAndHidden->BindInt32Parameter(1, newFrecency); + NS_ENSURE_SUCCESS(rv, rv); + + // if we calculated a non-zero frecency we should unhide this place + // so that previously hidden (non-livebookmark items) bookmarks + // will now appear in autocomplete. if we calculated a zero frecency, + // we re-use the old hidden value. + rv = mDBUpdateFrecencyAndHidden->BindInt32Parameter(2, + newFrecency ? 0 /* not hidden */ : hidden); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBUpdateFrecencyAndHidden->Execute(); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} diff --git a/toolkit/components/places/src/nsNavHistory.h b/toolkit/components/places/src/nsNavHistory.h index 4e69995e149b..f53ebb9b5507 100644 --- a/toolkit/components/places/src/nsNavHistory.h +++ b/toolkit/components/places/src/nsNavHistory.h @@ -48,9 +48,11 @@ #include "nsCOMPtr.h" #include "nsDataHashtable.h" #include "nsINavHistoryService.h" +#ifdef MOZ_XUL #include "nsIAutoCompleteSearch.h" #include "nsIAutoCompleteResult.h" #include "nsIAutoCompleteSimpleResult.h" +#endif #include "nsIBrowserHistory.h" #include "nsICollation.h" #include "nsIDateTimeFormat.h" @@ -64,8 +66,10 @@ #include "nsServiceManagerUtils.h" #include "nsIStringBundle.h" #include "nsITimer.h" +#ifdef MOZ_XUL #include "nsITreeSelection.h" #include "nsITreeView.h" +#endif #include "nsString.h" #include "nsVoidArray.h" #include "nsWeakReference.h" @@ -109,9 +113,11 @@ class nsNavHistory : public nsSupportsWeakReference, public nsIObserver, public nsIBrowserHistory, public nsIGlobalHistory3, - public nsIDownloadHistory, - public nsIAutoCompleteSearch, + public nsIDownloadHistory +#ifdef MOZ_XUL + , public nsIAutoCompleteSearch, public nsIAutoCompleteSimpleResultListener +#endif { friend class AutoCompleteIntermediateResultSet; friend class AutoCompleteResultComparator; @@ -126,8 +132,10 @@ public: NS_DECL_NSIDOWNLOADHISTORY NS_DECL_NSIBROWSERHISTORY NS_DECL_NSIOBSERVER +#ifdef MOZ_XUL NS_DECL_NSIAUTOCOMPLETESEARCH NS_DECL_NSIAUTOCOMPLETESIMPLERESULTLISTENER +#endif nsresult Init(); @@ -177,6 +185,12 @@ public: nsresult GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID, PRBool aAutoCreate); + nsresult CalculateVisitCount(PRInt64 aPlaceId, PRBool aForFrecency, PRInt32 *aVisitCount); + + nsresult UpdateFrecency(PRInt64 aPageID, PRBool isBookmark); + + nsresult FixInvalidFrecenciesForExcludedPlaces(); + /** * Returns a pointer to the storage connection used by history. This * connection object is also used by the annotation service and bookmarks, so @@ -382,14 +396,28 @@ protected: nsCOMPtr mDBUrlToUrlResult; // kGetInfoIndex_* results nsCOMPtr mDBBookmarkToUrlResult; // kGetInfoIndex_* results + nsresult RecalculateFrecencies(); + nsresult RecalculateFrecenciesInternal(mozIStorageStatement *aStatement, PRInt64 aBindParameter); + + nsresult CalculateFrecency(PRInt64 aPageID, PRInt32 aTyped, PRInt32 aVisitCount, nsCAutoString &aURL, PRInt32 *aFrecency); + nsresult CalculateFrecencyInternal(PRInt64 aPageID, PRInt32 aTyped, PRInt32 aVisitCount, PRBool aIsBookmarked, PRInt32 *aFrecency); + nsCOMPtr mDBVisitsForFrecency; + nsCOMPtr mDBInvalidFrecencies; + nsCOMPtr mDBOldFrecencies; + nsCOMPtr mDBUpdateFrecencyAndHidden; + nsCOMPtr mDBGetPlaceVisitStats; + nsCOMPtr mDBGetBookmarkParentsForPlace; + nsCOMPtr mDBVisitCountForFrecency; + nsCOMPtr mDBTrueVisitCount; + nsresult InitDBFile(PRBool aForceInit); nsresult BackupDBFile(); - nsresult InitDB(PRBool *aDoImport); + nsresult InitDB(PRInt16 *aMadeChanges); nsresult InitStatements(); nsresult ForceMigrateBookmarksDB(mozIStorageConnection *aDBConn); nsresult MigrateV3Up(mozIStorageConnection *aDBConn); nsresult MigrateV6Up(mozIStorageConnection *aDBConn); - nsresult EnsureCurrentSchema(mozIStorageConnection* aDBConn); + nsresult EnsureCurrentSchema(mozIStorageConnection* aDBConn, PRBool *aMadeChanges); nsresult CleanUpOnQuit(); #ifdef IN_MEMORY_LINKS @@ -410,14 +438,15 @@ protected: PRInt64* aSessionID, PRInt64* aRedirectBookmark); nsresult InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle, PRBool aHidden, PRBool aTyped, - PRInt32 aVisitCount, PRInt64* aPageID); + PRInt32 aVisitCount, PRBool aCalculateFrecency, + PRInt64* aPageID); nsresult InternalAddVisit(PRInt64 aPageID, PRInt64 aReferringVisit, PRInt64 aSessionID, PRTime aTime, PRInt32 aTransitionType, PRInt64* aVisitID); PRBool FindLastVisit(nsIURI* aURI, PRInt64* aVisitID, PRInt64* aSessionID); PRBool IsURIStringVisited(const nsACString& url); - nsresult LoadPrefs(); + nsresult LoadPrefs(PRBool aInitializing); // Current time optimization PRTime mLastNow; @@ -579,27 +608,32 @@ protected: static const PRInt32 kAutoCompleteIndex_FaviconURL; static const PRInt32 kAutoCompleteIndex_ItemId; static const PRInt32 kAutoCompleteIndex_ParentId; + static const PRInt32 kAutoCompleteIndex_BookmarkTitle; nsCOMPtr mDBAutoCompleteQuery; // kAutoCompleteIndex_* results nsCOMPtr mDBTagAutoCompleteQuery; // kAutoCompleteIndex_* results nsresult InitAutoComplete(); nsresult CreateAutoCompleteQueries(); PRBool mAutoCompleteOnlyTyped; + PRInt32 mAutoCompleteMaxResults; nsCOMPtr mAutoCompleteTimer; nsString mCurrentSearchString; + nsString mCurrentSearchStringEscaped; + +#ifdef MOZ_XUL nsCOMPtr mCurrentListener; nsCOMPtr mCurrentResult; +#endif + nsDataHashtable mCurrentResultURLs; - PRTime mCurrentChunkEndTime; - PRTime mCurrentOldestVisit; - PRBool mFirstChunk; + PRInt32 mCurrentChunkOffset; nsDataHashtable mLivemarkFeedItemIds; nsDataHashtable mLivemarkFeedURIs; nsresult AutoCompleteTypedSearch(); - nsresult AutoCompleteFullHistorySearch(); + nsresult AutoCompleteFullHistorySearch(PRBool* aHasMoreResults); nsresult AutoCompleteTagsSearch(); nsresult PerformAutoComplete(); @@ -611,12 +645,36 @@ protected: PRInt32 mExpireDaysMax; PRInt32 mExpireSites; + // frecency prefs + PRInt32 mNumVisitsForFrecency; + PRInt32 mFrecencyUpdateIdleTime; + PRInt32 mFirstBucketCutoffInDays; + PRInt32 mSecondBucketCutoffInDays; + PRInt32 mThirdBucketCutoffInDays; + PRInt32 mFourthBucketCutoffInDays; + PRInt32 mFirstBucketWeight; + PRInt32 mSecondBucketWeight; + PRInt32 mThirdBucketWeight; + PRInt32 mFourthBucketWeight; + PRInt32 mDefaultWeight; + PRInt32 mEmbedVisitBonus; + PRInt32 mLinkVisitBonus; + PRInt32 mTypedVisitBonus; + PRInt32 mBookmarkVisitBonus; + PRInt32 mDownloadVisitBonus; + PRInt32 mPermRedirectVisitBonus; + PRInt32 mTempRedirectVisitBonus; + PRInt32 mDefaultVisitBonus; + PRInt32 mUnvisitedBookmarkBonus; + PRInt32 mUnvisitedTypedBonus; + // in nsNavHistoryQuery.cpp nsresult TokensToQueries(const nsTArray& aTokens, nsCOMArray* aQueries, nsNavHistoryQueryOptions* aOptions); nsCOMPtr mIdleTimer; + nsresult InitializeIdleTimer(); static void IdleTimerCallback(nsITimer* aTimer, void* aClosure); nsresult OnIdle(); diff --git a/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp b/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp index 1e6e0656b5a7..7d29ee127f9e 100644 --- a/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp +++ b/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp @@ -23,6 +23,8 @@ * Brett Wilson * Joe Hewitt * Blake Ross + * Seth Spitzer + * 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 @@ -42,11 +44,18 @@ /** * Autocomplete algorithm: * - * The current algorithm searches history from now backwards to the oldest - * visit in chunks of time (AUTOCOMPLETE_SEARCH_CHUNK). We currently - * do SQL LIKE searches of the search term in the url and title - * within in each chunk of time. the results are ordered by visit_count - * (and then visit_date), giving us poor man's "frecency". + * Searches moz_places by frecency (in descending order) + * in chunks (AUTOCOMPLETE_SEARCH_CHUNK_SIZE). We currently + * do SQL LIKE searches of the search term in the place title, place url + * and bookmark titles (since a "place" can have multiple bookmarks) + * within in each chunk. The results are ordered by frecency. + * Note, we exclude places with no frecency (0) because + * frecency = 0 means "don't show this in autocomplete". place: queries should + * have that, as should unvisited children of livemark feeds (that aren't + * bookmarked elsewhere). + * + * But places with frecency (-1) are included, as that means that these items + * have not had their frecency calculated yet (will happen on idle). */ #include "nsNavHistory.h" @@ -63,12 +72,14 @@ #include "nsUnicharUtils.h" #include "nsNavBookmarks.h" #include "nsPrintfCString.h" +#include "nsILivemarkService.h" #define NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID \ "@mozilla.org/autocomplete/simple-result;1" // This is the maximum results we'll return for a "typed" search // This happens in response to clicking the down arrow next to the URL. +// XXX todo, check if doing rich autocomplete, and if so, limit to the max results? #define AUTOCOMPLETE_MAX_PER_TYPED 100 // nsNavHistory::InitAutoComplete @@ -100,33 +111,48 @@ nsresult nsNavHistory::CreateAutoCompleteQueries() { nsCString sql = NS_LITERAL_CSTRING( - "SELECT h.url, h.title, f.url, b.id, b.parent " + "SELECT h.url, h.title, f.url, b.id, b.parent, b.title " "FROM moz_places h " - "JOIN moz_historyvisits v ON h.id = v.place_id " "LEFT OUTER JOIN moz_bookmarks b ON b.fk = h.id " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " - "WHERE v.visit_date >= ?1 AND v.visit_date <= ?2 AND h.hidden <> 1 AND " - " v.visit_type NOT IN(0,4) AND "); + "WHERE h.frecency <> 0 AND "); if (mAutoCompleteOnlyTyped) sql += NS_LITERAL_CSTRING("h.typed = 1 AND "); + // NOTE: + // after migration or clear all private data, we might end up with + // a lot of places with frecency = -1 (until idle) + // + // XXX bug 412736 + // in the case of a frecency tie, break it with h.typed and h.visit_count + // which is better than nothing. but this is slow, so not doing it yet. sql += NS_LITERAL_CSTRING( - "(h.title LIKE ?3 ESCAPE '/' OR h.url LIKE ?3 ESCAPE '/') " - "GROUP BY h.id ORDER BY h.typed DESC, h.visit_count DESC, MAX(v.visit_date) DESC;"); + "(b.title LIKE ?1 ESCAPE '/' OR " + "h.title LIKE ?1 ESCAPE '/' OR " + "h.url LIKE ?1 ESCAPE '/') " + "ORDER BY h.frecency DESC LIMIT ?2 OFFSET ?3"); - nsresult rv = mDBConn->CreateStatement(sql, getter_AddRefs(mDBAutoCompleteQuery)); + nsresult rv = mDBConn->CreateStatement(sql, + getter_AddRefs(mDBAutoCompleteQuery)); NS_ENSURE_SUCCESS(rv, rv); + // NOTE: + // after migration or clear all private data, we might end up with + // a lot of places with frecency = -1 (until idle) + // + // XXX bug 412736 + // in the case of a frecency tie, break it with h.typed and h.visit_count + // which is better than nothing. but this is slow, so not doing it yet. sql = NS_LITERAL_CSTRING( "SELECT h.url, h.title, f.url, b.id, b.parent " "FROM moz_places h " "JOIN moz_bookmarks b ON b.fk = h.id " - "LEFT OUTER JOIN moz_historyvisits v ON h.id = v.place_id " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " - "WHERE " + "WHERE h.frecency <> 0 AND " "(b.parent in (SELECT t.id FROM moz_bookmarks t WHERE t.parent = ?1 AND LOWER(t.title) = LOWER(?2))) " - "GROUP BY h.id ORDER BY h.visit_count DESC, MAX(v.visit_date) DESC;"); + "ORDER BY h.frecency DESC"); + rv = mDBConn->CreateStatement(sql, getter_AddRefs(mDBTagAutoCompleteQuery)); NS_ENSURE_SUCCESS(rv, rv); @@ -152,25 +178,16 @@ nsNavHistory::StartAutoCompleteTimer(PRUint32 aMilliseconds) return NS_OK; } -static const PRInt64 USECS_PER_DAY = LL_INIT(20, 500654080); - -// search in day chunks. too big, and the UI will be unresponsive +// number of places to search per chunk +// too big, and the UI will be unresponsive // as we will be off searching the database. -// too short, and because of AUTOCOMPLETE_SEARCH_TIMEOUT +// too small, and because of AUTOCOMPLETE_SEARCH_TIMEOUT // results won't come back in fast enough to feel snappy. -// because we sort within chunks by visit_count (then visit_date) -// choose 4 days so that Friday's searches are in the first chunk -// and those will affect Monday's results -#define AUTOCOMPLETE_SEARCH_CHUNK (USECS_PER_DAY * 4) +#define AUTOCOMPLETE_SEARCH_CHUNK_SIZE 100 // wait this many milliseconds between searches -// too short, and the UI will be unresponsive -// as we will be off searching the database. -// too big, and results won't come back in fast enough to feel snappy. #define AUTOCOMPLETE_SEARCH_TIMEOUT 100 -#define LMANNO_FEEDURI "livemark/feedURI" - // nsNavHistory::AutoCompleteTimerCallback void // static @@ -196,15 +213,14 @@ nsNavHistory::PerformAutoComplete() rv = AutoCompleteTypedSearch(); else { // only search tags on the first chunk, - // but before we search history, as we want tagged + // but before we search places, as we want tagged // items to show up first. - if (mFirstChunk) { + if (!mCurrentChunkOffset) { rv = AutoCompleteTagsSearch(); NS_ENSURE_SUCCESS(rv, rv); } - rv = AutoCompleteFullHistorySearch(); - moreChunksToSearch = (mCurrentChunkEndTime >= mCurrentOldestVisit); + rv = AutoCompleteFullHistorySearch(&moreChunksToSearch); } NS_ENSURE_SUCCESS(rv, rv); @@ -229,11 +245,10 @@ nsNavHistory::PerformAutoComplete() mCurrentListener->OnSearchResult(this, mCurrentResult); - // if we're not done searching, adjust our end time and - // search the next earlier chunk of time + // if we're not done searching, adjust our current offset + // and search the next chunk if (moreChunksToSearch) { - mFirstChunk = PR_FALSE; - mCurrentChunkEndTime -= AUTOCOMPLETE_SEARCH_CHUNK; + mCurrentChunkOffset += AUTOCOMPLETE_SEARCH_CHUNK_SIZE; rv = StartAutoCompleteTimer(AUTOCOMPLETE_SEARCH_TIMEOUT); NS_ENSURE_SUCCESS(rv, rv); } else { @@ -258,158 +273,50 @@ nsNavHistory::StartSearch(const nsAString & aSearchString, nsIAutoCompleteResult *aPreviousResult, nsIAutoCompleteObserver *aListener) { + // We don't use aPreviousResult to get some matches from previous results in + // order to make sure ordering of results are consistent between reusing and + // not reusing results, see bug #412730 for details + NS_ENSURE_ARG_POINTER(aListener); mCurrentSearchString = aSearchString; // remove whitespace, see bug #392141 for details mCurrentSearchString.Trim(" \r\n\t\b"); + + nsresult rv = mDBAutoCompleteQuery->EscapeStringForLIKE(mCurrentSearchString, PRUnichar('/'), mCurrentSearchStringEscaped); + NS_ENSURE_SUCCESS(rv, rv); + mCurrentListener = aListener; - nsresult rv; - - // determine if we can start by searching through the previous search results. - // if we can't, we need to reset mCurrentChunkEndTime and mCurrentOldestVisit. - // if we can, we will search through our previous search results and then resume - // searching using the previous mCurrentChunkEndTime and mCurrentOldestVisit values. - PRBool searchPrevious = PR_FALSE; - if (aPreviousResult) { - nsAutoString prevSearchString; - aPreviousResult->GetSearchString(prevSearchString); - - // if search string begins with the previous search string, it's a go. - // but don't search previous results if the previous search string was empty - // or if the current search string is empty. (an empty search string is a "typed only" - // search from when clicking on the drop down to the right of the url bar.) - searchPrevious = !prevSearchString.IsEmpty() && Substring(mCurrentSearchString, 0, - prevSearchString.Length()).Equals(prevSearchString); - } mCurrentResult = do_CreateInstance(NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); + mCurrentChunkOffset = 0; mCurrentResultURLs.Clear(); + mLivemarkFeedItemIds.Clear(); + mLivemarkFeedURIs.Clear(); - // if we are searching through our previous results, - // we don't need to regenerate these hash tables - if (!searchPrevious) { - mLivemarkFeedItemIds.Clear(); - mLivemarkFeedURIs.Clear(); + // find all the items that have the "livemark/feedURI" annotation + // and save off their item ids and URIs. when doing autocomplete, + // if a result's parent item id matches a saved item id, the result + // it is not really a bookmark, but a rss feed item. + // if a results URI matches a saved URI, the result is a bookmark, + // so we should show the star. + mozStorageStatementScoper scope(mFoldersWithAnnotationQuery); - // find all the items that have the "livemark/feedURI" annotation - // and save off their item ids and URIs. when doing autocomplete, - // if a result's parent item id matches a saved item id, the result - // it is not really a bookmark, but a rss feed item. - // if a results URI matches a saved URI, the result is a bookmark, - // so we should show the star. - mozStorageStatementScoper scope(mFoldersWithAnnotationQuery); + rv = mFoldersWithAnnotationQuery->BindUTF8StringParameter(0, NS_LITERAL_CSTRING(LMANNO_FEEDURI)); + NS_ENSURE_SUCCESS(rv, rv); - rv = mFoldersWithAnnotationQuery->BindUTF8StringParameter(0, NS_LITERAL_CSTRING(LMANNO_FEEDURI)); + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(mFoldersWithAnnotationQuery->ExecuteStep(&hasMore)) && hasMore) { + PRInt64 itemId = 0; + rv = mFoldersWithAnnotationQuery->GetInt64(0, &itemId); NS_ENSURE_SUCCESS(rv, rv); - - PRBool hasMore = PR_FALSE; - while (NS_SUCCEEDED(mFoldersWithAnnotationQuery->ExecuteStep(&hasMore)) && hasMore) { - PRInt64 itemId = 0; - rv = mFoldersWithAnnotationQuery->GetInt64(0, &itemId); - NS_ENSURE_SUCCESS(rv, rv); - mLivemarkFeedItemIds.Put(itemId, PR_TRUE); - nsAutoString feedURI; - // no need to worry about duplicates. - rv = mFoldersWithAnnotationQuery->GetString(1, feedURI); - NS_ENSURE_SUCCESS(rv, rv); - mLivemarkFeedURIs.Put(feedURI, PR_TRUE); - } - } - - // Search through the previous result - if (searchPrevious) { - // when searching our previous results - // we need to first re-search tags. - // if our previous search was for "foo", we would have shown - // items tagged with "foo". if our current search is "food" - // we need to re-search for tags matching "food" first. - // then, when processing results we have to remove any previous tag matches - rv = AutoCompleteTagsSearch(); + mLivemarkFeedItemIds.Put(itemId, PR_TRUE); + nsAutoString feedURI; + // no need to worry about duplicates. + rv = mFoldersWithAnnotationQuery->GetString(1, feedURI); NS_ENSURE_SUCCESS(rv, rv); - - PRUint32 matchCount; - aPreviousResult->GetMatchCount(&matchCount); - for (PRUint32 i = 0; i < matchCount; i++) { - // if the previous result item was a tagged item, and it matches - // the current search term (due to url or title) don't include it. - // find it "naturally" with a history or bookmark search. - // - // note, if the previous result item is tagged with the current search term, - // our call to AutoCompleteTagsSearch() above will find it. - nsAutoString style; - aPreviousResult->GetStyleAt(i, style); - if (!style.Equals(NS_LITERAL_STRING("tag"))) { - nsAutoString url; - aPreviousResult->GetValueAt(i, url); - - // make sure the url isn't already listed, as a tag result - PRBool dummy; - if (!mCurrentResultURLs.Get(url, &dummy)) { - nsAutoString title; - aPreviousResult->GetCommentAt(i, title); - - // assuming that people learn to use the urlbar for titles (and not urls) - // we should search in titles first, to potentially save the second call to - // CaseInsensitiveFindInReadable() for the url - PRBool isMatch = CaseInsensitiveFindInReadable(mCurrentSearchString, title); - if (!isMatch) - isMatch = CaseInsensitiveFindInReadable(mCurrentSearchString, url); - - if (isMatch) { - nsAutoString image; - aPreviousResult->GetImageAt(i, image); - - mCurrentResultURLs.Put(url, PR_TRUE); - - rv = mCurrentResult->AppendMatch(url, title, image, style); - NS_ENSURE_SUCCESS(rv, rv); - } - } - } - } - // if we found some results, announce them now instead of waiting - // to do the first db search. - PRUint32 count; - mCurrentResult->GetMatchCount(&count); - - if (count > 0) { - // when searching previous autocomplete results, - // if we found any matches, tell the front end immediately, - // instead of waiting until our first query returns. - mCurrentResult->SetSearchResult(nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING); - mCurrentResult->SetDefaultIndex(0); - rv = mCurrentResult->SetListener(this); - NS_ENSURE_SUCCESS(rv, rv); - mCurrentListener->OnSearchResult(this, mCurrentResult); - } - } - else if (!mCurrentSearchString.IsEmpty()) { - // reset to mCurrentChunkEndTime - mCurrentChunkEndTime = PR_Now(); - mCurrentOldestVisit = 0; - mFirstChunk = PR_TRUE; - - // determine our earliest visit - nsCOMPtr dbSelectStatement; - rv = mDBConn->CreateStatement( - NS_LITERAL_CSTRING("SELECT MIN(visit_date) id FROM moz_historyvisits WHERE visit_type NOT IN(0,4)"), - getter_AddRefs(dbSelectStatement)); - NS_ENSURE_SUCCESS(rv, rv); - PRBool hasMinVisit; - rv = dbSelectStatement->ExecuteStep(&hasMinVisit); - NS_ENSURE_SUCCESS(rv, rv); - - if (hasMinVisit) { - rv = dbSelectStatement->GetInt64(0, &mCurrentOldestVisit); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (!mCurrentOldestVisit) { - // if we have no visits, use a reasonable value - mCurrentOldestVisit = PR_Now() - USECS_PER_DAY; - } + mLivemarkFeedURIs.Put(feedURI, PR_TRUE); } // fire right away, we already waited to start searching @@ -435,32 +342,43 @@ nsNavHistory::StopSearch() // nsNavHistory::AutoCompleteTypedSearch // // Called when there is no search string. This happens when you press -// down arrow from the URL bar: the most recent things you typed are listed. +// down arrow from the URL bar: the most "frecent" things you typed are listed. // -// Ordering here is simpler because there are no boosts for typing, and there -// is no URL information to use. The ordering just comes out of the DB by -// visit count (primary) and time since last visited (secondary). nsresult nsNavHistory::AutoCompleteTypedSearch() { nsCOMPtr dbSelectStatement; + // NOTE: + // after migration or clear all private data, we might end up with + // a lot of places with frecency = -1 (until idle) + // + // XXX bug 412736 + // in the case of a frecency tie, break it with h.typed and h.visit_count + // which is better than nothing. but this is slow, so not doing it yet. + // + // GROUP BY h.id to prevent duplicates. For mDBAutoCompleteQuery, + // we use the mCurrentResultURLs hash to accomplish this. + // + // NOTE: because we are grouping by h.id, b.id and b.parent + // get collapsed, so if something is both a livemark and a bookmark + // we might not show it as a "star" if the parentId we return is + // the one for the livemark item, and not the bookmark item. + // XXX bug 412734 nsCString sql = NS_LITERAL_CSTRING( "SELECT h.url, h.title, f.url, b.id, b.parent " "FROM moz_places h " "LEFT OUTER JOIN moz_bookmarks b ON b.fk = h.id " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " - "JOIN moz_historyvisits v ON h.id = v.place_id WHERE (h.id IN " - "(SELECT DISTINCT h.id from moz_historyvisits v, moz_places h WHERE " - "v.place_id = h.id AND h.typed = 1 AND v.visit_type NOT IN(0,4) " - "ORDER BY v.visit_date DESC LIMIT "); + "WHERE h.frecency <> 0 AND h.typed = 1 " + "GROUP BY h.id ORDER BY h.frecency DESC LIMIT "); sql.AppendInt(AUTOCOMPLETE_MAX_PER_TYPED); - sql += NS_LITERAL_CSTRING(")) GROUP BY h.id ORDER BY MAX(v.visit_date) DESC"); nsFaviconService* faviconService = nsFaviconService::GetFaviconService(); NS_ENSURE_TRUE(faviconService, NS_ERROR_OUT_OF_MEMORY); - nsresult rv = mDBConn->CreateStatement(sql, getter_AddRefs(dbSelectStatement)); + nsresult rv = mDBConn->CreateStatement(sql, + getter_AddRefs(dbSelectStatement)); NS_ENSURE_SUCCESS(rv, rv); PRBool hasMore = PR_FALSE; @@ -472,12 +390,13 @@ nsresult nsNavHistory::AutoCompleteTypedSearch() PRInt64 itemId = 0; dbSelectStatement->GetInt64(kAutoCompleteIndex_ItemId, &itemId); PRInt64 parentId = 0; - dbSelectStatement->GetInt64(kAutoCompleteIndex_ParentId, &parentId); + if (itemId) + dbSelectStatement->GetInt64(kAutoCompleteIndex_ParentId, &parentId); PRBool dummy; // don't show rss feed items as bookmarked, // but do show rss feed URIs as bookmarked. - PRBool isBookmark = (itemId != 0 && + PRBool isBookmark = (itemId && !mLivemarkFeedItemIds.Get(parentId, &dummy)) || mLivemarkFeedURIs.Get(entryURL, &dummy); @@ -543,9 +462,8 @@ nsNavHistory::AutoCompleteTagsSearch() "SELECT h.url, h.title, f.url, b.id, b.parent " "FROM moz_places h " "JOIN moz_bookmarks b ON b.fk = h.id " - "LEFT OUTER JOIN moz_historyvisits v ON h.id = v.place_id " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " - "WHERE " + "WHERE h.frecency <> 0 AND " "(b.parent in " " (SELECT t.id FROM moz_bookmarks t WHERE t.parent = ?1 AND ("); @@ -562,7 +480,7 @@ nsNavHistory::AutoCompleteTagsSearch() } tagQuery += NS_LITERAL_CSTRING("))) " - "GROUP BY h.id ORDER BY h.visit_count DESC, MAX(v.visit_date) DESC;"); + "GROUP BY h.id ORDER BY h.frecency DESC"); rv = mDBConn->CreateStatement(tagQuery, getter_AddRefs(tagAutoCompleteQuery)); NS_ENSURE_SUCCESS(rv, rv); @@ -586,24 +504,34 @@ nsNavHistory::AutoCompleteTagsSearch() // Determine the result of the search while (NS_SUCCEEDED(tagAutoCompleteQuery->ExecuteStep(&hasMore)) && hasMore) { - nsAutoString entryURL, entryTitle, entryFavicon; + nsAutoString entryURL; rv = tagAutoCompleteQuery->GetString(kAutoCompleteIndex_URL, entryURL); NS_ENSURE_SUCCESS(rv, rv); - rv = tagAutoCompleteQuery->GetString(kAutoCompleteIndex_Title, entryTitle); - NS_ENSURE_SUCCESS(rv, rv); - rv = tagAutoCompleteQuery->GetString(kAutoCompleteIndex_FaviconURL, entryFavicon); - NS_ENSURE_SUCCESS(rv, rv); - PRInt64 itemId = 0; - rv = tagAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ItemId, &itemId); - NS_ENSURE_SUCCESS(rv, rv); - PRInt64 parentId = 0; - rv = tagAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ParentId, &parentId); - NS_ENSURE_SUCCESS(rv, rv); PRBool dummy; // prevent duplicates. this can happen when chunking as we - // may have already seen this URL from an earlier chunk of time + // may have already seen this URL. + // NOTE: because we use mCurrentResultURLs to remove duplicates, + // the first url wins. + // so we might not show it as a "star" if the parentId we get first is + // the one for the livemark item, and not the bookmark item, + // we may not show the "star" even though we should. + // XXX bug 412734 if (!mCurrentResultURLs.Get(entryURL, &dummy)) { + nsAutoString entryTitle, entryFavicon; + rv = tagAutoCompleteQuery->GetString(kAutoCompleteIndex_Title, entryTitle); + NS_ENSURE_SUCCESS(rv, rv); + rv = tagAutoCompleteQuery->GetString(kAutoCompleteIndex_FaviconURL, entryFavicon); + NS_ENSURE_SUCCESS(rv, rv); + PRInt64 itemId = 0; + rv = tagAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ItemId, &itemId); + NS_ENSURE_SUCCESS(rv, rv); + PRInt64 parentId = 0; + if (itemId) { + rv = tagAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ParentId, &parentId); + NS_ENSURE_SUCCESS(rv, rv); + } + // new item, append to our results and put it in our hash table. nsCAutoString faviconSpec; faviconService->GetFaviconSpecForIconString( @@ -621,28 +549,26 @@ nsNavHistory::AutoCompleteTagsSearch() // nsNavHistory::AutoCompleteFullHistorySearch // -// Search history for visits that have a url or title that contains mCurrentSearchString -// and are within our current chunk of time: -// between (mCurrentChunkEndTime - AUTOCOMPLETE_SEARCH_CHUNK) and (mCurrentChunkEndTime) +// Search for places that have a title, url, +// or bookmark title(s) that contains mCurrentSearchString +// and are within our current chunk of "frecency". +// +// @param aHasMoreResults is false if the query found no matching items // nsresult -nsNavHistory::AutoCompleteFullHistorySearch() +nsNavHistory::AutoCompleteFullHistorySearch(PRBool* aHasMoreResults) { mozStorageStatementScoper scope(mDBAutoCompleteQuery); - nsresult rv = mDBAutoCompleteQuery->BindInt64Parameter(0, mCurrentChunkEndTime - AUTOCOMPLETE_SEARCH_CHUNK); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mDBAutoCompleteQuery->BindInt64Parameter(1, mCurrentChunkEndTime); - NS_ENSURE_SUCCESS(rv, rv); - - nsString escapedSearchString; - rv = mDBAutoCompleteQuery->EscapeStringForLIKE(mCurrentSearchString, PRUnichar('/'), escapedSearchString); - NS_ENSURE_SUCCESS(rv, rv); - // prepend and append with % for "contains" - rv = mDBAutoCompleteQuery->BindStringParameter(2, NS_LITERAL_STRING("%") + escapedSearchString + NS_LITERAL_STRING("%")); + nsresult rv = mDBAutoCompleteQuery->BindStringParameter(0, NS_LITERAL_STRING("%") + mCurrentSearchStringEscaped + NS_LITERAL_STRING("%")); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBAutoCompleteQuery->BindInt32Parameter(1, AUTOCOMPLETE_SEARCH_CHUNK_SIZE); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBAutoCompleteQuery->BindInt32Parameter(2, mCurrentChunkOffset); NS_ENSURE_SUCCESS(rv, rv); nsFaviconService* faviconService = nsFaviconService::GetFaviconService(); @@ -652,39 +578,70 @@ nsNavHistory::AutoCompleteFullHistorySearch() // Determine the result of the search while (NS_SUCCEEDED(mDBAutoCompleteQuery->ExecuteStep(&hasMore)) && hasMore) { - nsAutoString entryURL, entryTitle, entryFavicon; + *aHasMoreResults = PR_TRUE; + nsAutoString entryURL; rv = mDBAutoCompleteQuery->GetString(kAutoCompleteIndex_URL, entryURL); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBAutoCompleteQuery->GetString(kAutoCompleteIndex_Title, entryTitle); - NS_ENSURE_SUCCESS(rv, rv); - rv = mDBAutoCompleteQuery->GetString(kAutoCompleteIndex_FaviconURL, entryFavicon); - NS_ENSURE_SUCCESS(rv, rv); - PRInt64 itemId = 0; - rv = mDBAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ItemId, &itemId); - NS_ENSURE_SUCCESS(rv, rv); - PRInt64 parentId = 0; - rv = mDBAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ParentId, &parentId); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool dummy; - // don't show rss feed items as bookmarked, - // but do show rss feed URIs as bookmarked. - PRBool isBookmark = (itemId != 0 && - !mLivemarkFeedItemIds.Get(parentId, &dummy)) || - mLivemarkFeedURIs.Get(entryURL, &dummy); // prevent duplicates. this can happen when chunking as we - // may have already seen this URL from an earlier chunk of time + // may have already seen this URL from our tag search or an earlier + // chunk. + PRBool dummy; if (!mCurrentResultURLs.Get(entryURL, &dummy)) { + nsAutoString entryTitle, entryFavicon, entryBookmarkTitle; + rv = mDBAutoCompleteQuery->GetString(kAutoCompleteIndex_Title, entryTitle); + NS_ENSURE_SUCCESS(rv, rv); + rv = mDBAutoCompleteQuery->GetString(kAutoCompleteIndex_FaviconURL, entryFavicon); + NS_ENSURE_SUCCESS(rv, rv); + PRInt64 itemId = 0; + rv = mDBAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ItemId, &itemId); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt64 parentId = 0; + // only bother to fetch parent id and bookmark title + // if we have a bookmark (itemId != 0) + if (itemId) { + rv = mDBAutoCompleteQuery->GetInt64(kAutoCompleteIndex_ParentId, &parentId); + NS_ENSURE_SUCCESS(rv, rv); + rv = mDBAutoCompleteQuery->GetString(kAutoCompleteIndex_BookmarkTitle, entryBookmarkTitle); + NS_ENSURE_SUCCESS(rv, rv); + } + + // don't show rss feed items as bookmarked, + // but do show rss feed URIs as bookmarked. + // + // NOTE: because we use mCurrentResultURLs to remove duplicates, + // the first url wins. + // so we might not show it as a "star" if the parentId we get first is + // the one for the livemark item, and not the bookmark item, + // we may not show the "star" even though we should. + // XXX bug 412734 + PRBool isBookmark = (itemId && + !mLivemarkFeedItemIds.Get(parentId, &dummy)) || + mLivemarkFeedURIs.Get(entryURL, &dummy); + // new item, append to our results and put it in our hash table. nsCAutoString faviconSpec; faviconService->GetFaviconSpecForIconString( NS_ConvertUTF16toUTF8(entryFavicon), faviconSpec); - rv = mCurrentResult->AppendMatch(entryURL, entryTitle, - NS_ConvertUTF8toUTF16(faviconSpec), isBookmark ? NS_LITERAL_STRING("bookmark") : NS_LITERAL_STRING("favicon")); + + // if the search string is in the bookmark title, show that in the + // result (instead of the page title) + PRBool matchInBookmarkTitle = itemId && + CaseInsensitiveFindInReadable(mCurrentSearchString, entryBookmarkTitle); + + rv = mCurrentResult->AppendMatch(entryURL, + matchInBookmarkTitle ? entryBookmarkTitle : entryTitle, + NS_ConvertUTF8toUTF16(faviconSpec), + isBookmark ? NS_LITERAL_STRING("bookmark") : NS_LITERAL_STRING("favicon")); NS_ENSURE_SUCCESS(rv, rv); mCurrentResultURLs.Put(entryURL, PR_TRUE); + + if (mCurrentResultURLs.Count() >= mAutoCompleteMaxResults) { + *aHasMoreResults = PR_FALSE; + break; + } } } diff --git a/toolkit/components/places/src/nsNavHistoryExpire.cpp b/toolkit/components/places/src/nsNavHistoryExpire.cpp index a5ed35e22537..bf84a62195a5 100644 --- a/toolkit/components/places/src/nsNavHistoryExpire.cpp +++ b/toolkit/components/places/src/nsNavHistoryExpire.cpp @@ -259,6 +259,26 @@ nsNavHistoryExpire::ClearHistory() if (NS_FAILED(rv)) NS_WARNING("ExpireAnnotationsParanoid failed."); + // for all remaining places, reset the frecency + // Note, we don't reset the visit_count, as we use that in our "on idle" + // query to figure out which places to recalcuate frecency first. + rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "UPDATE moz_places SET frecency = -1")); + if (NS_FAILED(rv)) + NS_WARNING("failed to recent frecency"); + + // some of the remaining places could be place: urls or + // unvisited livemark items, so setting the frecency to -1 + // will cause them to show up in the url bar autocomplete + // call FixInvalidFrecenciesForExcludedPlaces() to handle that scenario + rv = mHistory->FixInvalidFrecenciesForExcludedPlaces(); + if (NS_FAILED(rv)) + NS_WARNING("failed to fix invalid frecencies"); + + // XXX todo + // forcibly call the "on idle" timer here to do a little work + // but the rest will happen on idle. + ENUMERATE_WEAKARRAY(mHistory->mObservers, nsINavHistoryObserver, OnClearHistory()) @@ -506,21 +526,54 @@ nsNavHistoryExpire::EraseVisits(mozIStorageConnection* aConnection, const nsTArray& aRecords) { // build a comma separated string of visit ids to delete + // also build a comma separated string of place ids to reset frecency and + // visit_count. nsCString deletedVisitIds; + nsCString placeIds; + nsTArray deletedPlaceIdsArray, deletedVisitIdsArray; for (PRUint32 i = 0; i < aRecords.Length(); i ++) { - // Do not add comma separator for the first entry - if (! deletedVisitIds.IsEmpty()) - deletedVisitIds.AppendLiteral(","); - deletedVisitIds.AppendInt(aRecords[i].visitID); + // Do not add comma separator for the first visit id + if (deletedVisitIdsArray.IndexOf(aRecords[i].visitID) == -1) { + if (!deletedVisitIds.IsEmpty()) + deletedVisitIds.AppendLiteral(","); + deletedVisitIds.AppendInt(aRecords[i].visitID); + } + + // Do not add comma separator for the first place id + if (deletedPlaceIdsArray.IndexOf(aRecords[i].placeID) == -1) { + if (!placeIds.IsEmpty()) + placeIds.AppendLiteral(","); + placeIds.AppendInt(aRecords[i].placeID); + } } if (deletedVisitIds.IsEmpty()) return NS_OK; - return aConnection->ExecuteSimpleSQL( + nsresult rv = aConnection->ExecuteSimpleSQL( NS_LITERAL_CSTRING("DELETE FROM moz_historyvisits WHERE id IN (") + deletedVisitIds + NS_LITERAL_CSTRING(")")); + NS_ENSURE_SUCCESS(rv, rv); + + if (placeIds.IsEmpty()) + return NS_OK; + + // reset the frecencies for these places. + // Note, we don't reset the visit_count, as we use that in our "on idle" + // query to figure out which places to recalcuate frecency first. + rv = aConnection->ExecuteSimpleSQL( + NS_LITERAL_CSTRING("UPDATE moz_places SET " + "frecency = -1 WHERE id IN (") + + placeIds + + NS_LITERAL_CSTRING(")")); + NS_ENSURE_SUCCESS(rv, rv); + + // XXX todo + // forcibly call the "on idle" timer here to do a little work + // but the rest will happen on idle. + + return NS_OK; } @@ -548,7 +601,7 @@ nsNavHistoryExpire::EraseHistory(mozIStorageConnection* aConnection, // avoid trying to delete the same place id twice if (deletedPlaceIdsArray.IndexOf(aRecords[i].placeID) == -1) { // Do not add comma separator for the first entry - if (! deletedPlaceIds.IsEmpty()) + if (!deletedPlaceIds.IsEmpty()) deletedPlaceIds.AppendLiteral(","); deletedPlaceIdsArray.AppendElement(aRecords[i].placeID); deletedPlaceIds.AppendInt(aRecords[i].placeID); @@ -583,12 +636,12 @@ nsNavHistoryExpire::EraseFavicons(mozIStorageConnection* aConnection, nsTArray deletedFaviconIdsArray; for (PRUint32 i = 0; i < aRecords.Length(); i ++) { // IF main entry not expired OR no favicon DO NOT DELETE - if (! aRecords[i].erased || aRecords[i].faviconID == 0) + if (!aRecords[i].erased || aRecords[i].faviconID == 0) continue; // avoid trying to delete the same favicon id twice if (deletedFaviconIdsArray.IndexOf(aRecords[i].faviconID) == -1) { // Do not add comma separator for the first entry - if (! deletedFaviconIds.IsEmpty()) + if (!deletedFaviconIds.IsEmpty()) deletedFaviconIds.AppendLiteral(","); deletedFaviconIdsArray.AppendElement(aRecords[i].faviconID); deletedFaviconIds.AppendInt(aRecords[i].faviconID); @@ -893,7 +946,7 @@ nsNavHistoryExpire::ComputeNextExpirationTime( PRBool hasMore; rv = statement->ExecuteStep(&hasMore); - if (NS_FAILED(rv) || ! hasMore) + if (NS_FAILED(rv) || !hasMore) return; // no items, we'll leave mNextExpirationTime = 0 and try to expire // again next time @@ -907,7 +960,7 @@ nsNavHistoryExpire::ComputeNextExpirationTime( nsresult nsNavHistoryExpire::StartTimer(PRUint32 aMilleseconds) { - if (! mTimer) + if (!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1"); NS_ENSURE_STATE(mTimer); // returns on error nsresult rv = mTimer->InitWithFuncCallback(TimerCallback, this, diff --git a/toolkit/components/places/src/nsNavHistoryResult.cpp b/toolkit/components/places/src/nsNavHistoryResult.cpp index b745371c5447..fd2c6b6269dc 100644 --- a/toolkit/components/places/src/nsNavHistoryResult.cpp +++ b/toolkit/components/places/src/nsNavHistoryResult.cpp @@ -57,7 +57,9 @@ #include "nsIDynamicContainer.h" #include "nsIServiceManager.h" #include "nsISupportsPrimitives.h" +#ifdef MOZ_XUL #include "nsITreeColumns.h" +#endif #include "nsIURI.h" #include "nsIURL.h" #include "nsIWritablePropertyBag.h" @@ -2189,6 +2191,14 @@ nsNavHistoryQueryResultNode::GetUri(nsACString& aURI) return NS_OK; } +// nsNavHistoryQueryResultNode::GetFolderItemId + +NS_IMETHODIMP +nsNavHistoryQueryResultNode::GetFolderItemId(PRInt64* aItemId) +{ + *aItemId = mItemId; + return NS_OK; +} // nsNavHistoryQueryResultNode::GetQueries @@ -2951,6 +2961,15 @@ nsNavHistoryFolderResultNode::GetChildrenReadOnly(PRBool *aChildrenReadOnly) } +// nsNavHistoryFolderResultNode::GetFolderItemId + +NS_IMETHODIMP +nsNavHistoryFolderResultNode::GetFolderItemId(PRInt64* aItemId) +{ + *aItemId = mItemId; + return NS_OK; +} + // nsNavHistoryFolderResultNode::GetUri // // This lazily computes the URI for this specific folder query with @@ -4013,7 +4032,10 @@ nsNavHistoryResult::OnItemChanged(PRInt64 aItemId, if (folder) { PRUint32 nodeIndex; nsNavHistoryResultNode* node = folder->FindChildById(aItemId, &nodeIndex); - if (node && !(folder->mOptions->ExcludeItems()) && + // if ExcludeItems is true we don't update non visible items + if (node && + (!folder->mOptions->ExcludeItems() || + !(node->IsURI() || node->IsSeparator())) && folder->StartIncrementalUpdate()) { node->OnItemChanged(aItemId, aProperty, aIsAnnotationProperty, aValue); } diff --git a/toolkit/components/places/src/nsNavHistoryResult.h b/toolkit/components/places/src/nsNavHistoryResult.h index f9b1e7c70468..f330edce02cf 100644 --- a/toolkit/components/places/src/nsNavHistoryResult.h +++ b/toolkit/components/places/src/nsNavHistoryResult.h @@ -314,6 +314,7 @@ public: type == nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER || type == nsINavHistoryResultNode::RESULT_TYPE_QUERY || type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER || + type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT || type == nsINavHistoryResultNode::RESULT_TYPE_DAY); } PRBool IsContainer() { @@ -359,7 +360,8 @@ public: return IsTypeVisit(type); } static PRBool IsTypeFolder(PRUint32 type) { - return (type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER); + return (type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER || + type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT); } PRBool IsFolder() { PRUint32 type; @@ -760,8 +762,14 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID - NS_IMETHOD GetType(PRUint32* type) - { *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER; return NS_OK; } + NS_IMETHOD GetType(PRUint32* type) { + if (mQueryItemId != -1) { + *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT; + } else { + *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER; + } + return NS_OK; + } NS_IMETHOD GetUri(nsACString& aURI); NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN_AND_READONLY NS_IMETHOD GetHasChildren(PRBool* aHasChildren); diff --git a/toolkit/components/places/tests/bookmarks/test_bookmarks.js b/toolkit/components/places/tests/bookmarks/test_bookmarks.js index 2e3bba167cc2..553336c75b65 100644 --- a/toolkit/components/places/tests/bookmarks/test_bookmarks.js +++ b/toolkit/components/places/tests/bookmarks/test_bookmarks.js @@ -664,7 +664,7 @@ function run_test() { // bug 378820 var uri1 = uri("http://foo.tld/a"); bmsvc.insertBookmark(testRoot, uri1, bmsvc.DEFAULT_INDEX, ""); - histsvc.addVisit(uri1, Date.now(), null, histsvc.TRANSITION_TYPED, false, 0); + histsvc.addVisit(uri1, Date.now() * 1000, null, histsvc.TRANSITION_TYPED, false, 0); testSimpleFolderResult(); } diff --git a/toolkit/components/places/tests/bookmarks/test_savedsearches.js b/toolkit/components/places/tests/bookmarks/test_savedsearches.js index 96351265ae6a..9f88bc807290 100644 --- a/toolkit/components/places/tests/bookmarks/test_savedsearches.js +++ b/toolkit/components/places/tests/bookmarks/test_savedsearches.js @@ -176,7 +176,7 @@ function run_test() { // add a visit that matches the search term var testURI = uri("http://" + searchTerm + ".com"); - bhist.addPageWithDetails(testURI, searchTerm, Date.now()); + bhist.addPageWithDetails(testURI, searchTerm, Date.now() * 1000); // create a saved-search that matches the visit we added var searchId = bmsvc.insertBookmark(testRoot, @@ -216,7 +216,7 @@ function run_test() { do_check_eq(item.uri, testURI.spec); // history visit // test live-update of query results - add a history visit that matches the query - bhist.addPageWithDetails(uri("http://foo.com"), searchTerm + "blah", Date.now()); + bhist.addPageWithDetails(uri("http://foo.com"), searchTerm + "blah", Date.now() * 1000); do_check_eq(node.childCount, 2); // test live-update of query results - delete a history visit that matches the query diff --git a/toolkit/components/places/tests/unit/expected-favicon-big32.jpg.png b/toolkit/components/places/tests/unit/expected-favicon-big32.jpg.png index c3a4aee61667..0418a096d9e5 100644 Binary files a/toolkit/components/places/tests/unit/expected-favicon-big32.jpg.png and b/toolkit/components/places/tests/unit/expected-favicon-big32.jpg.png differ diff --git a/toolkit/components/places/tests/unit/expected-favicon-big4.jpg.png b/toolkit/components/places/tests/unit/expected-favicon-big4.jpg.png index 1175ba320343..01d99891caaa 100644 Binary files a/toolkit/components/places/tests/unit/expected-favicon-big4.jpg.png and b/toolkit/components/places/tests/unit/expected-favicon-big4.jpg.png differ diff --git a/toolkit/components/places/tests/unit/expected-favicon-big64.png.png b/toolkit/components/places/tests/unit/expected-favicon-big64.png.png index afe2c2dffe16..4814280b0a25 100644 Binary files a/toolkit/components/places/tests/unit/expected-favicon-big64.png.png and b/toolkit/components/places/tests/unit/expected-favicon-big64.png.png differ diff --git a/toolkit/components/places/tests/unit/expected-favicon-scale160x3.jpg.png b/toolkit/components/places/tests/unit/expected-favicon-scale160x3.jpg.png index 1b121e995183..5df53e60919f 100644 Binary files a/toolkit/components/places/tests/unit/expected-favicon-scale160x3.jpg.png and b/toolkit/components/places/tests/unit/expected-favicon-scale160x3.jpg.png differ diff --git a/toolkit/components/places/tests/unit/expected-favicon-scale3x160.jpg.png b/toolkit/components/places/tests/unit/expected-favicon-scale3x160.jpg.png index 56021cbd591c..9e8a65a9b881 100644 Binary files a/toolkit/components/places/tests/unit/expected-favicon-scale3x160.jpg.png and b/toolkit/components/places/tests/unit/expected-favicon-scale3x160.jpg.png differ diff --git a/toolkit/components/places/tests/unit/test_000_frecency.js b/toolkit/components/places/tests/unit/test_000_frecency.js new file mode 100644 index 000000000000..b54dac5bb32f --- /dev/null +++ b/toolkit/components/places/tests/unit/test_000_frecency.js @@ -0,0 +1,254 @@ +version(180); +/* -*- 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 Bug 378079 unit test code. + * + * The Initial Developer of the Original Code is POTI Inc. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Matt Crocker + * Seth Spitzer + * 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 ***** */ + +/* + +Autocomplete Frecency Tests + +- add a visit for each score permutation +- search +- test number of matches +- test each item's location in results + +*/ + +var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); +var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); +var prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + +function add_visit(aURI, aVisitDate, aVisitType) { + var isRedirect = aVisitType == histsvc.TRANSITION_REDIRECT_PERMANENT || + aVisitType == histsvc.TRANSITION_REDIRECT_TEMPORARY; + var placeID = histsvc.addVisit(aURI, aVisitDate, null, + aVisitType, isRedirect, 0); + do_check_true(placeID > 0); + return placeID; +} + +var bucketPrefs = [ + [ "firstBucketCutoff", "firstBucketWeight"], + [ "secondBucketCutoff", "secondBucketWeight"], + [ "thirdBucketCutoff", "thirdBucketWeight"], + [ "fourthBucketCutoff", "fourthBucketWeight"], + [ null, "defaultBucketWeight"] +]; + +var bonusPrefs = { + embedVisitBonus: Ci.nsINavHistoryService.TRANSITION_EMBED, + linkVisitBonus: Ci.nsINavHistoryService.TRANSITION_LINK, + typedVisitBonus: Ci.nsINavHistoryService.TRANSITION_TYPED, + bookmarkVisitBonus: Ci.nsINavHistoryService.TRANSITION_BOOKMARK, + downloadVisitBonus: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD, + permRedirectVisitBonus: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT, + tempRedirectVisitBonus: Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY, + defaultVisitBonus: 0, + unvisitedBookmarkBonus: 0 +// XXX todo +// unvisitedTypedBonus: 0 +}; + +// create test data +var searchTerm = "frecency"; +var results = []; +var matchCount = 0; +var now = Date.now(); +var prefPrefix = "places.frecency."; +bucketPrefs.every(function(bucket) { + let [cutoffName, weightName] = bucket; + // get pref values + var weight = 0, cutoff = 0, bonus = 0; + try { + weight = prefs.getIntPref(prefPrefix + weightName); + } catch(ex) {} + try { + cutoff = prefs.getIntPref(prefPrefix + cutoffName); + } catch(ex) {} + + if (cutoff < 1) + return true; + + // generate a date within the cutoff period + var dateInPeriod = (now - ((cutoff - 1) * 86400 * 1000)) * 1000; + + for (let [bonusName, visitType] in Iterator(bonusPrefs)) { + var frecency = -1; + var calculatedURI = null; + var matchTitle = ""; + var bonusValue = prefs.getIntPref(prefPrefix + bonusName); + // unvisited (only for first cutoff date bucket) + if (bonusName == "unvisitedBookmarkBonus" || bonusName == "unvisitedTypedBonus") { + if (cutoffName == "firstBucketCutoff") { + var points = Math.ceil(bonusValue / parseFloat(100.0) * weight); + var visitCount = 1; //bonusName == "unvisitedBookmarkBonus" ? 1 : 0; + frecency = Math.ceil(visitCount * points); + calculatedURI = uri("http://" + searchTerm + ".com/" + + bonusName + ":" + bonusValue + "/cutoff:" + cutoff + + "/weight:" + weight + "/frecency:" + frecency); + if (bonusName == "unvisitedBookmarkBonus") { + matchTitle = searchTerm + "UnvisitedBookmark"; + bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder, calculatedURI, bmsvc.DEFAULT_INDEX, matchTitle); + } + else { + matchTitle = searchTerm + "UnvisitedTyped"; + histsvc.setPageDetails(calculatedURI, matchTitle, 1, false, true); + } + } + } + else { + // visited + var points = Math.ceil(1 * ((bonusValue / parseFloat(100.000000)).toFixed(6) * weight) / 1); + if (!points) { + if (visitType == Ci.nsINavHistoryService.TRANSITION_EMBED || bonusName == "defaultVisitBonus") + frecency = 0; + else + frecency = -1; + } + else + frecency = points; + calculatedURI = uri("http://" + searchTerm + ".com/" + + bonusName + ":" + bonusValue + "/cutoff:" + cutoff + + "/weight:" + weight + "/frecency:" + frecency); + if (visitType == Ci.nsINavHistoryService.TRANSITION_BOOKMARK) { + matchTitle = searchTerm + "Bookmarked"; + bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder, calculatedURI, bmsvc.DEFAULT_INDEX, matchTitle); + } + else + matchTitle = calculatedURI.spec.substr(calculatedURI.spec.lastIndexOf("/")+1); + add_visit(calculatedURI, dateInPeriod, visitType); + } + + if (calculatedURI && frecency) + results.push([calculatedURI, frecency, matchTitle]); + } + return true; +}); + +// sort results by frecency +results.sort(function(a,b) a[1] - b[1]); +results.reverse(); + +//results.every(function(el) { dump("result: " + el[1] + ": " + el[0].spec + " (" + el[2] + ")\n"); return true; }) + +function AutoCompleteInput(aSearches) { + this.searches = aSearches; +} +AutoCompleteInput.prototype = { + constructor: AutoCompleteInput, + + searches: null, + + minResultsForPopup: 0, + timeout: 10, + searchParam: "", + textValue: "", + disableAutoComplete: false, + completeDefaultIndex: false, + + get searchCount() { + return this.searches.length; + }, + + getSearchAt: function(aIndex) { + return this.searches[aIndex]; + }, + + onSearchComplete: function() {}, + + popupOpen: false, + + popup: { + setSelectedIndex: function(aIndex) {}, + invalidate: function() {}, + + // nsISupports implementation + QueryInterface: function(iid) { + if (iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIAutoCompletePopup)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } + }, + + // nsISupports implementation + QueryInterface: function(iid) { + if (iid.equals(Ci.nsISupports) || + iid.equals(Ci.nsIAutoCompleteInput)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } +} + +function run_test() { + var controller = Components.classes["@mozilla.org/autocomplete/controller;1"]. + getService(Components.interfaces.nsIAutoCompleteController); + + // Make an AutoCompleteInput that uses our searches + // and confirms results on search complete + var input = new AutoCompleteInput(["history"]); + + controller.input = input; + + // Search is asynchronous, so don't let the test finish immediately + do_test_pending(); + + input.onSearchComplete = function() { + do_check_eq(controller.searchStatus, + Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH); + + // test that all records with non-zero frecency were matched + do_check_eq(controller.matchCount, results.length); + + // test that matches are sorted by frecency + for (var i = 0; i < controller.matchCount; i++) { + do_check_eq(controller.getValueAt(i), results[i][0].spec); + do_check_eq(controller.getCommentAt(i), results[i][2]); + } + + do_test_finished(); + }; + + controller.startSearch(searchTerm); +} diff --git a/toolkit/components/places/tests/unit/test_385397.js b/toolkit/components/places/tests/unit/test_385397.js index 5e831ba334e8..0f1302c544ba 100644 --- a/toolkit/components/places/tests/unit/test_385397.js +++ b/toolkit/components/places/tests/unit/test_385397.js @@ -62,7 +62,7 @@ const TOTAL_SITES = 20; // main function run_test() { - var now = Date.now(); + var now = Date.now() * 1000; // add visits for (var i=0; i < TOTAL_SITES; i++) { var site = "http://www.test-" + i + ".com/"; diff --git a/toolkit/components/places/tests/unit/test_399266.js b/toolkit/components/places/tests/unit/test_399266.js index 283bac617884..b4cc7cca6534 100644 --- a/toolkit/components/places/tests/unit/test_399266.js +++ b/toolkit/components/places/tests/unit/test_399266.js @@ -49,7 +49,7 @@ try { // adds a test URI visit to the database, and checks for a valid place ID function add_visit(aURI, aType) { var placeID = histsvc.addVisit(uri(aURI), - Date.now(), + Date.now() * 1000, null, // no referrer aType, false, // not redirect diff --git a/toolkit/components/places/tests/unit/test_browserhistory.js b/toolkit/components/places/tests/unit/test_browserhistory.js index 07e03e373ffa..ee6d5d2e142f 100644 --- a/toolkit/components/places/tests/unit/test_browserhistory.js +++ b/toolkit/components/places/tests/unit/test_browserhistory.js @@ -55,7 +55,7 @@ function run_test() { * the History migrator. */ try { - bhist.addPageWithDetails(testURI, "testURI", Date.now()); + bhist.addPageWithDetails(testURI, "testURI", Date.now() * 1000); } catch(ex) { do_throw("addPageWithDetails failed"); } @@ -89,13 +89,13 @@ function run_test() { * If aEntireDomain is true, will assume aHost is a domain, * and remove all pages from the entire domain. */ - bhist.addPageWithDetails(testURI, "testURI", Date.now()); + bhist.addPageWithDetails(testURI, "testURI", Date.now() * 1000); bhist.removePagesFromHost("mozilla.com", true); do_check_eq(0, bhist.count); // test aEntireDomain - bhist.addPageWithDetails(testURI, "testURI", Date.now()); - bhist.addPageWithDetails(uri("http://foobar.mozilla.com"), "testURI2", Date.now()); + bhist.addPageWithDetails(testURI, "testURI", Date.now() * 1000); + bhist.addPageWithDetails(uri("http://foobar.mozilla.com"), "testURI2", Date.now() * 1000); bhist.removePagesFromHost("mozilla.com", false); do_check_eq(1, bhist.count); @@ -115,7 +115,7 @@ function run_test() { * as if it was visited, and then marked as hidden */ //XXX NOT IMPLEMENTED in the history service - //bhist.addPageWithDetails(testURI, "testURI", Date.now()); + //bhist.addPageWithDetails(testURI, "testURI", Date.now() * 1000); //bhist.hidePage(testURI); //do_check_eq(0, bhist.count); } diff --git a/toolkit/components/places/tests/unit/test_expiration.js b/toolkit/components/places/tests/unit/test_expiration.js index f560f6819136..62fa11569f50 100644 --- a/toolkit/components/places/tests/unit/test_expiration.js +++ b/toolkit/components/places/tests/unit/test_expiration.js @@ -139,9 +139,9 @@ function run_test() { histsvc.addVisit(removeAllTestURI, Date.now() * 1000, null, histsvc.TRANSITION_TYPED, false, 0); var bmURI = uri("http://bookmarked"); bmsvc.insertBookmark(bmsvc.bookmarksMenuFolder, bmURI, bmsvc.DEFAULT_INDEX, "foo"); - //bhist.addPageWithDetails(placeURI, "place uri", Date.now()); + //bhist.addPageWithDetails(placeURI, "place uri", Date.now() * 1000); var placeURI = uri("place:folder=23"); - bhist.addPageWithDetails(placeURI, "place uri", Date.now()); + bhist.addPageWithDetails(placeURI, "place uri", Date.now() * 1000); annosvc.setPageAnnotation(removeAllTestURI, testAnnoName + "Hist", testAnnoVal, 0, annosvc.EXPIRE_WITH_HISTORY); annosvc.setPageAnnotation(removeAllTestURINever, testAnnoName + "Never", testAnnoVal, 0, annosvc.EXPIRE_NEVER); bhist.removeAllPages(); diff --git a/toolkit/components/places/tests/unit/test_favicons.js b/toolkit/components/places/tests/unit/test_favicons.js index 2edaadddc12e..99b634665903 100644 --- a/toolkit/components/places/tests/unit/test_favicons.js +++ b/toolkit/components/places/tests/unit/test_favicons.js @@ -100,9 +100,6 @@ var iconsvc; function run_test() { try { -// Disable test for now. -return; - /* ========== 0 ========== */ var testnum = 0; var testdesc = "nsIFaviconService setup"; @@ -113,6 +110,13 @@ iconsvc = Cc["@mozilla.org/browser/favicon-service;1"]. if (!iconsvc) throw "Couldn't get nsIFaviconService service" +// Ugh, this is an ugly hack. The pixel values we get in Windows are sometimes +// +/- 1 value compared to other platforms, so we need to compare against a +// different set of reference images. nsIXULRuntime.OS doesn't seem to be +// available in xpcshell, so we'll use this as a kludgy way to figure out if +// we're running on Windows. +var isWindows = ("@mozilla.org/windows-registry-key;1" in Cc); + /* ========== 1 ========== */ testnum++; @@ -220,7 +224,10 @@ var expectedData = readFileData(expectedFile); // Compare thet expected data to the actual data. do_check_eq("image/png", outMimeType); -compareArrays(expectedData, outData); +// Disabled on Windows due to problems with pixels varying slightly. +if (!isWindows) + compareArrays(expectedData, outData); + /* ========== 6 ========== */ testnum++; diff --git a/toolkit/components/places/tests/unit/test_history.js b/toolkit/components/places/tests/unit/test_history.js index ccab226503a8..fd25d6b87065 100644 --- a/toolkit/components/places/tests/unit/test_history.js +++ b/toolkit/components/places/tests/unit/test_history.js @@ -56,7 +56,7 @@ try { */ function add_visit(aURI, aReferrer) { var placeID = histsvc.addVisit(aURI, - Date.now(), + Date.now() * 1000, aReferrer, histsvc.TRANSITION_TYPED, // user typed in URL bar false, // not redirect diff --git a/toolkit/components/places/tests/unit/test_nsINavHistoryViewer.js b/toolkit/components/places/tests/unit/test_nsINavHistoryViewer.js index 709ef9a11ecb..d922913d2c03 100644 --- a/toolkit/components/places/tests/unit/test_nsINavHistoryViewer.js +++ b/toolkit/components/places/tests/unit/test_nsINavHistoryViewer.js @@ -53,7 +53,7 @@ try { // adds a test URI visit to the database, and checks for a valid place ID function add_visit(aURI, aDate) { - var date = aDate || Date.now(); + var date = aDate || Date.now() * 1000; var placeID = histsvc.addVisit(aURI, date, null, // no referrer @@ -152,7 +152,7 @@ function run_test() { do_check_eq(root.uri, viewer.changedItem.uri); // nsINavHistoryResultViewer.itemChanged for a leaf node - bhist.addPageWithDetails(testURI, "baz", Date.now()); + bhist.addPageWithDetails(testURI, "baz", Date.now() * 1000); do_check_eq(viewer.changedItem.title, "baz"); // nsINavHistoryResultViewer.itemRemoved diff --git a/toolkit/components/places/tests/unit/test_resolveNullBookmarkTitles.js b/toolkit/components/places/tests/unit/test_resolveNullBookmarkTitles.js index b19dea36d95c..0b79eed3ebcd 100644 --- a/toolkit/components/places/tests/unit/test_resolveNullBookmarkTitles.js +++ b/toolkit/components/places/tests/unit/test_resolveNullBookmarkTitles.js @@ -71,9 +71,9 @@ function run_test() { tagssvc.tagURI(uri1, ["tag 1"]); tagssvc.tagURI(uri2, ["tag 2"]); - histsvc.addVisit(uri1, Date.now(), null, histsvc.TRANSITION_TYPED, false, 0); + histsvc.addVisit(uri1, Date.now() * 1000, null, histsvc.TRANSITION_TYPED, false, 0); histsvc.setPageDetails(uri1, "foo title", 0, false, true); - histsvc.addVisit(uri2, Date.now(), null, histsvc.TRANSITION_TYPED, false, 0); + histsvc.addVisit(uri2, Date.now() * 1000, null, histsvc.TRANSITION_TYPED, false, 0); histsvc.setPageDetails(uri2, "bar title", 0, false, true); var options = histsvc.getNewQueryOptions(); diff --git a/toolkit/components/url-classifier/public/nsIUrlClassifierDBService.idl b/toolkit/components/url-classifier/public/nsIUrlClassifierDBService.idl index b716f6dcf091..8e648e151d98 100644 --- a/toolkit/components/url-classifier/public/nsIUrlClassifierDBService.idl +++ b/toolkit/components/url-classifier/public/nsIUrlClassifierDBService.idl @@ -127,7 +127,8 @@ interface nsIUrlClassifierDBService : nsISupports // is complete. /** - * Begin an update process. + * Begin an update process. Will throw NS_ERROR_NOT_AVAILABLE if there + * is already an update in progress. */ void beginUpdate(in nsIUrlClassifierUpdateObserver updater); diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp index f8bb07a52532..e01f00cf3d2c 100644 --- a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp +++ b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp @@ -2593,6 +2593,7 @@ nsUrlClassifierDBService::GetInstance(nsresult *result) nsUrlClassifierDBService::nsUrlClassifierDBService() : mCheckMalware(CHECK_MALWARE_DEFAULT) , mCheckPhishing(CHECK_PHISHING_DEFAULT) + , mInUpdate(PR_FALSE) { } @@ -2779,6 +2780,11 @@ nsUrlClassifierDBService::BeginUpdate(nsIUrlClassifierUpdateObserver *observer) { NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED); + if (mInUpdate) + return NS_ERROR_NOT_AVAILABLE; + + mInUpdate = PR_TRUE; + nsresult rv; // The proxy observer uses the current thread @@ -2817,12 +2823,13 @@ nsUrlClassifierDBService::FinishStream() return mWorkerProxy->FinishStream(); } - NS_IMETHODIMP nsUrlClassifierDBService::FinishUpdate() { NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED); + mInUpdate = PR_FALSE; + return mWorkerProxy->FinishUpdate(); } @@ -2832,6 +2839,8 @@ nsUrlClassifierDBService::CancelUpdate() { NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED); + mInUpdate = PR_FALSE; + return mWorkerProxy->CancelUpdate(); } diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.h b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.h index a002769280c4..af9a09896a5a 100644 --- a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.h +++ b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.h @@ -101,6 +101,12 @@ private: // TRUE if the nsURIClassifier implementation should check for phishing // uris on document loads. PRBool mCheckPhishing; + + // TRUE if a BeginUpdate() has been called without an accompanying + // CancelUpdate()/FinishUpdate(). This is used to prevent competing + // updates, not to determine whether an update is still being + // processed. + PRBool mInUpdate; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsUrlClassifierDBService, NS_URLCLASSIFIERDBSERVICE_CID) diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierStreamUpdater.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierStreamUpdater.cpp index 93dd7c105957..68b60c02b85b 100644 --- a/toolkit/components/url-classifier/src/nsUrlClassifierStreamUpdater.cpp +++ b/toolkit/components/url-classifier/src/nsUrlClassifierStreamUpdater.cpp @@ -164,6 +164,10 @@ nsUrlClassifierStreamUpdater::DownloadUpdates( nsIUrlClassifierCallback *aDownloadErrorCallback, PRBool *_retval) { + NS_ENSURE_ARG(aSuccessCallback); + NS_ENSURE_ARG(aUpdateErrorCallback); + NS_ENSURE_ARG(aDownloadErrorCallback); + if (mIsUpdating) { LOG(("already updating, skipping update")); *_retval = PR_FALSE; @@ -194,6 +198,15 @@ nsUrlClassifierStreamUpdater::DownloadUpdates( mInitialized = PR_TRUE; } + rv = mDBService->BeginUpdate(this); + if (rv == NS_ERROR_NOT_AVAILABLE) { + LOG(("already updating, skipping update")); + *_retval = PR_FALSE; + return NS_OK; + } else if (NS_FAILED(rv)) { + return rv; + } + mSuccessCallback = aSuccessCallback; mUpdateErrorCallback = aUpdateErrorCallback; mDownloadErrorCallback = aDownloadErrorCallback; @@ -201,7 +214,6 @@ nsUrlClassifierStreamUpdater::DownloadUpdates( mIsUpdating = PR_TRUE; *_retval = PR_TRUE; - mDBService->BeginUpdate(this); return FetchUpdate(mUpdateUrl, aRequestBody); } @@ -269,7 +281,7 @@ nsUrlClassifierStreamUpdater::UpdateSuccess(PRUint32 requestedTimeout) NS_IMETHODIMP nsUrlClassifierStreamUpdater::UpdateError(PRUint32 result) { - LOG(("nsUrlClassifierStreamUpdater::UpdateSuccess [this=%p]", this)); + LOG(("nsUrlClassifierStreamUpdater::UpdateError [this=%p]", this)); // DownloadDone() clears mUpdateErrorCallback, so we save it off here. nsCOMPtr errorCallback = mUpdateErrorCallback; diff --git a/toolkit/components/viewconfig/content/config.xul b/toolkit/components/viewconfig/content/config.xul index 525cc406daa6..973fabfe4c50 100644 --- a/toolkit/components/viewconfig/content/config.xul +++ b/toolkit/components/viewconfig/content/config.xul @@ -81,11 +81,11 @@ - - - + + + - +

&crashes.title;

+
+ + + + + + + + + +
&id.heading;&date.heading;
+
+ + + + diff --git a/toolkit/crashreporter/jar.mn b/toolkit/crashreporter/jar.mn new file mode 100644 index 000000000000..09c848f398b1 --- /dev/null +++ b/toolkit/crashreporter/jar.mn @@ -0,0 +1,2 @@ +toolkit.jar: +*+ content/global/crashes.xhtml (content/crashes.xhtml) diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 9218af0e9208..3410581eb5a9 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -212,9 +212,6 @@ endif ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT)) EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(MOZ_XFT_LIBS) $(MOZ_GTK2_LIBS) $(XT_LIBS) -lgthread-2.0 -endif - -ifdef MOZ_ENABLE_XFT EXTRA_DSO_LDOPTS += $(FT2_LIBS) endif diff --git a/toolkit/library/libxul-rules.mk b/toolkit/library/libxul-rules.mk index 994d46aa7a0a..80227eabf751 100644 --- a/toolkit/library/libxul-rules.mk +++ b/toolkit/library/libxul-rules.mk @@ -81,7 +81,7 @@ endif endif endif # MOZ_ENABLE_CAIRO_GFX -ifdef MOZ_ENABLE_PANGO +ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) endif diff --git a/toolkit/library/xulrunos2.rc b/toolkit/library/xulrunos2.rc index 4a0ad1e73fc0..382fb7022fc3 100644 --- a/toolkit/library/xulrunos2.rc +++ b/toolkit/library/xulrunos2.rc @@ -49,6 +49,7 @@ POINTER IDC_ZOOMOUT "..\\..\\widget\\src\\os2\\res\\zoom_out.ptr" POINTER IDC_ARROWWAIT "..\\..\\widget\\src\\os2\\res\\arrow_wait.ptr" POINTER IDC_CROSS "..\\..\\widget\\src\\os2\\res\\crosshair.ptr" POINTER IDC_HELP "..\\..\\widget\\src\\os2\\res\\help.ptr" +POINTER IDC_NONE "..\\..\\widget\\src\\os2\\res\\none.ptr" ICON IDC_DNDURL "..\\..\\widget\\src\\os2\\res\\dndurl.ico" ICON IDC_DNDTEXT "..\\..\\widget\\src\\os2\\res\\dndtext.ico" diff --git a/toolkit/locales/en-US/chrome/global/config.dtd b/toolkit/locales/en-US/chrome/global/config.dtd index 1cfaa6c68c09..6bbff60080c4 100644 --- a/toolkit/locales/en-US/chrome/global/config.dtd +++ b/toolkit/locales/en-US/chrome/global/config.dtd @@ -36,10 +36,11 @@ - - - - + + + + + diff --git a/toolkit/locales/en-US/chrome/global/findbar.properties b/toolkit/locales/en-US/chrome/global/findbar.properties index 8cb3a106a211..0166aaed2780 100644 --- a/toolkit/locales/en-US/chrome/global/findbar.properties +++ b/toolkit/locales/en-US/chrome/global/findbar.properties @@ -6,3 +6,6 @@ NormalFindLabel=Find: FastFindLabel=Quick Find: FastFindLinksLabel=Quick Find (links only): CaseSensitive=(Case sensitive) +FoundMatchCount=%S match +FoundMatchesCount=%S matches +FoundTooManyMatches=More than %S matches diff --git a/toolkit/locales/en-US/chrome/global/gnomeprintdialog.properties b/toolkit/locales/en-US/chrome/global/gnomeprintdialog.properties new file mode 100644 index 000000000000..96a8c55e290f --- /dev/null +++ b/toolkit/locales/en-US/chrome/global/gnomeprintdialog.properties @@ -0,0 +1,28 @@ +printTitle=Print +optionsTabLabel=Options +printFramesTitle=Print Frames + +# TRANSLATOR NOTE: For radio button labels and check button labels, an underscore _ +# before a character will turn that character into an accesskey. +# e.g. "_As laid out" will make A the accesskey. + +asLaidOut=_As Laid Out on the Screen +selectedFrame=The _Selected Frame +separateFrames=Each Frame on Separate _Pages +shrinkToFit=Ignore Scaling and S_hrink To Fit Page Width +selectionOnly=Print Selection _Only +printBGOptions=Print Backgrounds +printBGColors=Print Background _Colors +printBGImages=Print Background I_mages +headerFooter=Header and Footer +left=Left +center=Center +right=Right +headerFooterBlank=--blank-- +headerFooterTitle=Title +headerFooterURL=URL +headerFooterDate=Date/Time +headerFooterPage=Page # +headerFooterPageTotal=Page # of # +headerFooterCustom=Custom... +customHeaderFooterPrompt=Please enter your custom header/footer text diff --git a/toolkit/locales/en-US/chrome/global/intl.properties b/toolkit/locales/en-US/chrome/global/intl.properties index 741e09711181..8afc0f37363e 100644 --- a/toolkit/locales/en-US/chrome/global/intl.properties +++ b/toolkit/locales/en-US/chrome/global/intl.properties @@ -6,6 +6,13 @@ # charset names and use canonical names exactly as listed there. # Also note that "UTF-8" should always be included in intl.charsetmenu.browser.static general.useragent.locale=en-US + +# LOCALIZATION NOTE (pluralRule): Pick the appropriate plural rule for your +# language. This will determine how many plural forms of a word you will need +# to provide and in what order. +# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals +pluralRule=1 + # Localization Note: font.language.group controls the initial setting of the # language drop-down in the fonts pref panel. Set it to the value of one of the # menuitems in the "selectLangs" menulist in diff --git a/toolkit/locales/en-US/chrome/global/textcontext.dtd b/toolkit/locales/en-US/chrome/global/textcontext.dtd index a3f33f797db3..c870eeca52be 100644 --- a/toolkit/locales/en-US/chrome/global/textcontext.dtd +++ b/toolkit/locales/en-US/chrome/global/textcontext.dtd @@ -11,10 +11,10 @@ - + - - - + + + diff --git a/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.dtd b/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.dtd index 2d6f1824b498..c2ff50017220 100644 --- a/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.dtd +++ b/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.dtd @@ -1,4 +1,7 @@ - + + @@ -13,9 +16,9 @@ - - + + diff --git a/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties b/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties index c352d8489d89..3bfd944220fd 100644 --- a/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties +++ b/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties @@ -1,3 +1,10 @@ +# LOCALIZATION NOTE (seconds, minutes, hours, days): Semi-colon list of plural +# forms. See: http://developer.mozilla.org/en/docs/Localization_and_Plurals +seconds=second;seconds +minutes=minute;minutes +hours=hour;hours +days=day;days + # LOCALIZATION NOTE (paused): — is the "em dash" (long dash) paused=Paused — #1 downloading=Downloading @@ -6,6 +13,8 @@ failed=Failed finished=Finished canceled=Canceled +cannotPause=This download cannot be paused + downloadErrorAlertTitle=Download Error downloadErrorGeneric=The download cannot be saved because an unknown error occurred.\n\nPlease try again. @@ -41,14 +50,17 @@ transferSameUnits=#1 of #3 #4 transferDiffUnits=#1 #2 of #3 #4 transferNoTotal=#1 #2 -# LOCALIZATION NOTE (timeMinutesLeft): number of minutes left (greater than 1) -# LOCALIZATION NOTE (timeSecondsLeft): number of seconds left (greater than 3) -# 3 min -> 2 min -> 60 secs -> 59 secs -> … -> 5 secs -> 4 secs -> few secs -# examples: 11 minutes left; 11 seconds left; -timeMinutesLeft=#1 minutes left -timeSecondsLeft=#1 seconds left -timeFewSeconds=A few seconds left -timeUnknown=Unknown time left +# LOCALIZATION NOTE (timePair): #1 time number; #2 time unit +# example: 1 minute; 11 hours +timePair=#1 #2 +# LOCALIZATION NOTE (timeLeftSingle): #1 time left +# example: 1 minute remaining; 11 hours remaining +timeLeftSingle=#1 remaining +# LOCALIZATION NOTE (timeLeftDouble): #1 time left; #2 time left sub units +# example: 11 hours, 2 minutes remaining; 1 day, 22 hours remaining +timeLeftDouble=#1, #2 remaining +timeFewSeconds=A few seconds remaining +timeUnknown=Unknown time remaining # LOCALIZATION NOTE (doneStatus): — is the "em dash" (long dash) # #1 download size for FINISHED or download state; #2 host (e.g., eTLD + 1, IP) @@ -83,6 +95,13 @@ chooseAppFilePickerTitle=Open With… downloadsTitle=%S%% of 1 file - Downloads downloadsTitleMultiple=%S%% of %S files - Downloads +# LOCALIZATION NOTE (downloadsTitleFiles, downloadsTitlePercent): Semi-colon list of +# plural forms. See: http://developer.mozilla.org/en/docs/Localization_and_Plurals +# #1 number of files; #2 overall download percent (only for downloadsTitlePercent) +# examples: 2% of 1 file - Downloads; 22% of 11 files - Downloads +downloadsTitleFiles=#1 file - Downloads;#1 files - Downloads +downloadsTitlePercent=#2% of #1 file - Downloads;#2% of #1 files - Downloads + fileExecutableSecurityWarning="%S" is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch "%S"? fileExecutableSecurityWarningTitle=Open Executable File? fileExecutableSecurityWarningDontAsk=Don't ask me this again diff --git a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd index 99bd07dbf384..9040d90c7a0e 100644 --- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd +++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd @@ -9,6 +9,7 @@ + @@ -32,7 +33,7 @@ - + @@ -82,6 +83,9 @@ + + + @@ -117,6 +121,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -134,3 +159,8 @@ + + + + + diff --git a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties index 2336cefdabf2..eb7ada1adc78 100644 --- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties +++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties @@ -20,7 +20,9 @@ multipleUpdateNotificationText=%S has found updates for %S of your add-ons uninstallButton=Uninstall disableButton=Disable cancelButton=Cancel +restartMessage=Restart %S to complete your changes. restartButton=Restart %S +restartAccessKey=R laterButton=Later moreInfoText=More information uninstallTitle=Uninstall %S @@ -103,6 +105,7 @@ disabledCompatMsg=Add-on compatibility checking is disabled. You may have incomp disabledUpdateSecurityMsg=Add-on update security checking is disabled. You may be compromised by updates. noUpdatesMsg=No updates were found. offlineUpdateMsg=%S is currently in offline mode and is unable to update Add-ons. Click Go Online and try again. +offlineSearchMsg=%S is currently in offline mode and is unable to search for add-ons. Click Go Online and try again. enableButtonLabel=Enable enableButtonAccesskey=n goOnlineButtonLabel=Go Online @@ -110,3 +113,7 @@ goOnlineButtonAccesskey=G newUpdateWindowTitle=%S Add-on Updates newUpdatesAvailableMsg=There are new updates available for your add-ons. + +searchResults=See all results (%S) + +eulaHeader=%S requires that you accept the following End User License Agreement before installation can proceed: diff --git a/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.dtd b/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.dtd index f9147542b4e3..5a1acd7dcbaf 100644 --- a/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.dtd +++ b/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.dtd @@ -1,8 +1,9 @@ - - - + + + + diff --git a/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.properties b/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.properties index eb7785208fe4..fbee44787001 100644 --- a/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.properties +++ b/toolkit/locales/en-US/chrome/mozapps/xpinstall/xpinstallConfirm.properties @@ -1,4 +1,5 @@ -Unsigned=Unsigned +unsigned=(Author Unknown) +signed=(%S) itemWarnIntroMultiple=You have asked to install the following %S items: itemWarnIntroSingle=You have asked to install the following item: diff --git a/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties b/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties index e952c11da1a6..d6f9ec663d66 100644 --- a/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties +++ b/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties @@ -48,8 +48,12 @@ rememberButtonText = &Remember notifyBarRememberButtonText = Remember notifyBarRememberButtonAccessKey = R passwordChangeTitle = Confirm Password Change -passwordChangeText = Would you like to have Password Manager change the stored password for %S? -passwordChangeTextNoUser = Would you like to have Password Manager change the stored password for this login? +passwordChangeText = Would you like to change the stored password for %S? +passwordChangeTextNoUser = Would you like to change the stored password for this login? +notifyBarChangeButtonText = Change +notifyBarChangeButtonAccessKey = C +notifyBarDontChangeButtonText = Don't Change +notifyBarDontChangeButtonAccessKey = D userSelectText = Please confirm which user you are changing the password for hidePasswords=Hide Passwords hidePasswordsAccessKey=P diff --git a/toolkit/locales/en-US/crashreporter/crashes.dtd b/toolkit/locales/en-US/crashreporter/crashes.dtd new file mode 100644 index 000000000000..23b0def9d413 --- /dev/null +++ b/toolkit/locales/en-US/crashreporter/crashes.dtd @@ -0,0 +1,7 @@ + + + + +breakpad.reportURL must be set."> + + diff --git a/toolkit/locales/en-US/crashreporter/crashes.properties b/toolkit/locales/en-US/crashreporter/crashes.properties new file mode 100644 index 000000000000..41e51bb69421 --- /dev/null +++ b/toolkit/locales/en-US/crashreporter/crashes.properties @@ -0,0 +1,2 @@ +deleteconfirm.title=Are you sure? +deleteconfirm.description=This will delete all reports and cannot be undone diff --git a/toolkit/locales/en-US/crashreporter/crashreporter.ini b/toolkit/locales/en-US/crashreporter/crashreporter.ini index f694dc136723..0650ac981223 100644 --- a/toolkit/locales/en-US/crashreporter/crashreporter.ini +++ b/toolkit/locales/en-US/crashreporter/crashreporter.ini @@ -3,24 +3,34 @@ CrashReporterTitle=Crash Reporter # LOCALIZATION NOTE (CrashReporterVendorTitle): %s is replaced with the vendor name. (i.e. "Mozilla") CrashReporterVendorTitle=%s Crash Reporter -# LOCALIZATION NOTE (CrashReporterError): %s is replaced with another string containing detailed information. -CrashReporterError=We're sorry, but the application hit an unexpected problem and crashed.\n\nUnfortunately the crash reporter is unable to submit a report for this crash.\n\nDetails: %s -# LOCALIZATION NOTE (CrashReporterProductError): The first %s is replaced with the product name (i.e. "Firefox"), the second is replaced with another string containing detailed information. These two substitutions can not be reordered! -CrashReporterProductError=We're sorry, but %s hit an unexpected problem and crashed. We'll try to restore your tabs and windows when it restarts.\n\nUnfortunately the crash reporter is unable to submit a crash report.\n\nDetails: %s -CrashReporterHeader=Crash! Bang! Boom! -# LOCALIZATION NOTE (CrashReporterDescription): The %s is replaced with the product name. -CrashReporterDescription=We're sorry, but %s hit an unexpected problem and crashed. We'll try to restore your tabs and windows when it restarts.\n\nTo help us diagnose and repair this problem, you can send us a crash report. +# LOCALIZATION NOTE (CrashReporterErrorText): %s is replaced with another string containing detailed information. +CrashReporterErrorText=The application had problem and crashed.\n\nUnfortunately the crash reporter is unable to submit a report for this crash.\n\nDetails: %s +# LOCALIZATION NOTE (CrashReporterProductErrorText2): The first %s is replaced with the product name (i.e. "Firefox"), the second is replaced with another string containing detailed information. These two substitutions can not be reordered! +CrashReporterProductErrorText2=%s had a problem and crashed.\n\nUnfortunately the crash reporter is unable to submit a crash report.\n\nDetails: %s +CrashReporterSorry=We're Sorry +# LOCALIZATION NOTE (CrashReporterDescriptionText2): The %s is replaced with the product name. +CrashReporterDescriptionText2=%s had a problem and crashed.\n\nTo help us diagnose and fix the problem, you can send us a crash report. CrashReporterDefault=This application is run after a crash to report the problem to the application vendor. It should not be run directly. -ViewReport=View Report -ExtraReportInfo=This report also contains information about the state of the application when it crashed. -# LOCALIZATION NOTE (CheckSubmit): The %s is replaced with the vendor name. -CheckSubmit=Submit crash report to %s -CheckURL=Include the URL in the crash report -CheckEmail=Email me when the problem is fixed -Close=Close +Details=Details… +ViewReportTitle=Report Contents +CommentGrayText=Add a comment. Note: Comments are publicly visible +ExtraReportInfo=This report also contains technical information about the state of the application when it crashed. +# LOCALIZATION NOTE (CheckSendReport): The %s is replaced with the vendor name. +CheckSendReport=Tell %s about this crash so they can fix it +CheckIncludeURL=Include the address of the page I was on +CheckSendEmail=Email me when more information is available +EmailGrayText=Enter your email address here +ReportPreSubmit=Your crash report will be submitted when you restart. +ReportDuringSubmit=Submitting your report and restarting… +ReportSubmitSuccess=Report submitted successfully! +ReportSubmitFailed=There was a problem submitting your report. +ReportResubmit=Resending reports that previously failed to send… +Quit=Quit without sending # LOCALIZATION NOTE (Restart): The %s is replaced with the product name. Restart=Restart %s -SubmitFailed=Failed to submit crash report +Ok=OK +Close=Close + # LOCALIZATION NOTE (CrashID): The %s is replaced with the Crash ID from the server, which is a string like abc12345-6789-0abc-def1-23456abcdef1 CrashID=Crash ID: %s # LOCALIZATION NOTE (CrashDetailsURL): The %s is replaced with a URL that the user can visit to view the crash details. @@ -35,4 +45,6 @@ ErrorNoProductName=The application did not identify itself. ErrorNoServerURL=The application did not specify a crash reporting server. ErrorNoSettingsPath=Couldn't find the crash reporter's settings. ErrorCreateDumpDir=Couldn't create pending dump directory. +# LOCALIZATION NOTE (ErrorEndOfLife): The %s is replaced with the product name. +ErrorEndOfLife=The version of %s you are using is no longer supported. Crash reports are no longer being accepted for this version. Please consider upgrading to a supported version. diff --git a/toolkit/locales/jar.mn b/toolkit/locales/jar.mn index 1b2477c57b04..d32cc44420ab 100644 --- a/toolkit/locales/jar.mn +++ b/toolkit/locales/jar.mn @@ -40,6 +40,7 @@ + locale/@AB_CD@/global/printPageSetup.dtd (%chrome/global/printPageSetup.dtd) + locale/@AB_CD@/global/printPreview.dtd (%chrome/global/printPreview.dtd) + locale/@AB_CD@/global/printPreviewProgress.dtd (%chrome/global/printPreviewProgress.dtd) + locale/@AB_CD@/global/gnomeprintdialog.properties (%chrome/global/gnomeprintdialog.properties) + locale/@AB_CD@/global/printProgress.dtd (%chrome/global/printProgress.dtd) + locale/@AB_CD@/global/regionNames.properties (%chrome/global/regionNames.properties) + locale/@AB_CD@/global/dialog.properties (%chrome/global/dialog.properties) @@ -55,6 +56,8 @@ locale/@AB_CD@/global/nsProgressDialog.properties (%chrome/global/nsProgressDialog.properties) locale/@AB_CD@/global/history/history.properties (%chrome/global/history/history.properties) locale/@AB_CD@/global/xpinstall/xpinstall.properties (%chrome/global/xpinstall/xpinstall.properties) + locale/@AB_CD@/global/crashes.dtd (%crashreporter/crashes.dtd) + locale/@AB_CD@/global/crashes.properties (%crashreporter/crashes.properties) % locale global-region @AB_CD@ %locale/@AB_CD@/global-region/ + locale/@AB_CD@/global-region/region.dtd (%chrome/global-region/region.dtd) + locale/@AB_CD@/global-region/region.properties (%chrome/global-region/region.properties) diff --git a/toolkit/mozapps/downloads/content/download.xml b/toolkit/mozapps/downloads/content/download.xml index c8a6278ddb6b..b60577bcaffd 100644 --- a/toolkit/mozapps/downloads/content/download.xml +++ b/toolkit/mozapps/downloads/content/download.xml @@ -99,8 +99,12 @@ diff --git a/toolkit/mozapps/downloads/content/downloads.js b/toolkit/mozapps/downloads/content/downloads.js index 1c5c17d62321..e741c8473ce5 100644 --- a/toolkit/mozapps/downloads/content/downloads.js +++ b/toolkit/mozapps/downloads/content/downloads.js @@ -53,7 +53,10 @@ const nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", var Cc = Components.classes; var Ci = Components.interfaces; -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +let Cu = Components.utils; +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/DownloadUtils.jsm"); +Cu.import("resource://gre/modules/PluralForm.jsm"); const nsIDM = Ci.nsIDownloadManager; @@ -78,28 +81,18 @@ var gUserInteracted = false; // bundle on startup. let gStr = { paused: "paused", - statusFormat: "statusFormat2", - transferSameUnits: "transferSameUnits", - transferDiffUnits: "transferDiffUnits", - transferNoTotal: "transferNoTotal", - timeMinutesLeft: "timeMinutesLeft", - timeSecondsLeft: "timeSecondsLeft", - timeFewSeconds: "timeFewSeconds", - timeUnknown: "timeUnknown", + cannotPause: "cannotPause", doneStatus: "doneStatus", doneSize: "doneSize", doneSizeUnknown: "doneSizeUnknown", - doneScheme: "doneScheme", - doneFileScheme: "doneFileScheme", stateFailed: "stateFailed", stateCanceled: "stateCanceled", stateBlocked: "stateBlocked", stateDirty: "stateDirty", yesterday: "yesterday", monthDate: "monthDate", - - units: ["bytes", "kilobyte", "megabyte", "gigabyte"], - + downloadsTitleFiles: "downloadsTitleFiles", + downloadsTitlePercent: "downloadsTitlePercent", fileExecutableSecurityWarningTitle: "fileExecutableSecurityWarningTitle", fileExecutableSecurityWarningDontAsk: "fileExecutableSecurityWarningDontAsk" }; @@ -107,7 +100,8 @@ let gStr = { // Create a getDisplayHost function for queries to use gDownloadManager.DBConnection.createFunction("getDisplayHost", 1, { QueryInterface: XPCOMUtils.generateQI([Ci.mozIStorageFunction]), - onFunctionCall: function(aArgs) getHost(aArgs.getUTF8String(0))[0] + onFunctionCall: function(aArgs) + DownloadUtils.getURIHost(aArgs.getUTF8String(0))[0] }); // The statement to query for downloads that are active or match the search @@ -338,47 +332,47 @@ var gLastComputedMean = -1; var gLastActiveDownloads = 0; function onUpdateProgress() { - if (gDownloadManager.activeDownloads == 0) { + let numActiveDownloads = gDownloadManager.activeDownloadCount; + + // Use the default title and reset "last" values if there's no downloads + if (numActiveDownloads == 0) { document.title = document.documentElement.getAttribute("statictitle"); gLastComputedMean = -1; + gLastActiveDownloads = 0; + return; } // Establish the mean transfer speed and amount downloaded. var mean = 0; var base = 0; - var numActiveDownloads = 0; var dls = gDownloadManager.activeDownloads; while (dls.hasMoreElements()) { - let dl = dls.getNext(); - dl.QueryInterface(Ci.nsIDownload); + let dl = dls.getNext().QueryInterface(Ci.nsIDownload); if (dl.percentComplete < 100 && dl.size > 0) { mean += dl.amountTransferred; base += dl.size; } - numActiveDownloads++; } - // we're not downloading anything at the moment, - // but we already downloaded something. - if (base == 0) { - mean = 100; - } else { + // Calculate the percent transferred, unless we don't have a total file size + let title = gStr.downloadsTitlePercent; + if (base == 0) + title = gStr.downloadsTitleFiles; + else mean = Math.floor((mean / base) * 100); - } // Update title of window if (mean != gLastComputedMean || gLastActiveDownloads != numActiveDownloads) { gLastComputedMean = mean; gLastActiveDownloads = numActiveDownloads; - let strings = document.getElementById("downloadStrings"); - if (numActiveDownloads > 1) { - document.title = strings.getFormattedString("downloadsTitleMultiple", - [mean, numActiveDownloads]); - } else { - document.title = strings.getFormattedString("downloadsTitle", [mean]); - } + // Get the correct plural form and insert number of downloads and percent + title = PluralForm.get(numActiveDownloads, title); + title = replaceInsert(title, 1, numActiveDownloads); + title = replaceInsert(title, 2, mean); + + document.title = title; } } @@ -613,6 +607,7 @@ var gDownloadViewController = { } let dl = aItem; + let download = null; // used for getting an nsIDownload object switch (aCommand) { case "cmd_cancel": @@ -621,11 +616,14 @@ var gDownloadViewController = { let file = getLocalFileFromNativePathOrUrl(dl.getAttribute("file")); return dl.openable && file.exists(); case "cmd_pause": - return dl.inProgress && !dl.paused; + download = gDownloadManager.getDownload(dl.getAttribute("dlid")); + return dl.inProgress && !dl.paused && download.resumable; case "cmd_pauseResume": - return dl.inProgress || dl.paused; + download = gDownloadManager.getDownload(dl.getAttribute("dlid")); + return (dl.inProgress || dl.paused) && download.resumable; case "cmd_resume": - return dl.paused; + download = gDownloadManager.getDownload(dl.getAttribute("dlid")); + return dl.paused && download.resumable; case "cmd_openReferrer": return dl.hasAttribute("referrer"); case "cmd_removeFromList": @@ -658,10 +656,10 @@ var gDownloadViewController = { pauseDownload(aSelectedItem); }, cmd_pauseResume: function(aSelectedItem) { - if (aSelectedItem.inProgress) - this.commands.cmd_pause(aSelectedItem); + if (aSelectedItem.paused) + this.cmd_resume(aSelectedItem); else - this.commands.cmd_resume(aSelectedItem); + this.cmd_pause(aSelectedItem); }, cmd_removeFromList: function(aSelectedItem) { removeDownload(aSelectedItem); @@ -784,6 +782,12 @@ function updateButtons(aItem) let cmd = buttons[i].getAttribute("cmd"); let enabled = gDownloadViewController.isCommandEnabled(cmd, aItem); buttons[i].disabled = !enabled; + + if ("cmd_pause" == cmd && !enabled) { + // We need to add the tooltip indicating that the download cannot be + // paused now. + buttons[i].setAttribute("tooltiptext", gStr.cannotPause); + } } } @@ -803,94 +807,45 @@ function updateStatus(aItem, aDownload) { let state = Number(aItem.getAttribute("state")); switch (state) { case nsIDM.DOWNLOAD_PAUSED: - case nsIDM.DOWNLOAD_DOWNLOADING: + { let currBytes = Number(aItem.getAttribute("currBytes")); let maxBytes = Number(aItem.getAttribute("maxBytes")); - // Update the bytes transferred and bytes total - let ([progress, progressUnits] = convertByteUnits(currBytes), - [total, totalUnits] = convertByteUnits(maxBytes), - transfer) { - if (total < 0) - transfer = gStr.transferNoTotal; - else if (progressUnits == totalUnits) - transfer = gStr.transferSameUnits; - else - transfer = gStr.transferDiffUnits; - - transfer = replaceInsert(transfer, 1, progress); - transfer = replaceInsert(transfer, 2, progressUnits); - transfer = replaceInsert(transfer, 3, total); - transfer = replaceInsert(transfer, 4, totalUnits); - - if (state == nsIDM.DOWNLOAD_PAUSED) { - status = replaceInsert(gStr.paused, 1, transfer); - - // don't need to process any more for PAUSED - break; - } - - // Insert 1 is the download progress - status = replaceInsert(gStr.statusFormat, 1, transfer); - } - - // if we don't have an active download, assume 0 bytes/sec - let speed = aDownload ? aDownload.speed : 0; - - // Update the download rate - let ([rate, unit] = convertByteUnits(speed)) { - // Insert 2 is the download rate - status = replaceInsert(status, 2, rate); - // Insert 3 is the |unit|/sec - status = replaceInsert(status, 3, unit); - } - - // Update time remaining. - let (remain) { - if ((speed > 0) && (maxBytes > 0)) { - let seconds = Math.ceil((maxBytes - currBytes) / speed); - let lastSec = Number(aItem.getAttribute("lastSeconds")); - - // Reuse the last seconds if the new one is only slighty longer - // This avoids jittering seconds, e.g., 41 40 38 40 -> 41 40 38 38 - // However, large changes are shown, e.g., 41 38 49 -> 41 38 49 - let (diff = seconds - lastSec) { - if (diff > 0 && diff <= 10) - seconds = lastSec; - else - aItem.setAttribute("lastSeconds", seconds); - } - - // Be friendly in the last few seconds - if (seconds <= 3) - remain = gStr.timeFewSeconds; - // Show 2 digit seconds starting at 60; otherwise use minutes - else if (seconds <= 60) - remain = replaceInsert(gStr.timeSecondsLeft, 1, seconds); - else - remain = replaceInsert(gStr.timeMinutesLeft, 1, - Math.ceil(seconds / 60)); - } else { - remain = gStr.timeUnknown; - } - - // Insert 4 is the time remaining - status = replaceInsert(status, 4, remain); - } + let transfer = DownloadUtils.getTransferTotal(currBytes, maxBytes); + status = replaceInsert(gStr.paused, 1, transfer); break; + } + case nsIDM.DOWNLOAD_DOWNLOADING: + { + let currBytes = Number(aItem.getAttribute("currBytes")); + let maxBytes = Number(aItem.getAttribute("maxBytes")); + // If we don't have an active download, assume 0 bytes/sec + let speed = aDownload ? aDownload.speed : 0; + let lastSec = Number(aItem.getAttribute("lastSeconds")); + + let newLast; + [status, newLast] = + DownloadUtils.getDownloadStatus(currBytes, maxBytes, speed, lastSec); + + // Update lastSeconds to be the new value + aItem.setAttribute("lastSeconds", newLast); + + break; + } case nsIDM.DOWNLOAD_FINISHED: case nsIDM.DOWNLOAD_FAILED: case nsIDM.DOWNLOAD_CANCELED: case nsIDM.DOWNLOAD_BLOCKED: case nsIDM.DOWNLOAD_DIRTY: + { let (stateSize = {}) { stateSize[nsIDM.DOWNLOAD_FINISHED] = function() { // Display the file size, but show "Unknown" for negative sizes let fileSize = Number(aItem.getAttribute("maxBytes")); let sizeText = gStr.doneSizeUnknown; if (fileSize >= 0) { - let [size, unit] = convertByteUnits(fileSize); + let [size, unit] = DownloadUtils.convertByteUnits(fileSize); sizeText = replaceInsert(gStr.doneSize, 1, size); sizeText = replaceInsert(sizeText, 2, unit); } @@ -905,13 +860,15 @@ function updateStatus(aItem, aDownload) { status = replaceInsert(gStr.doneStatus, 1, stateSize[state]()); } - let [displayHost, fullHost] = getHost(getReferrerOrSource(aItem)); + let [displayHost, fullHost] = + DownloadUtils.getURIHost(getReferrerOrSource(aItem)); // Insert 2 is the eTLD + 1 or other variations of the host status = replaceInsert(status, 2, displayHost); // Set the tooltip to be the full host statusTip = fullHost; break; + } } aItem.setAttribute("status", status); @@ -978,92 +935,16 @@ function updateTime(aItem) } /** - * Converts a number of bytes to the appropriate unit that results in a - * number that needs fewer than 4 digits + * Helper function to replace a placeholder string with a real string * - * @return a pair: [new value with 3 sig. figs., its unit] + * @param aText + * Source text containing placeholder (e.g., #1) + * @param aIndex + * Index number of placeholder to replace + * @param aValue + * New string to put in place of placeholder + * @return The string with placeholder replaced with the new string */ -function convertByteUnits(aBytes) -{ - let unitIndex = 0; - - // convert to next unit if it needs 4 digits (after rounding), but only if - // we know the name of the next unit - while ((aBytes >= 999.5) && (unitIndex < gStr.units.length - 1)) { - aBytes /= 1024; - unitIndex++; - } - - // Get rid of insignificant bits by truncating to 1 or 0 decimal points - // 0 -> 0; 1.2 -> 1.2; 12.3 -> 12.3; 123.4 -> 123; 234.5 -> 235 - aBytes = aBytes.toFixed((aBytes > 0) && (aBytes < 100) ? 1 : 0); - - return [aBytes, gStr.units[unitIndex]]; -} - -/** - * Get the appropriate display host string for a URI string depending on if the - * URI has an eTLD + 1, is an IP address, a local file, or other protocol - * - * @param aURIString - * The URI string to try getting an eTLD + 1, etc. - * @return a pair: [display host for the provided URI string, full host name] - */ -function getHost(aURIString) -{ - let ioService = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - let eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"]. - getService(Ci.nsIEffectiveTLDService); - let idnService = Cc["@mozilla.org/network/idn-service;1"]. - getService(Ci.nsIIDNService); - - // Get a URI that knows about its components - let uri = ioService.newURI(aURIString, null, null); - - // Get the inner-most uri for schemes like jar: - if (uri instanceof Ci.nsINestedURI) - uri = uri.innermostURI; - - let fullHost; - try { - // Get the full host name; some special URIs fail (data: jar:) - fullHost = uri.host; - } catch (e) { - fullHost = ""; - } - - let displayHost; - try { - // This might fail if it's an IP address or doesn't have more than 1 part - let baseDomain = eTLDService.getBaseDomain(uri); - - // Convert base domain for display; ignore the isAscii out param - displayHost = idnService.convertToDisplayIDN(baseDomain, {}); - } catch (e) { - // Default to the host name - displayHost = fullHost; - } - - // Check if we need to show something else for the host - if (uri.scheme == "file") { - // Display special text for file protocol - displayHost = gStr.doneFileScheme; - fullHost = displayHost; - } else if (displayHost.length == 0) { - // Got nothing; show the scheme (data: about: moz-icon:) - displayHost = replaceInsert(gStr.doneScheme, 1, uri.scheme); - fullHost = displayHost; - } else if (uri.port != -1) { - // Tack on the port if it's not the default port - let port = ":" + uri.port; - displayHost += port; - fullHost += port; - } - - return [displayHost, fullHost]; -} - function replaceInsert(aText, aIndex, aValue) { return aText.replace("#" + aIndex, aValue); diff --git a/toolkit/mozapps/downloads/content/downloads.xul b/toolkit/mozapps/downloads/content/downloads.xul index 2b6dc5f8fa43..c656f612a355 100644 --- a/toolkit/mozapps/downloads/content/downloads.xul +++ b/toolkit/mozapps/downloads/content/downloads.xul @@ -60,7 +60,7 @@ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="downloadManager" windowtype="Download:Manager" orient="vertical" title="&downloads.title;" statictitle="&downloads.title;" - width="&window.width;" height="&window.height;" screenX="10" screenY="10" + width="&window.width2;" height="&window.height;" screenX="10" screenY="10" persist="width height screenX screenY sizemode" onload="Startup();" onunload="Shutdown();" onclose="return closeWindow(false);"> @@ -84,7 +84,7 @@ - + #ifdef XP_MACOSX @@ -123,8 +123,8 @@ cmd="cmd_open"/> . + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 ***** */ + +EXPORTED_SYMBOLS = [ "DownloadUtils" ]; + +/** + * This module provides the DownloadUtils object which contains useful methods + * for downloads such as displaying file sizes, transfer times, and download + * locations. + * + * List of methods: + * + * [string status, double newLast] + * getDownloadStatus(int aCurrBytes, [optional] int aMaxBytes, + * [optional] double aSpeed, [optional] double aLastSec) + * + * string progress + * getTransferTotal(int aCurrBytes, [optional] int aMaxBytes) + * + * [string timeLeft, double newLast] + * getTimeLeft(double aSeconds, [optional] double aLastSec) + * + * [string displayHost, string fullHost] + * getURIHost(string aURIString) + * + * [double convertedBytes, string units] + * convertByteUnits(int aBytes) + * + * [int time, string units, int subTime, string subUnits] + * convertTimeUnits(double aSecs) + */ + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils +Cu.import("resource://gre/modules/PluralForm.jsm"); + +const kDownloadProperties = + "chrome://mozapps/locale/downloads/downloads.properties"; + +// These strings will be converted to the corresponding ones from the string +// bundle on load +let gStr = { + statusFormat: "statusFormat2", + transferSameUnits: "transferSameUnits", + transferDiffUnits: "transferDiffUnits", + transferNoTotal: "transferNoTotal", + timePair: "timePair", + timeLeftSingle: "timeLeftSingle", + timeLeftDouble: "timeLeftDouble", + timeFewSeconds: "timeFewSeconds", + timeUnknown: "timeUnknown", + doneScheme: "doneScheme", + doneFileScheme: "doneFileScheme", + units: ["bytes", "kilobyte", "megabyte", "gigabyte"], + // Update timeSize in convertTimeUnits if changing the length of this array + timeUnits: ["seconds", "minutes", "hours", "days"], +}; + +// Convert strings to those in the string bundle +let (getStr = Cc["@mozilla.org/intl/stringbundle;1"]. + getService(Ci.nsIStringBundleService). + createBundle(kDownloadProperties). + GetStringFromName) { + for (let [name, value] in Iterator(gStr)) { + try { + gStr[name] = typeof value == "string" ? getStr(value) : value.map(getStr); + } catch (e) { + log(["Couldn't get string '", name, "' from property '", value, "'"]); + } + } +} + +let DownloadUtils = { + /** + * Generate a full status string for a download given its current progress, + * total size, speed, last time remaining + * + * @param aCurrBytes + * Number of bytes transferred so far + * @param [optional] aMaxBytes + * Total number of bytes or -1 for unknown + * @param [optional] aSpeed + * Current transfer rate in bytes/sec or -1 for unknown + * @param [optional] aLastSec + * Last time remaining in seconds or Infinity for unknown + * @return A pair: [download status text, new value of "last seconds"] + */ + getDownloadStatus: function(aCurrBytes, aMaxBytes, aSpeed, aLastSec) + { + if (isNil(aMaxBytes)) + aMaxBytes = -1; + if (isNil(aSpeed)) + aSpeed = -1; + if (isNil(aLastSec)) + aLastSec = Infinity; + + // Calculate the time remaining if we have valid values + let seconds = (aSpeed > 0) && (aMaxBytes > 0) ? + (aMaxBytes - aCurrBytes) / aSpeed : -1; + + // Update the bytes transferred and bytes total + let status; + let (transfer = DownloadUtils.getTransferTotal(aCurrBytes, aMaxBytes)) { + // Insert 1 is the download progress + status = replaceInsert(gStr.statusFormat, 1, transfer); + } + + // Update the download rate + let ([rate, unit] = DownloadUtils.convertByteUnits(aSpeed)) { + // Insert 2 is the download rate + status = replaceInsert(status, 2, rate); + // Insert 3 is the |unit|/sec + status = replaceInsert(status, 3, unit); + } + + // Update time remaining + let ([timeLeft, newLast] = DownloadUtils.getTimeLeft(seconds, aLastSec)) { + // Insert 4 is the time remaining + status = replaceInsert(status, 4, timeLeft); + + return [status, newLast]; + } + }, + + /** + * Generate the transfer progress string to show the current and total byte + * size. Byte units will be as large as possible and the same units for + * current and max will be supressed for the former. + * + * @param aCurrBytes + * Number of bytes transferred so far + * @param [optional] aMaxBytes + * Total number of bytes or -1 for unknown + * @return The transfer progress text + */ + getTransferTotal: function(aCurrBytes, aMaxBytes) + { + if (isNil(aMaxBytes)) + aMaxBytes = -1; + + let [progress, progressUnits] = DownloadUtils.convertByteUnits(aCurrBytes); + let [total, totalUnits] = DownloadUtils.convertByteUnits(aMaxBytes); + + // Figure out which byte progress string to display + let transfer; + if (total < 0) + transfer = gStr.transferNoTotal; + else if (progressUnits == totalUnits) + transfer = gStr.transferSameUnits; + else + transfer = gStr.transferDiffUnits; + + transfer = replaceInsert(transfer, 1, progress); + transfer = replaceInsert(transfer, 2, progressUnits); + transfer = replaceInsert(transfer, 3, total); + transfer = replaceInsert(transfer, 4, totalUnits); + + return transfer; + }, + + /** + * Generate a "time left" string given an estimate on the time left and the + * last time. The extra time is used to give a better estimate on the time to + * show. Both the time values are doubles instead of integers to help get + * sub-second accuracy for current and future estimates. + * + * @param aSeconds + * Current estimate on number of seconds left for the download + * @param [optional] aLastSec + * Last time remaining in seconds or Infinity for unknown + * @return A pair: [time left text, new value of "last seconds"] + */ + getTimeLeft: function(aSeconds, aLastSec) + { + if (isNil(aLastSec)) + aLastSec = Infinity; + + if (aSeconds < 0) + return [gStr.timeUnknown, aLastSec]; + + // Apply smoothing only if the new time isn't a huge change -- e.g., if the + // new time is more than half the previous time; this is useful for + // downloads that start/resume slowly + if (aSeconds > aLastSec / 2) { + // Apply hysteresis to favor downward over upward swings + // 30% of down and 10% of up (exponential smoothing) + let (diff = aSeconds - aLastSec) { + aSeconds = aLastSec + (diff < 0 ? .3 : .1) * diff; + } + + // If the new time is similar, reuse something close to the last seconds, + // but subtract a little to provide forward progress + let diff = aSeconds - aLastSec; + let diffPct = diff / aLastSec * 100; + if (Math.abs(diff) < 5 || Math.abs(diffPct) < 5) + aSeconds = aLastSec - (diff < 0 ? .4 : .2); + } + + // Decide what text to show for the time + let timeLeft; + if (aSeconds < 4) { + // Be friendly in the last few seconds + timeLeft = gStr.timeFewSeconds; + } else { + // Convert the seconds into its two largest units to display + let [time1, unit1, time2, unit2] = + DownloadUtils.convertTimeUnits(aSeconds); + + let pair1 = replaceInsert(gStr.timePair, 1, time1); + pair1 = replaceInsert(pair1, 2, unit1); + let pair2 = replaceInsert(gStr.timePair, 1, time2); + pair2 = replaceInsert(pair2, 2, unit2); + + // Only show minutes for under 1 hour or the second pair is 0 + if (aSeconds < 3600 || time2 == 0) { + timeLeft = replaceInsert(gStr.timeLeftSingle, 1, pair1); + } else { + // We've got 2 pairs of times to display + timeLeft = replaceInsert(gStr.timeLeftDouble, 1, pair1); + timeLeft = replaceInsert(timeLeft, 2, pair2); + } + } + + return [timeLeft, aSeconds]; + }, + + /** + * Get the appropriate display host string for a URI string depending on if + * the URI has an eTLD + 1, is an IP address, a local file, or other protocol + * + * @param aURIString + * The URI string to try getting an eTLD + 1, etc. + * @return A pair: [display host for the URI string, full host name] + */ + getURIHost: function(aURIString) + { + let ioService = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + let eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"]. + getService(Ci.nsIEffectiveTLDService); + let idnService = Cc["@mozilla.org/network/idn-service;1"]. + getService(Ci.nsIIDNService); + + // Get a URI that knows about its components + let uri = ioService.newURI(aURIString, null, null); + + // Get the inner-most uri for schemes like jar: + if (uri instanceof Ci.nsINestedURI) + uri = uri.innermostURI; + + let fullHost; + try { + // Get the full host name; some special URIs fail (data: jar:) + fullHost = uri.host; + } catch (e) { + fullHost = ""; + } + + let displayHost; + try { + // This might fail if it's an IP address or doesn't have more than 1 part + let baseDomain = eTLDService.getBaseDomain(uri); + + // Convert base domain for display; ignore the isAscii out param + displayHost = idnService.convertToDisplayIDN(baseDomain, {}); + } catch (e) { + // Default to the host name + displayHost = fullHost; + } + + // Check if we need to show something else for the host + if (uri.scheme == "file") { + // Display special text for file protocol + displayHost = gStr.doneFileScheme; + fullHost = displayHost; + } else if (displayHost.length == 0) { + // Got nothing; show the scheme (data: about: moz-icon:) + displayHost = replaceInsert(gStr.doneScheme, 1, uri.scheme); + fullHost = displayHost; + } else if (uri.port != -1) { + // Tack on the port if it's not the default port + let port = ":" + uri.port; + displayHost += port; + fullHost += port; + } + + return [displayHost, fullHost]; + }, + + /** + * Converts a number of bytes to the appropriate unit that results in a + * number that needs fewer than 4 digits + * + * @param aBytes + * Number of bytes to convert + * @return A pair: [new value with 3 sig. figs., its unit] + */ + convertByteUnits: function(aBytes) + { + let unitIndex = 0; + + // Convert to next unit if it needs 4 digits (after rounding), but only if + // we know the name of the next unit + while ((aBytes >= 999.5) && (unitIndex < gStr.units.length - 1)) { + aBytes /= 1024; + unitIndex++; + } + + // Get rid of insignificant bits by truncating to 1 or 0 decimal points + // 0 -> 0; 1.2 -> 1.2; 12.3 -> 12.3; 123.4 -> 123; 234.5 -> 235 + aBytes = aBytes.toFixed((aBytes > 0) && (aBytes < 100) ? 1 : 0); + + return [aBytes, gStr.units[unitIndex]]; + }, + + /** + * Converts a number of seconds to the two largest units. Time values are + * whole numbers, and units have the correct plural/singular form. + * + * @param aSecs + * Seconds to convert into the appropriate 2 units + * @return 4-item array [first value, its unit, second value, its unit] + */ + convertTimeUnits: function(aSecs) + { + // These are the maximum values for seconds, minutes, hours corresponding + // with gStr.timeUnits without the last item + let timeSize = [60, 60, 24]; + + let time = aSecs; + let scale = 1; + let unitIndex = 0; + + // Keep converting to the next unit while we have units left and the + // current one isn't the largest unit possible + while ((unitIndex < timeSize.length) && (time >= timeSize[unitIndex])) { + time /= timeSize[unitIndex]; + scale *= timeSize[unitIndex]; + unitIndex++; + } + + let value = convertTimeUnitsValue(time); + let units = convertTimeUnitsUnits(value, unitIndex); + + let extra = aSecs - value * scale; + let nextIndex = unitIndex - 1; + + // Convert the extra time to the next largest unit + for (let index = 0; index < nextIndex; index++) + extra /= timeSize[index]; + + let value2 = convertTimeUnitsValue(extra); + let units2 = convertTimeUnitsUnits(value2, nextIndex); + + return [value, units, value2, units2]; + }, +}; + +/** + * Private helper for convertTimeUnits that gets the display value of a time + * + * @param aTime + * Time value for display + * @return An integer value for the time rounded down + */ +function convertTimeUnitsValue(aTime) +{ + return Math.floor(aTime); +} + +/** + * Private helper for convertTimeUnits that gets the display units of a time + * + * @param aTime + * Time value for display + * @param aIndex + * Index into gStr.timeUnits for the appropriate unit + * @return The appropriate plural form of the unit for the time + */ +function convertTimeUnitsUnits(aTime, aIndex) +{ + // Negative index would be an invalid unit, so just give empty + if (aIndex < 0) + return ""; + + return PluralForm.get(aTime, gStr.timeUnits[aIndex]); +} + +/** + * Private helper function to replace a placeholder string with a real string + * + * @param aText + * Source text containing placeholder (e.g., #1) + * @param aIndex + * Index number of placeholder to replace + * @param aValue + * New string to put in place of placeholder + * @return The string with placeholder replaced with the new string + */ +function replaceInsert(aText, aIndex, aValue) +{ + return aText.replace("#" + aIndex, aValue); +} + +/** + * Private helper function to determine if an argument is null or undefined + * + * @param aArg + * The argument to check for nullness or undefinedness + * @return true if null or undefined, false otherwise + */ +function isNil(aArg) +{ + return (aArg == null) || (aArg == undefined); +} + +/** + * Private helper function to log errors to the error console and command line + * + * @param aMsg + * Error message to log or an array of strings to concat + */ +function log(aMsg) +{ + let msg = "DownloadUtils.jsm: " + (aMsg.join ? aMsg.join("") : aMsg); + Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService). + logStringMessage(msg); + dump(msg + "\n"); +} diff --git a/toolkit/mozapps/downloads/src/Makefile.in b/toolkit/mozapps/downloads/src/Makefile.in index bf0d80f2d804..2d0e944e68e1 100644 --- a/toolkit/mozapps/downloads/src/Makefile.in +++ b/toolkit/mozapps/downloads/src/Makefile.in @@ -47,6 +47,10 @@ MODULE = helperAppDlg EXTRA_COMPONENTS = nsHelperAppDlg.js GARBAGE += nsHelperAppDlg.js +EXTRA_JS_MODULES = \ + DownloadUtils.jsm \ + $(NULL) + include $(topsrcdir)/config/rules.mk nsHelperAppDlg.js: nsHelperAppDlg.js.in diff --git a/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in b/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in index 63fc481fbd3c..660695d40a40 100644 --- a/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in +++ b/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in @@ -710,13 +710,7 @@ nsUnknownContentTypeDialog.prototype = { } } - // otherHandler is always disabled on Mac -#ifdef XP_MACOSX - otherHandler.hidden = true; - otherHandler.nextSibling.hidden = otherHandler.nextSibling.nextSibling.hidden = true; -#else otherHandler.nextSibling.hidden = otherHandler.nextSibling.nextSibling.hidden = false; -#endif this.updateOKButton(); }, diff --git a/toolkit/mozapps/downloads/tests/browser/Makefile.in b/toolkit/mozapps/downloads/tests/browser/Makefile.in index da50e7203eed..2e3ca52d575c 100644 --- a/toolkit/mozapps/downloads/tests/browser/Makefile.in +++ b/toolkit/mozapps/downloads/tests/browser/Makefile.in @@ -49,6 +49,8 @@ _BROWSER_FILES = \ browser_basic_functionality.js \ browser_bug_411172.js \ browser_bug_394039.js \ + browser_bug_410289.js \ + browser_bug_413985.js \ $(NULL) ifneq (,$(filter cocoa, $(MOZ_WIDGET_TOOLKIT))) diff --git a/toolkit/mozapps/downloads/tests/browser/browser_bug_410289.js b/toolkit/mozapps/downloads/tests/browser/browser_bug_410289.js new file mode 100644 index 000000000000..3d8c8dd47948 --- /dev/null +++ b/toolkit/mozapps/downloads/tests/browser/browser_bug_410289.js @@ -0,0 +1,151 @@ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Shawn Wilsher (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 ***** */ + +var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); +var dmFile = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile); +dmFile.append("dmuitest.file"); +dmFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); +var gTestPath = ios.newFileURI(dmFile).spec; + +const DownloadData = [ + { name: "Firefox 2.0.0.11.dmg", + source: "http://mozilla-mirror.naist.jp//firefox/releases/2.0.0.11/mac/en-US/Firefox%202.0.0.11.dmg", + target: gTestPath, + startTime: 1200185939538521, + endTime: 1200185939538521, + entityID: "%22216c12-1116bd8-440070d5d2700%22/17918936/Thu, 29 Nov 2007 01:15:40 GMT", + state: Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING, + currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0 }, + { name: "Firefox 2.0.0.11.dmg", + source: "http://mozilla-mirror.naist.jp//firefox/releases/2.0.0.11/mac/en-US/Firefox%202.0.0.11.dmg", + target: gTestPath, + startTime: 1200185939538520, + endTime: 1200185939538520, + entityID: "", + state: Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING, + currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0 } +]; + +function test_pauseButtonCorrect(aWin) +{ + // This also tests the ordering of the display + var doc = aWin.document; + + var dm = Cc["@mozilla.org/download-manager;1"]. + getService(Ci.nsIDownloadManager); + + var richlistbox = doc.getElementById("downloadView"); + for (var i = 0; i < DownloadData.length; i++) { + var dl = richlistbox.children[i]; + var buttons = dl.buttons; + for (var j = 0; j < buttons.length; j++) { + var button = buttons[j]; + if ("cmd_pause" == button.getAttribute("cmd")) { + var id = dl.getAttribute("dlid"); + + // check if it should be disabled or not + var resumable = dm.getDownload(id).resumable; + is(DownloadData[i].entityID ? true : false, resumable, + "Pause button is properly disabled"); + + // also check if tooltip text was updated + if (!resumable) { + var sb = doc.getElementById("downloadStrings"); + is(button.getAttribute("tooltiptext"), sb.getString("cannotPause"), + "Pause button has proper text"); + } + } + } + } +} + +var testFuncs = [ + test_pauseButtonCorrect +]; + +function test() +{ + var dm = Cc["@mozilla.org/download-manager;1"]. + getService(Ci.nsIDownloadManager); + var db = dm.DBConnection; + + // First, we populate the database with some fake data + db.executeSimpleSQL("DELETE FROM moz_downloads"); + var rawStmt = db.createStatement( + "INSERT INTO moz_downloads (name, source, target, startTime, endTime, " + + "state, currBytes, maxBytes, preferredAction, autoResume, entityID) " + + "VALUES (:name, :source, :target, :startTime, :endTime, :state, " + + ":currBytes, :maxBytes, :preferredAction, :autoResume, :entityID)"); + var stmt = Cc["@mozilla.org/storage/statement-wrapper;1"]. + createInstance(Ci.mozIStorageStatementWrapper) + stmt.initialize(rawStmt); + for each (var dl in DownloadData) { + for (var prop in dl) + stmt.params[prop] = dl[prop]; + + stmt.execute(); + } + stmt.statement.finalize(); + + // 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"); + if (win) + win.close(); + + // OK, now that all the data is in, let's pull up the UI + Cc["@mozilla.org/download-manager-ui;1"]. + getService(Ci.nsIDownloadManagerUI).show(); + + // 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"); + + // Now we can run our tests + for each (var t in testFuncs) + t(win); + + win.close(); + finish(); + } + + waitForExplicitFinish(); + // We also need to allow enough time for the DM to build up the whole list + window.setTimeout(finishUp, 2000); +} diff --git a/toolkit/mozapps/downloads/tests/browser/browser_bug_411172.js b/toolkit/mozapps/downloads/tests/browser/browser_bug_411172.js index f447722bc984..f42e8804d226 100644 --- a/toolkit/mozapps/downloads/tests/browser/browser_bug_411172.js +++ b/toolkit/mozapps/downloads/tests/browser/browser_bug_411172.js @@ -80,23 +80,6 @@ const DownloadData = [ currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0 } ]; -// XXX remove me when Bug 411521 is fixed -function synthesizeKey(aKey, aWin) -{ - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - - var utils = aWin.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - if (utils) { - var charCode = 0; - var keyCode = Ci.nsIDOMKeyEvent[aKey]; - var modifiers = 0; - utils.sendKeyEvent("keydown", keyCode, charCode, modifiers); - utils.sendKeyEvent("keypress", keyCode, charCode, modifiers); - utils.sendKeyEvent("keyup", keyCode, charCode, modifiers); - } -} - function test_deleteKeyRemoves(aWin) { // This also tests the ordering of the display @@ -114,7 +97,7 @@ function test_deleteKeyRemoves(aWin) var len = DownloadData.length; for (var i = 0; i < len; i++) { - synthesizeKey("DOM_VK_DELETE", aWin); + EventUtils.synthesizeKey("VK_DELETE", {}, aWin); stmt.executeStep(); is(stmt.getInt32(0), len - (i + 1), diff --git a/toolkit/mozapps/downloads/tests/browser/browser_bug_411172_mac.js b/toolkit/mozapps/downloads/tests/browser/browser_bug_411172_mac.js index efab68465dcf..b4795b67f223 100644 --- a/toolkit/mozapps/downloads/tests/browser/browser_bug_411172_mac.js +++ b/toolkit/mozapps/downloads/tests/browser/browser_bug_411172_mac.js @@ -80,23 +80,6 @@ const DownloadData = [ currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0 } ]; -// XXX remove me when Bug 411521 is fixed -function synthesizeKey(aKey, aWin) -{ - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - - var utils = aWin.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - if (utils) { - var charCode = 0; - var keyCode = Ci.nsIDOMKeyEvent[aKey]; - var modifiers = 0; - utils.sendKeyEvent("keydown", keyCode, charCode, modifiers); - utils.sendKeyEvent("keypress", keyCode, charCode, modifiers); - utils.sendKeyEvent("keyup", keyCode, charCode, modifiers); - } -} - function test_backspaceKeyRemoves(aWin) { // This also tests the ordering of the display @@ -114,7 +97,7 @@ function test_backspaceKeyRemoves(aWin) var len = DownloadData.length; for (var i = 0; i < len; i++) { - synthesizeKey("DOM_VK_BACK_SPACE", aWin); + EventUtils.synthesizeKey("VK_BACK_SPACE", {}, aWin); stmt.executeStep(); is(stmt.getInt32(0), len - (i + 1), diff --git a/toolkit/mozapps/downloads/tests/browser/browser_bug_413985.js b/toolkit/mozapps/downloads/tests/browser/browser_bug_413985.js new file mode 100644 index 000000000000..df24947e3414 --- /dev/null +++ b/toolkit/mozapps/downloads/tests/browser/browser_bug_413985.js @@ -0,0 +1,153 @@ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Shawn Wilsher (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 ***** */ + +function bug413985obs(aWin) +{ + this.mWin = aWin; + this.wasPaused = false; + this.wasResumed = false; +} +bug413985obs.prototype = { + observe: function(aSubject, aTopic, aData) + { + if ("timer-callback" == aTopic) { + // dispatch a space keypress to resume the download + EventUtils.synthesizeKey(" ", {}, this.mWin); + } + }, + + onDownloadStateChange: function(aState, aDownload) + { + if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING && + !this.wasPaused) { + this.wasPaused = true; + // dispatch a space keypress to pause the download + EventUtils.synthesizeKey(" ", {}, this.mWin); + } + + if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_PAUSED && + !this.wasResumed) { + this.wasResumed = true; + // We have to do this on a timer so other JS stuff that handles the UI + // can actually catch up to us... + var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.init(this, 0, Ci.nsITimer.TYPE_ONE_SHOT); + } + + if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED) { + ok(this.wasPaused && this.wasResumed, + "The download was paused, and then resumed to completion"); + aDownload.targetFile.remove(false); + + var dm = Cc["@mozilla.org/download-manager;1"]. + getService(Ci.nsIDownloadManager); + dm.removeListener(this); + + finish(); + } + }, + onStateChange: function(a, b, c, d, e) { }, + onProgressChange: function(a, b, c, d, e, f, g) { }, + onSecurityChange: function(a, b, c, d) { } +}; +function test() +{ + var dm = Cc["@mozilla.org/download-manager;1"]. + getService(Ci.nsIDownloadManager); + + function addDownload() { + function createURI(aObj) { + var ios = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) : + ios.newURI(aObj, null, null); + } + + const nsIWBP = Ci.nsIWebBrowserPersist; + var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] + .createInstance(Ci.nsIWebBrowserPersist); + persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES | + nsIWBP.PERSIST_FLAGS_BYPASS_CACHE | + nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; + + var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); + var destFile = dirSvc.get("ProfD", Ci.nsIFile); + destFile.append("download.result"); + if (destFile.exists()) + destFile.remove(false); + + var dl = dm.addDownload(Ci.nsIDownloadManager.DOWNLOAD_TYPE_DOWNLOAD, + createURI("http://example.com/httpd.js"), + createURI(destFile), null, null, + Math.round(Date.now() * 1000), null, persist); + + persist.progressListener = dl.QueryInterface(Ci.nsIWebProgressListener); + persist.saveURI(dl.source, null, null, null, null, dl.targetFile); + + return dl; + } + + // First, we clear out the database + dm.DBConnection.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"); + if (win) + win.close(); + + // OK, now that all the data is in, let's pull up the UI + Cc["@mozilla.org/download-manager-ui;1"]. + getService(Ci.nsIDownloadManagerUI).show(); + + // 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"); + + dm.addListener(new bug413985obs(win)); + + var dl = addDownload(); + // we need to focus the download as well + var doc = win.document; + doc.getElementById("downloadView").selectedIndex = 0; + } + + waitForExplicitFinish(); + window.setTimeout(finishUp, 500); +} diff --git a/toolkit/mozapps/extensions/content/eula.js b/toolkit/mozapps/extensions/content/eula.js new file mode 100644 index 000000000000..f665e9a08835 --- /dev/null +++ b/toolkit/mozapps/extensions/content/eula.js @@ -0,0 +1,43 @@ +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# ***** 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 The Extension Manager. +# +# The Initial Developer of the Original Code is mozilla.org +# Portions created by the Initial Developer are Copyright (C) 2008 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Dave Townsend +# +# 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 ***** + +function Startup() { + var bundle = document.getElementById("extensionsStrings"); + var label = document.createTextNode(bundle.getFormattedString("eulaHeader", [window.arguments[0].name])); + document.getElementById("heading").appendChild(label); + document.getElementById("eula").appendChild(document.createTextNode(window.arguments[0].text)); +} diff --git a/toolkit/mozapps/extensions/content/eula.xul b/toolkit/mozapps/extensions/content/eula.xul new file mode 100644 index 000000000000..163234b825d0 --- /dev/null +++ b/toolkit/mozapps/extensions/content/eula.xul @@ -0,0 +1,68 @@ + + +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# ***** 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 The Extension Manager. +# +# The Initial Developer of the Original Code is mozilla.org +# Portions created by the Initial Developer are Copyright (C) 2008 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Dave Townsend +# +# 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 ***** + + + + + +%brandDTD; + +%extensionsDTD; +]> + + + +