From 8927c9d22b3ff9b9bdadabde18b1eb808a4cec16 Mon Sep 17 00:00:00 2001 From: Marko Mikulicic Date: Tue, 8 Sep 2015 13:49:03 +0200 Subject: [PATCH] Merge dev branch code named Fossa as next stable Mongoose --- LICENSE | 10 +- README.md | 113 +- examples/Makefile | 9 +- examples/api_server/Makefile | 25 + examples/api_server/api_server.c | 104 + examples/api_server/db_plugin.h | 19 + examples/api_server/db_plugin_sqlite.c | 107 + examples/api_server/sqlite3.c | 140456 +++++++++++++++ examples/api_server/sqlite3.h | 7245 + examples/api_server/unit_test.sh | 35 + .../web_root}/index.html | 29 +- examples/arduino_restful_client/Makefile | 2 + examples/arduino_restful_client/README.md | 46 + .../arduino_restful_client.ino | 141 + examples/arduino_restful_server/Makefile | 2 + examples/arduino_restful_server/README.md | 45 + .../arduino_restful_server.ino | 133 + examples/array_vars/Makefile | 21 - examples/array_vars/array_vars.c | 45 - examples/big_upload/Makefile | 12 - examples/big_upload/big_upload.c | 84 - examples/captive_dns_server/Makefile | 4 + .../captive_dns_server/captive_dns_server.c | 82 + examples/coap_client/Makefile | 14 + examples/coap_client/coap_client.c | 72 + examples/coap_server/Makefile | 14 + examples/coap_server/coap_server.c | 73 + examples/cookie_authentication/Makefile | 12 - examples/cookie_authentication/cookie_auth.c | 97 - examples/cookie_authentication/login.html | 44 - examples/csharp/example.cs | 43 - examples/csharp/mongoose.cs | 68 - examples/digest_authentication/Makefile | 12 - examples/digest_authentication/digest_auth.c | 36 - examples/file_upload/Makefile | 20 - examples/file_upload/file_upload.c | 61 - examples/form_submit/Makefile | 12 - examples/form_submit/form_submit.c | 62 - examples/hello_world/Makefile | 21 - examples/hello_world/hello_world.c | 38 - examples/http_client/Makefile | 16 +- examples/http_client/http_client.c | 120 +- examples/json_rpc_server/Makefile | 14 + examples/json_rpc_server/json_rpc_server.c | 67 + examples/load_balancer/Dockerfile | 10 + examples/load_balancer/Makefile | 39 + examples/load_balancer/README.md | 44 + examples/load_balancer/load_balancer.c | 637 + examples/load_balancer/unit_test.sh | 21 + examples/mjpg_streamer/Makefile | 12 - examples/mjpg_streamer/mjpg_streamer.c | 105 - examples/mqtt_broker/Makefile | 14 + examples/mqtt_broker/mqtt_broker.c | 43 + examples/mqtt_client/Makefile | 14 + examples/mqtt_client/mqtt_client.c | 86 + examples/multi_threaded_server/Makefile | 12 - .../multi_threaded_server.c | 40 - .../multithreaded_restful_server/Makefile | 18 + .../multithreaded_restful_server.c | 52 + examples/netcat/Makefile | 14 + examples/netcat/nc.c | 140 + examples/proxy_server/Makefile | 13 - examples/proxy_server/proxy_server.c | 202 - .../proxy_web_root/app1/index.html | 23 - .../proxy_web_root/app2/index.html | 37 - .../proxy_server/proxy_web_root/index.html | 29 - examples/proxy_server/ssl_cert.pem | 50 - examples/publish_subscribe/Makefile | 14 + .../publish_subscribe/publish_subscribe.c | 112 + examples/raspberry_pi_mjpeg_led/Makefile | 18 + examples/raspberry_pi_mjpeg_led/README.adoc | 72 + examples/raspberry_pi_mjpeg_led/cloud_side.c | 143 + examples/raspberry_pi_mjpeg_led/device_side.c | 168 + examples/raspberry_pi_mjpeg_led/docs/arch.png | Bin 0 -> 40959 bytes .../raspberry_pi_mjpeg_led/web_root/doc.html | 533 + .../web_root/docs/arch.png | 1 + .../web_root/framework7.min.css | 15 + .../web_root/framework7.min.js | 18 + .../web_root/index.html | 108 + examples/restful_api/Makefile | 12 - examples/restful_api/restful_api.c | 51 - examples/restful_client/Makefile | 14 + examples/restful_client/restful_client.c | 56 + examples/restful_server/Makefile | 20 + .../index.html | 17 +- examples/restful_server/restful_server.c | 114 + examples/restful_server_s3/Makefile | 20 + examples/restful_server_s3/README.md | 31 + examples/restful_server_s3/index.html | 97 + .../restful_server_s3/restful_server_s3.c | 180 + examples/rules.mk | 13 + examples/send_file/Makefile | 21 - examples/send_file/send_file.c | 27 - examples/server_data_push/Makefile | 12 - examples/server_data_push/server_data_push.c | 99 - examples/settings_panel_for_a_device/Makefile | 11 + .../settings_panel.c | 81 + .../web_root/fossa.jpg | Bin 0 -> 16584 bytes .../web_root/index.shtml | 104 + .../web_root/jquery-1.11.3.min.js | 5 + examples/simplest_web_server/Makefile | 14 + .../simplest_web_server/simplest_web_server.c | 34 + examples/tcp_echo_server/Makefile | 14 + examples/tcp_echo_server/echo_server.c | 50 + examples/websocket_chat/index.html | 41 +- examples/websocket_chat/websocket_chat.c | 107 +- examples/websocket_echo_server/Makefile | 12 - examples/websocket_echo_server/index.html | 46 - .../websocket_echo_server.c | 61 - examples/websocket_ssl_proxy/Makefile | 27 - examples/websocket_ssl_proxy/certs/ws1_ca.pem | 49 - .../websocket_ssl_proxy/certs/ws1_client.pem | 45 - .../websocket_ssl_proxy/certs/ws1_server.pem | 45 - examples/websocket_ssl_proxy/certs/ws2_ca.pem | 49 - .../websocket_ssl_proxy/certs/ws2_client.pem | 45 - .../websocket_ssl_proxy/certs/ws2_server.pem | 45 - examples/websocket_ssl_proxy/net_skeleton.h | 253 - examples/websocket_ssl_proxy/ssl_wrapper.c | 123 - examples/websocket_ssl_proxy/ssl_wrapper.h | 34 - examples/websocket_ssl_proxy/ws_ssl.c | 182 - examples/websocket_ssl_proxy/ws_ssl.html | 50 - jni/Android.mk | 2 +- mongoose.c | 12537 +- mongoose.h | 2605 +- test/Makefile | 21 - test/unit_test.c | 533 - 126 files changed, 162049 insertions(+), 8502 deletions(-) create mode 100644 examples/api_server/Makefile create mode 100644 examples/api_server/api_server.c create mode 100644 examples/api_server/db_plugin.h create mode 100644 examples/api_server/db_plugin_sqlite.c create mode 100644 examples/api_server/sqlite3.c create mode 100644 examples/api_server/sqlite3.h create mode 100644 examples/api_server/unit_test.sh rename examples/{cookie_authentication => api_server/web_root}/index.html (52%) create mode 100644 examples/arduino_restful_client/Makefile create mode 100644 examples/arduino_restful_client/README.md create mode 100644 examples/arduino_restful_client/arduino_restful_client.ino create mode 100644 examples/arduino_restful_server/Makefile create mode 100644 examples/arduino_restful_server/README.md create mode 100644 examples/arduino_restful_server/arduino_restful_server.ino delete mode 100644 examples/array_vars/Makefile delete mode 100644 examples/array_vars/array_vars.c delete mode 100644 examples/big_upload/Makefile delete mode 100644 examples/big_upload/big_upload.c create mode 100644 examples/captive_dns_server/Makefile create mode 100644 examples/captive_dns_server/captive_dns_server.c create mode 100644 examples/coap_client/Makefile create mode 100644 examples/coap_client/coap_client.c create mode 100644 examples/coap_server/Makefile create mode 100644 examples/coap_server/coap_server.c delete mode 100644 examples/cookie_authentication/Makefile delete mode 100644 examples/cookie_authentication/cookie_auth.c delete mode 100644 examples/cookie_authentication/login.html delete mode 100644 examples/csharp/example.cs delete mode 100644 examples/csharp/mongoose.cs delete mode 100644 examples/digest_authentication/Makefile delete mode 100644 examples/digest_authentication/digest_auth.c delete mode 100644 examples/file_upload/Makefile delete mode 100644 examples/file_upload/file_upload.c delete mode 100644 examples/form_submit/Makefile delete mode 100644 examples/form_submit/form_submit.c delete mode 100644 examples/hello_world/Makefile delete mode 100644 examples/hello_world/hello_world.c create mode 100644 examples/json_rpc_server/Makefile create mode 100644 examples/json_rpc_server/json_rpc_server.c create mode 100644 examples/load_balancer/Dockerfile create mode 100644 examples/load_balancer/Makefile create mode 100644 examples/load_balancer/README.md create mode 100644 examples/load_balancer/load_balancer.c create mode 100644 examples/load_balancer/unit_test.sh delete mode 100644 examples/mjpg_streamer/Makefile delete mode 100644 examples/mjpg_streamer/mjpg_streamer.c create mode 100644 examples/mqtt_broker/Makefile create mode 100644 examples/mqtt_broker/mqtt_broker.c create mode 100644 examples/mqtt_client/Makefile create mode 100644 examples/mqtt_client/mqtt_client.c delete mode 100644 examples/multi_threaded_server/Makefile delete mode 100644 examples/multi_threaded_server/multi_threaded_server.c create mode 100644 examples/multithreaded_restful_server/Makefile create mode 100644 examples/multithreaded_restful_server/multithreaded_restful_server.c create mode 100644 examples/netcat/Makefile create mode 100644 examples/netcat/nc.c delete mode 100644 examples/proxy_server/Makefile delete mode 100644 examples/proxy_server/proxy_server.c delete mode 100644 examples/proxy_server/proxy_web_root/app1/index.html delete mode 100644 examples/proxy_server/proxy_web_root/app2/index.html delete mode 100644 examples/proxy_server/proxy_web_root/index.html delete mode 100644 examples/proxy_server/ssl_cert.pem create mode 100644 examples/publish_subscribe/Makefile create mode 100644 examples/publish_subscribe/publish_subscribe.c create mode 100644 examples/raspberry_pi_mjpeg_led/Makefile create mode 100644 examples/raspberry_pi_mjpeg_led/README.adoc create mode 100644 examples/raspberry_pi_mjpeg_led/cloud_side.c create mode 100644 examples/raspberry_pi_mjpeg_led/device_side.c create mode 100644 examples/raspberry_pi_mjpeg_led/docs/arch.png create mode 100644 examples/raspberry_pi_mjpeg_led/web_root/doc.html create mode 120000 examples/raspberry_pi_mjpeg_led/web_root/docs/arch.png create mode 100755 examples/raspberry_pi_mjpeg_led/web_root/framework7.min.css create mode 100755 examples/raspberry_pi_mjpeg_led/web_root/framework7.min.js create mode 100644 examples/raspberry_pi_mjpeg_led/web_root/index.html delete mode 100644 examples/restful_api/Makefile delete mode 100644 examples/restful_api/restful_api.c create mode 100644 examples/restful_client/Makefile create mode 100644 examples/restful_client/restful_client.c create mode 100644 examples/restful_server/Makefile rename examples/{restful_api => restful_server}/index.html (75%) create mode 100644 examples/restful_server/restful_server.c create mode 100644 examples/restful_server_s3/Makefile create mode 100644 examples/restful_server_s3/README.md create mode 100644 examples/restful_server_s3/index.html create mode 100644 examples/restful_server_s3/restful_server_s3.c create mode 100644 examples/rules.mk delete mode 100644 examples/send_file/Makefile delete mode 100644 examples/send_file/send_file.c delete mode 100644 examples/server_data_push/Makefile delete mode 100644 examples/server_data_push/server_data_push.c create mode 100644 examples/settings_panel_for_a_device/Makefile create mode 100644 examples/settings_panel_for_a_device/settings_panel.c create mode 100644 examples/settings_panel_for_a_device/web_root/fossa.jpg create mode 100644 examples/settings_panel_for_a_device/web_root/index.shtml create mode 100644 examples/settings_panel_for_a_device/web_root/jquery-1.11.3.min.js create mode 100644 examples/simplest_web_server/Makefile create mode 100644 examples/simplest_web_server/simplest_web_server.c create mode 100644 examples/tcp_echo_server/Makefile create mode 100644 examples/tcp_echo_server/echo_server.c delete mode 100644 examples/websocket_echo_server/Makefile delete mode 100644 examples/websocket_echo_server/index.html delete mode 100644 examples/websocket_echo_server/websocket_echo_server.c delete mode 100644 examples/websocket_ssl_proxy/Makefile delete mode 100644 examples/websocket_ssl_proxy/certs/ws1_ca.pem delete mode 100644 examples/websocket_ssl_proxy/certs/ws1_client.pem delete mode 100644 examples/websocket_ssl_proxy/certs/ws1_server.pem delete mode 100644 examples/websocket_ssl_proxy/certs/ws2_ca.pem delete mode 100644 examples/websocket_ssl_proxy/certs/ws2_client.pem delete mode 100644 examples/websocket_ssl_proxy/certs/ws2_server.pem delete mode 100644 examples/websocket_ssl_proxy/net_skeleton.h delete mode 100644 examples/websocket_ssl_proxy/ssl_wrapper.c delete mode 100644 examples/websocket_ssl_proxy/ssl_wrapper.h delete mode 100644 examples/websocket_ssl_proxy/ws_ssl.c delete mode 100644 examples/websocket_ssl_proxy/ws_ssl.html delete mode 100644 test/Makefile delete mode 100644 test/unit_test.c diff --git a/LICENSE b/LICENSE index feb3592d..6a8f0875 100644 --- a/LICENSE +++ b/LICENSE @@ -2,15 +2,15 @@ Copyright (c) 2004-2013 Sergey Lyubka Copyright (c) 2013-2015 Cesanta Software Limited All rights reserved -This code is dual-licensed: you can redistribute it and/or modify +This software is dual-licensed: you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. For the terms of this -license, see . +license, see . -You are free to use this code under the terms of the GNU General +You are free to use this software under the terms of the GNU General Public License, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -Alternatively, you can license this code under a commercial -license, as set out in . +Alternatively, you can license this software under a commercial +license, as set out in . diff --git a/README.md b/README.md index 64f1a6a7..754888e5 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,23 @@ [![Join the chat at https://gitter.im/cesanta/mongoose](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cesanta/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Mongoose is an embedded HTTP and WebSocket library that can turn anything -into a web server in 5 minutes by adding a few lines of C/C++ code. -On the market since 2004 with over 1 million cumulative downloads, -it's simplicity and flexibility has made it the top choice for -embedded software engineers. +![](https://img.shields.io/badge/license-GPL_2-green.svg "License") -Mongoose Binary is built on top of Mongoose Library which is used to serve Web -GUI on embedded devices, implement RESTful services, RPC frameworks (e.g. -JSON-RPC), handle telemetry data exchange and perform many other tasks. You'll find -it used across various industries including aerospace, manufacturing, finance, -research, automotive, gaming, IT and many more. +[Mongoose](https://www.cesanta.com/mongoose) is a +multi-protocol networking library written in C. +It provides easy to use event-driven interface that allows to implement +network protocols or scalable network applications with little effort. +Mongoose helps developers to manage the complexity of network programming +and let them concentrate on the logic, saving time and money. -> "Nothing overdone. Nothing less. So unbelievably easy to use. Just how good -> software should be!" - Pritin Tyagaraj, SAP +Mongoose has built-in support for several protocols, like +HTTP, Websocket, MQTT, mDNS. Example applications include +Websocket-based chat server, JSON-RPC server, +database server with RESTful API, MQTT broker, netcat with SSL and hexdump, +Raspberry PI camera video feed + led control, and more. + +Mongoose is ideal for the embedded environments, it has been designed as +an open source platform for connecting devices and bringing them online. [Download Mongoose Source Code here](http://hubs.ly/H0150FK0) @@ -23,21 +26,31 @@ Are you an embedded developer? Working on an embedded task? Check out our [embedded development products](http://hubs.ly/H0150sY0) to make the right choice for your project. -# Technical Specification +# Features -- Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX -and many other platforms -- CGI, SSI, SSL, Digest auth, Websocket, WEbDAV, Resumed download, - URL rewrite, file blacklist -- Custom error pages, Virtual hosts, IP-based ACL, Windows service, - HTTP/HTTPS client -- Simple and clean - [embedding API](https://github.com/cesanta/mongoose/blob/master/mongoose.h). - The source is in single - [mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) file - to make embedding easy -- Extremely lightweight, has a core of under 40kB and tiny runtime footprint -- Asynchronous, non-blocking core supporting single- or multi-threaded usage +* Cross-platform: works on Linux/UNIX, QNX, eCos, Windows, Android, iPhone, etc +* Single-threaded, asynchronous, non-blocking core with simple event-based API +* Builtin protocols: + - plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way) + - HTTP client, HTTP server + - Websocket client, Websocket server + - JSON-RPC client, JSON-RPC server + - MQTT client, MQTT broker + - CoAP client, CoAP server + - DNS client, DNS server, async DNS resolver +* Tiny static and run-time footprint +* Source code is both ISO C and ISO C++ compliant +* Very easy to integrate: just copy + [mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and + [mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h) + files to your build tree +* Extensively tested and production-ready, trusted by many blue chip businesses + +# Examples & Documentation + +- [User Guide](https://docs.cesanta.com/mongoose) - Detailed User Guide and API reference +- [examples](examples) - Collection of well-commented examples. To build any example, +go into respective directory and type `make` # Dashboard Example @@ -47,43 +60,17 @@ and many other platforms ](https://www.cesanta.com/contact) +# Contributions -# Licensing +People who have agreed to the +[Cesanta CLA](https://docs.cesanta.com/contributors_la.shtml) +can make contributions. Note that the CLA isn't a copyright +_assigment_ but rather a copyright _license_. +You retain the copyright on your contributions. -Cesanta made Mongoose open source under GPLv2 for a reason. We are all -developers here and appreciate easy access to code and therefore seamless -integration. It's great to be able to play around with the software before -committing to it. +# License -However, the GPLv2 open source license does not permit incorporating the -software into non-open source programs. In order to comply with GPLv2 licensing -you need to open the source code of your end product fully or alternatively -purchase a commercial license. - -[Enquire about commercial licensing here](https://www.cesanta.com/contact) - -# Documentation - -- [Embedding Guide](https://github.com/cesanta/mongoose/blob/master/docs/Embed.md) -- [Config Options Reference](https://github.com/cesanta/mongoose/blob/master/docs/Options.md) -- [API Reference](https://github.com/cesanta/mongoose/blob/master/docs/API.md) -- [Android Build Tutorial](https://docs.cesanta.com/AndroidBuild.shtml) -- [Release Notes](https://github.com/cesanta/mongoose/blob/master/docs/ReleaseNotes.md) - -# Mongoose Binary - -This is our easy to use web server for web developers (PHP, Ruby, Python, etc) -and web designers. Available in three editions to suit your needs: free, pro -(USD 5) and dev edition (from USD 8). To install, simply download, double-click -to start and run browser - that's all! - -[Download Mongoose Binary here](https://www.cesanta.com/mongoose) - -# Other products by Cesanta - -- [Smart.js](https://github.com/cesanta/smart.js) - Generic, hardware independent, full-stack IoT software platform -- [Fossa](http://github.com/cesanta/fossa) - Multi-protocol networking library -- [V7](https://github.com/cesanta/v7) - Embedded JavaScript engine -- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator -- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression - library +Mongoose is released under +[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html). +Businesses have an option to get non-restrictive, royalty-free commercial +license and professional support from [Cesanta](https://www.cesanta.com). diff --git a/examples/Makefile b/examples/Makefile index 43483c3f..8b1313a6 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,20 +1,15 @@ # Copyright (c) 2014 Cesanta Software # All rights reserved -SUBDIRS = $(sort $(filter-out csharp/, $(dir $(wildcard */)))) +SUBDIRS = $(sort $(dir $(wildcard */))) X = $(SUBDIRS) -ifdef WINDIR - # appending the Winsock2 library at the end of the compiler - # invocation - CFLAGS_EXTRA += -lws2_32 -endif .PHONY: $(SUBDIRS) all: $(SUBDIRS) $(SUBDIRS): - @$(MAKE) CFLAGS_EXTRA="$(CFLAGS_EXTRA)" -C $@ + @$(MAKE) -C $@ clean: for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done diff --git a/examples/api_server/Makefile b/examples/api_server/Makefile new file mode 100644 index 00000000..9face7f6 --- /dev/null +++ b/examples/api_server/Makefile @@ -0,0 +1,25 @@ +PROG = api_server +SOURCES = $(PROG).c sqlite3.c db_plugin_sqlite.c ../../mongoose.c +CFLAGS = -W -Wall -pthread $(CFLAGS_EXTRA) + +ifeq ($(OS), Windows_NT) +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S), Linux) + CFLAGS += -ldl -lm + endif +endif + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I.. /MD /Fe$@ + +test: $(PROG) + sh unit_test.sh $$(pwd)/$(PROG) + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/api_server/api_server.c b/examples/api_server/api_server.c new file mode 100644 index 00000000..445b0cf8 --- /dev/null +++ b/examples/api_server/api_server.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#include "db_plugin.h" + +static const char *s_http_port = "8000"; +static struct mg_serve_http_opts s_http_server_opts; +static int s_sig_num = 0; +static void *s_db_handle = NULL; +static const char *s_db_path = "api_server.db"; +static const struct mg_str s_get_method = NS_STR("GET"); +static const struct mg_str s_put_method = NS_STR("PUT"); +static const struct mg_str s_delele_method = NS_STR("DELETE"); + +static void signal_handler(int sig_num) { + signal(sig_num, signal_handler); + s_sig_num = sig_num; +} + +static int has_prefix(const struct mg_str *uri, const struct mg_str *prefix) { + return uri->len > prefix->len && memcmp(uri->p, prefix->p, prefix->len) == 0; +} + +static int is_equal(const struct mg_str *s1, const struct mg_str *s2) { + return s1->len == s2->len && memcmp(s1->p, s2->p, s2->len) == 0; +} + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + static const struct mg_str api_prefix = NS_STR("/api/v1"); + struct http_message *hm = (struct http_message *) ev_data; + struct mg_str key; + + switch (ev) { + case NS_HTTP_REQUEST: + if (has_prefix(&hm->uri, &api_prefix)) { + key.p = hm->uri.p + api_prefix.len; + key.len = hm->uri.len - api_prefix.len; + if (is_equal(&hm->method, &s_get_method)) { + db_op(nc, hm, &key, s_db_handle, API_OP_GET); + } else if (is_equal(&hm->method, &s_put_method)) { + db_op(nc, hm, &key, s_db_handle, API_OP_SET); + } else if (is_equal(&hm->method, &s_delele_method)) { + db_op(nc, hm, &key, s_db_handle, API_OP_DEL); + } else { + mg_printf(nc, "%s", + "HTTP/1.0 501 Not Implemented\r\n" + "Content-Length: 0\r\n\r\n"); + } + } else { + mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */ + } + break; + default: + break; + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + int i; + + /* Open listening socket */ + mg_mgr_init(&mgr, NULL); + nc = mg_bind(&mgr, s_http_port, ev_handler); + mg_set_protocol_http_websocket(nc); + s_http_server_opts.document_root = "web_root"; + + /* Parse command line arguments */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-D") == 0) { + mgr.hexdump_file = argv[++i]; + } else if (strcmp(argv[i], "-f") == 0) { + s_db_path = argv[++i]; + } else if (strcmp(argv[i], "-r") == 0) { + s_http_server_opts.document_root = argv[++i]; + } + } + + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + /* Open database */ + if ((s_db_handle = db_open(s_db_path)) == NULL) { + fprintf(stderr, "Cannot open DB [%s]\n", s_db_path); + exit(EXIT_FAILURE); + } + + /* Run event loop until signal is received */ + printf("Starting RESTful server on port %s\n", s_http_port); + while (s_sig_num == 0) { + mg_mgr_poll(&mgr, 1000); + } + + /* Cleanup */ + mg_mgr_free(&mgr); + db_close(&s_db_handle); + + printf("Exiting on signal %d\n", s_sig_num); + + return 0; +} diff --git a/examples/api_server/db_plugin.h b/examples/api_server/db_plugin.h new file mode 100644 index 00000000..da906bca --- /dev/null +++ b/examples/api_server/db_plugin.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#ifndef DB_PLUGIN_HEADER_DEFINED +#define DB_PLUGIN_HEADER_DEFINED + +#include "../../mongoose.h" + +void *db_open(const char *db_path); +void db_close(void **db_handle); + +enum { API_OP_GET, API_OP_SET, API_OP_DEL }; + +void db_op(struct mg_connection *nc, const struct http_message *hm, + const struct mg_str *key, void *db, int op); + +#endif /* DB_PLUGIN_HEADER_DEFINED */ diff --git a/examples/api_server/db_plugin_sqlite.c b/examples/api_server/db_plugin_sqlite.c new file mode 100644 index 00000000..1c87dd90 --- /dev/null +++ b/examples/api_server/db_plugin_sqlite.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#include "db_plugin.h" +#include "sqlite3.h" + +void *db_open(const char *db_path) { + sqlite3 *db = NULL; + if (sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL) == SQLITE_OK) { + sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS kv(key PRIMARY KEY, val);", + 0, 0, 0); + } + return db; +} + +void db_close(void **db_handle) { + if (db_handle != NULL && *db_handle != NULL) { + sqlite3_close(*db_handle); + *db_handle = NULL; + } +} + +static void op_set(struct mg_connection *nc, const struct http_message *hm, + const struct mg_str *key, void *db) { + sqlite3_stmt *stmt = NULL; + char value[200]; + const struct mg_str *body = hm->query_string.len > 0 ? + &hm->query_string : &hm->body; + + mg_get_http_var(body, "value", value, sizeof(value)); + if (sqlite3_prepare_v2(db, "INSERT OR REPLACE INTO kv VALUES (?, ?);", + -1, &stmt, NULL) == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, key->p, key->len, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, value, strlen(value), SQLITE_STATIC); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + } + mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); +} + +static void op_get(struct mg_connection *nc, const struct http_message *hm, + const struct mg_str *key, void *db) { + sqlite3_stmt *stmt = NULL; + const char *data = NULL; + int result; + (void) hm; + + if (sqlite3_prepare_v2(db, "SELECT val FROM kv WHERE key = ?;", + -1, &stmt, NULL) == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, key->p, key->len, SQLITE_STATIC); + result = sqlite3_step(stmt); + data = (char *) sqlite3_column_text(stmt, 0); + if ((result == SQLITE_OK || result == SQLITE_ROW) && data != NULL) { + mg_printf(nc, "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n\r\n%s", + (int) strlen(data), data); + } else { + mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\n" + "Content-Length: 0\r\n\r\n"); + } + sqlite3_finalize(stmt); + } else { + mg_printf(nc, "%s", "HTTP/1.1 500 Server Error\r\n" + "Content-Length: 0\r\n\r\n"); + } +} + +static void op_del(struct mg_connection *nc, const struct http_message *hm, + const struct mg_str *key, void *db) { + sqlite3_stmt *stmt = NULL; + int result; + (void) hm; + + if (sqlite3_prepare_v2(db, "DELETE FROM kv WHERE key = ?;", + -1, &stmt, NULL) == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, key->p, key->len, SQLITE_STATIC); + result = sqlite3_step(stmt); + if (result == SQLITE_OK || result == SQLITE_ROW) { + mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + } else { + mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\n" + "Content-Length: 0\r\n\r\n"); + } + sqlite3_finalize(stmt); + } else { + mg_printf(nc, "%s", "HTTP/1.1 500 Server Error\r\n" + "Content-Length: 0\r\n\r\n"); + } +} + +void db_op(struct mg_connection *nc, const struct http_message *hm, + const struct mg_str *key, void *db, int op) { + switch (op) { + case API_OP_GET: op_get(nc, hm, key, db); break; + case API_OP_SET: op_set(nc, hm, key, db); break; + case API_OP_DEL: op_del(nc, hm, key, db); break; + default: + mg_printf(nc, "%s", "HTTP/1.0 501 Not Implemented\r\n" + "Content-Length: 0\r\n\r\n"); + break; + } +} + diff --git a/examples/api_server/sqlite3.c b/examples/api_server/sqlite3.c new file mode 100644 index 00000000..a49c83c5 --- /dev/null +++ b/examples/api_server/sqlite3.c @@ -0,0 +1,140456 @@ +/****************************************************************************** +** This file is an amalgamation of many separate C source files from SQLite +** version 3.7.17. By combining all the individual C code files into this +** single large file, the entire code can be compiled as a single translation +** unit. This allows many compilers to do optimizations that would not be +** possible if the files were compiled separately. Performance improvements +** of 5% or more are commonly seen when SQLite is compiled as a single +** translation unit. +** +** This file is all you need to compile SQLite. To use SQLite in other +** programs, you need this file and the "sqlite3.h" header file that defines +** the programming interface to the SQLite library. (If you do not have +** the "sqlite3.h" header file at hand, you will find a copy embedded within +** the text of this file. Search for "Begin file sqlite3.h" to find the start +** of the embedded sqlite3.h header file.) Additional code files may be needed +** if you want a wrapper to interface SQLite with your choice of programming +** language. The code for the "sqlite3" command-line shell is also in a +** separate file. This file contains only code for the core SQLite library. +*/ +#define SQLITE_CORE 1 +#define SQLITE_AMALGAMATION 1 +#ifndef SQLITE_PRIVATE +# define SQLITE_PRIVATE static +#endif +#ifndef SQLITE_API +# define SQLITE_API +#endif +/************** Begin file sqliteInt.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. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" +#endif + +/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ +/************** Begin file sqliteLimit.h *************************************/ +/* +** 2007 May 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 file defines various limits of what SQLite can process. +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 127 +#endif + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +*/ +#ifndef SQLITE_DEFAULT_CACHE_SIZE +# define SQLITE_DEFAULT_CACHE_SIZE 2000 +#endif +#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE +# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 +#endif + +/* +** The default number of frames to accumulate in the log file before +** checkpointing the database in WAL mode. +*/ +#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT +# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 +#endif + +/* +** The maximum number of attached databases. This must be between 0 +** and 62. The upper bound on 62 is because a 64-bit integer bitmap +** is used internally to track attached databases. +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* Maximum page size. The upper bound on this value is 65536. This a limit +** imposed by the use of 16-bit offsets within each page. +** +** Earlier versions of SQLite allowed the user to change this value at +** compile time. This is no longer permitted, on the grounds that it creates +** a library that is technically incompatible with an SQLite library +** compiled with a different limit. If a process operating on a database +** with a page-size of 65536 bytes crashes, then an instance of SQLite +** compiled with the default page-size limit will not be able to rollback +** the aborted transaction. This could lead to database corruption. +*/ +#ifdef SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_PAGE_SIZE +#endif +#define SQLITE_MAX_PAGE_SIZE 65536 + + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif +#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + +/* +** Ordinarily, if no value is explicitly provided, SQLite creates databases +** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain +** device characteristics (sector-size and atomic write() support), +** SQLite may choose a larger value. This constant is the maximum value +** SQLite will choose on its own. +*/ +#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 +#endif +#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + +/* +** Maximum depth of recursion for triggers. +** +** A value of 1 means that a trigger program will not be able to itself +** fire any triggers. A value of 0 means that no trigger programs at all +** may be executed. +*/ +#ifndef SQLITE_MAX_TRIGGER_DEPTH +# define SQLITE_MAX_TRIGGER_DEPTH 1000 +#endif + +/************** End of sqliteLimit.h *****************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicious pointer arithmetic */ +#endif + +/* Needed for various definitions... */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) +# define _BSD_SOURCE +#endif + +/* +** Include standard header files as necessary +*/ +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +/* +** The following macros are used to cast pointers to integers and +** integers to pointers. The way you do this varies from one compiler +** to the next, so we have developed the following set of #if statements +** to generate appropriate macros for a wide range of compilers. +** +** The correct "ANSI" way to do this is to use the intptr_t type. +** Unfortunately, that typedef is not available on all compilers, or +** if it is available, it requires an #include of specific headers +** that vary from one machine to the next. +** +** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on +** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). +** So we have to define the macros in different ways depending on the +** compiler. +*/ +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ +# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) +#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ +# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) +#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) +#else /* Generates a warning - but it always works */ +# define SQLITE_INT_TO_PTR(X) ((void*)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(X)) +#endif + +/* +** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. +** 0 means mutexes are permanently disable and the library is never +** threadsafe. 1 means the library is serialized which is the highest +** level of threadsafety. 2 means the libary is multithreaded - multiple +** threads can use SQLite as long as no two threads try to use the same +** database connection at the same time. +** +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy. +*/ +#if !defined(SQLITE_THREADSAFE) +# if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +# else +# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ +# endif +#endif + +/* +** Powersafe overwrite is on by default. But can be turned off using +** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. +*/ +#ifndef SQLITE_POWERSAFE_OVERWRITE +# define SQLITE_POWERSAFE_OVERWRITE 1 +#endif + +/* +** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. +** It determines whether or not the features related to +** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can +** be overridden at runtime using the sqlite3_config() API. +*/ +#if !defined(SQLITE_DEFAULT_MEMSTATUS) +# define SQLITE_DEFAULT_MEMSTATUS 1 +#endif + +/* +** Exactly one of the following macros must be defined in order to +** specify which memory allocation subsystem to use. +** +** SQLITE_SYSTEM_MALLOC // Use normal system malloc() +** SQLITE_WIN32_MALLOC // Use Win32 native heap API +** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails +** SQLITE_MEMDEBUG // Debugging version of system malloc() +** +** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the +** assert() macro is enabled, each call into the Win32 native heap subsystem +** will cause HeapValidate to be called. If heap validation should fail, an +** assertion will be triggered. +** +** (Historical note: There used to be several other options, but we've +** pared it down to just these three.) +** +** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as +** the default. +*/ +#if defined(SQLITE_SYSTEM_MALLOC) \ + + defined(SQLITE_WIN32_MALLOC) \ + + defined(SQLITE_ZERO_MALLOC) \ + + defined(SQLITE_MEMDEBUG)>1 +# error "Two or more of the following compile-time configuration options\ + are defined but at most one is allowed:\ + SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ + SQLITE_ZERO_MALLOC" +#endif +#if defined(SQLITE_SYSTEM_MALLOC) \ + + defined(SQLITE_WIN32_MALLOC) \ + + defined(SQLITE_ZERO_MALLOC) \ + + defined(SQLITE_MEMDEBUG)==0 +# define SQLITE_SYSTEM_MALLOC 1 +#endif + +/* +** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the +** sizes of memory allocations below this value where possible. +*/ +#if !defined(SQLITE_MALLOC_SOFT_LIMIT) +# define SQLITE_MALLOC_SOFT_LIMIT 1024 +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most Unix systems. But Mac OS X is different. +** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, +** so it is omitted there. See ticket #2673. +** +** Later we learn that _XOPEN_SOURCE is poorly or incorrectly +** implemented on some systems. So we avoid defining it at all +** if it is already defined or if it is unneeded because we are +** not doing a threadsafe build. Ticket #2681. +** +** See also ticket #2741. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \ + && !defined(__APPLE__) && SQLITE_THREADSAFE +# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ +#endif + +/* +** The TCL headers are only needed when compiling the TCL bindings. +*/ +#if defined(SQLITE_TCL) || defined(TCLSH) +# include +#endif + +/* +** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that +** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, +** make it true by defining or undefining NDEBUG. +** +** Setting NDEBUG makes the code smaller and run faster by disabling the +** number assert() statements in the code. So we want the default action +** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG +** is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif +#if defined(NDEBUG) && defined(SQLITE_DEBUG) +# undef NDEBUG +#endif + +/* +** The testcase() macro is used to aid in coverage testing. When +** doing coverage testing, the condition inside the argument to +** testcase() must be evaluated both true and false in order to +** get full branch coverage. The testcase() macro is inserted +** to help ensure adequate test coverage in places where simple +** condition/decision coverage is inadequate. For example, testcase() +** can be used to make sure boundary values are tested. For +** bitmask tests, testcase() can be used to make sure each bit +** is significant and used at least once. On switch statements +** where multiple cases go to the same block of code, testcase() +** can insure that all cases are evaluated. +** +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + +/* +** The TESTONLY macro is used to enclose variable declarations or +** other bits of code that are needed to support the arguments +** within testcase() and assert() macros. +*/ +#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) +# define TESTONLY(X) X +#else +# define TESTONLY(X) +#endif + +/* +** Sometimes we need a small amount of code such as a variable initialization +** to setup for a later assert() statement. We do not want this code to +** appear when assert() is disabled. The following macro is therefore +** used to contain that setup code. The "VVA" acronym stands for +** "Verification, Validation, and Accreditation". In other words, the +** code within VVA_ONLY() will only run during verification processes. +*/ +#ifndef NDEBUG +# define VVA_ONLY(X) X +#else +# define VVA_ONLY(X) +#endif + +/* +** The ALWAYS and NEVER macros surround boolean expressions which +** are intended to always be true or false, respectively. Such +** expressions could be omitted from the code completely. But they +** are included in a few cases in order to enhance the resilience +** of SQLite to unexpected behavior - to make the code "self-healing" +** or "ductile" rather than being "brittle" and crashing at the first +** hint of unplanned behavior. +** +** In other words, ALWAYS and NEVER are added for defensive code. +** +** When doing coverage testing ALWAYS and NEVER are hard-coded to +** be true and false so that the unreachable code then specify will +** not be counted as untested code. +*/ +#if defined(SQLITE_COVERAGE_TEST) +# define ALWAYS(X) (1) +# define NEVER(X) (0) +#elif !defined(NDEBUG) +# define ALWAYS(X) ((X)?1:(assert(0),0)) +# define NEVER(X) ((X)?(assert(0),1):0) +#else +# define ALWAYS(X) (X) +# define NEVER(X) (X) +#endif + +/* +** Return true (non-zero) if the input is a integer that is too large +** to fit in 32-bits. This macro is used inside of various testcase() +** macros to verify that we have tested SQLite for large-file support. +*/ +#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. GCC is able to +** use these hints to generate better code, sometimes. +*/ +#if defined(__GNUC__) && 0 +# define likely(X) __builtin_expect((X),1) +# define unlikely(X) __builtin_expect((X),0) +#else +# define likely(X) !!(X) +# define unlikely(X) !!(X) +#endif + +/************** Include sqlite3.h in the middle of sqliteInt.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 the right 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. +*/ +#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 + +#ifndef SQLITE_API +# define SQLITE_API +#endif + + +/* +** These no-op macros are used in front of interfaces to mark those +** interfaces as either deprecated or experimental. New applications +** should not use deprecated interfaces - they are support for backwards +** compatibility only. Application writers should be aware that +** experimental interfaces are subject to change in point releases. +** +** These macros used to resolve to various kinds of compiler magic that +** would generate warning messages when they were used. But that +** compiler magic ended up generating such a flurry of bug reports +** that we have taken it all out and gone back to using simple +** noop macros. +*/ +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL + +/* +** Ensure these symbols were 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 +** +** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header +** evaluates to a string literal that is the SQLite version in the +** format "X.Y.Z" where X is the major version number (always 3 for +** SQLite3) and Y is the minor version number and Z is the release number.)^ +** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same +** numbers used in [SQLITE_VERSION].)^ +** The SQLITE_VERSION_NUMBER for any given release of SQLite will also +** be larger than the release from which it is derived. Either Y will +** be held constant and Z will be incremented or else Y will be incremented +** and Z will be reset to zero. +** +** Since version 3.6.18, SQLite source code has been stored in the +** Fossil configuration management +** system. ^The SQLITE_SOURCE_ID macro evaluates to +** a string which identifies a particular check-in of SQLite +** within its configuration management system. ^The SQLITE_SOURCE_ID +** string contains the date and time of the check-in (UTC) and an SHA1 +** hash of the entire source tree. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. +*/ +#define SQLITE_VERSION "3.7.17" +#define SQLITE_VERSION_NUMBER 3007017 +#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668" + +/* +** CAPI3REF: Run-Time Library Version Numbers +** KEYWORDS: sqlite3_version, sqlite3_sourceid +** +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros +** but are associated with the library instead of the header file. ^(Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus insure that the application is +** compiled with matching library and header files. +** +**
+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** 
)^ +** +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() +** function is provided for use in DLLs since DLL users usually do not have +** direct access to string constants within the DLL. ^The +** sqlite3_libversion_number() function returns an integer equal to +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns +** a pointer to a string constant whose value is the same as the +** [SQLITE_SOURCE_ID] C preprocessor macro. +** +** See also: [sqlite_version()] and [sqlite_source_id()]. +*/ +SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Run-Time Library Compilation Options Diagnostics +** +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). +** +** ^The sqlite3_compileoption_get() function allows iterating +** over the list of options that were defined at compile time by +** returning the N-th compile time option string. ^If N is out of range, +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by +** sqlite3_compileoption_get(). +** +** ^Support for the diagnostic functions sqlite3_compileoption_used() +** and sqlite3_compileoption_get() may be omitted by specifying the +** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. +** +** See also: SQL functions [sqlite_compileoption_used()] and +** [sqlite_compileoption_get()] and the [compile_options pragma]. +*/ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); +#endif + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe +** +** ^The sqlite3_threadsafe() function returns zero if and only if +** SQLite was compiled with mutexing code omitted due to the +** [SQLITE_THREADSAFE] compile-time option being set to 0. +** +** SQLite can be compiled with or without mutexes. When +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes +** are enabled and SQLite is threadsafe. When the +** [SQLITE_THREADSAFE] macro is 0, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite concurrently from more than one thread. +** +** Enabling mutexes incurs a measurable performance penalty. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** ^The default behavior is for mutexes to be enabled. +** +** This interface can be used by an application to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the [SQLITE_THREADSAFE] macro. +** +** This interface only reports on the compile-time mutex setting +** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with +** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but +** can be fully or partially disabled using a call to [sqlite3_config()] +** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], +** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the +** sqlite3_threadsafe() function shows only the compile-time setting of +** thread safety, not any run-time changes to that setting made by +** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() +** is unchanged by calls to sqlite3_config().)^ +** +** See the [threading mode] documentation for additional information. +*/ +SQLITE_API int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle +** KEYWORDS: {database connection} {database connections} +** +** Each open SQLite database is represented by a 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()] +** and [sqlite3_close_v2()] are its destructors. 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 an +** sqlite3 object. +*/ +typedef struct sqlite3 sqlite3; + +/* +** CAPI3REF: 64-Bit Integer Types +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. +** The sqlite_int64 and sqlite_uint64 types are supported for backwards +** compatibility only. +** +** ^The sqlite3_int64 and sqlite_int64 types can store integer values +** between -9223372036854775808 and +9223372036854775807 inclusive. ^The +** sqlite3_uint64 and sqlite_uint64 types can store integer values +** between 0 and +18446744073709551615 inclusive. +*/ +#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 +** +** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors +** for the [sqlite3] object. +** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if +** the [sqlite3] object is successfully destroyed and all associated +** resources are deallocated. +** +** ^If the database connection is associated with unfinalized prepared +** statements or unfinished sqlite3_backup objects then sqlite3_close() +** will leave the database connection open and return [SQLITE_BUSY]. +** ^If sqlite3_close_v2() is called with unfinalized prepared statements +** and unfinished sqlite3_backups, then the database connection becomes +** an unusable "zombie" which will automatically be deallocated when the +** last prepared statement is finalized or the last sqlite3_backup is +** finished. The sqlite3_close_v2() interface is intended for use with +** host languages that are garbage collected, and where the order in which +** destructors are called is arbitrary. +** +** Applications should [sqlite3_finalize | finalize] all [prepared statements], +** [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated +** with the [sqlite3] object prior to attempting to close the object. ^If +** sqlite3_close_v2() is called on a [database connection] that still has +** outstanding [prepared statements], [BLOB handles], and/or +** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation +** of resources is deferred until all [prepared statements], [BLOB handles], +** and [sqlite3_backup] objects are also destroyed. +** +** ^If an [sqlite3] object is destroyed while a transaction is open, +** the transaction is automatically rolled back. +** +** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] +** must be either a NULL +** pointer or an [sqlite3] object pointer obtained +** from [sqlite3_open()], [sqlite3_open16()], or +** [sqlite3_open_v2()], and not previously closed. +** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer +** argument is a harmless no-op. +*/ +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(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 +** +** The sqlite3_exec() interface is a convenience wrapper around +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], +** that allows an application to run multiple statements of SQL +** without having to use a lot of C code. +** +** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, +** semicolon-separate SQL statements passed into its 2nd argument, +** in the context of the [database connection] passed in as its 1st +** argument. ^If the callback function of the 3rd argument to +** sqlite3_exec() is not NULL, then it is invoked for each result row +** coming out of the evaluated SQL statements. ^The 4th argument to +** sqlite3_exec() is relayed through to the 1st argument of each +** callback invocation. ^If the callback pointer to sqlite3_exec() +** is NULL, then no callback is ever invoked and result rows are +** ignored. +** +** ^If an error occurs while evaluating the SQL statements passed into +** sqlite3_exec(), then execution of the current statement stops and +** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() +** is not NULL then any error message is written into memory obtained +** from [sqlite3_malloc()] and passed back through the 5th parameter. +** To avoid memory leaks, the application should invoke [sqlite3_free()] +** on error message strings returned through the 5th parameter of +** of sqlite3_exec() after the error message string is no longer needed. +** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors +** occur, then sqlite3_exec() sets the pointer in its 5th parameter to +** NULL before returning. +** +** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() +** routine returns SQLITE_ABORT without invoking the callback again and +** without running any subsequent SQL statements. +** +** ^The 2nd argument to the sqlite3_exec() callback function is the +** number of columns in the result. ^The 3rd argument to the sqlite3_exec() +** callback is an array of pointers to strings obtained as if from +** [sqlite3_column_text()], one for each column. ^If an element of a +** result row is NULL then the corresponding string pointer for the +** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the +** sqlite3_exec() callback is an array of pointers to strings where each +** entry represents the name of corresponding result column as obtained +** from [sqlite3_column_name()]. +** +** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer +** to an empty string, or a pointer that contains only whitespace and/or +** SQL comments, then no SQL statements are evaluated and the database +** is not changed. +** +** Restrictions: +** +**
    +**
  • The application must insure that the 1st parameter to sqlite3_exec() +** is a valid and open [database connection]. +**
  • The application must not close [database connection] specified by +** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not modify the SQL statement text passed into +** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
+*/ +SQLITE_API int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes +** KEYWORDS: SQLITE_OK {error code} {error codes} +** KEYWORDS: {result code} {result codes} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicate success or failure. +** +** New error codes may be added in future versions of SQLite. +** +** See also: [SQLITE_IOERR_READ | extended result codes], +** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | 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 /* Unknown opcode in sqlite3_file_control() */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* 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_NOTICE 27 /* Notifications from sqlite3_log() */ +#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ +#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 +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result code} {extended result codes} +** +** 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 coarse-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. The extended result codes are enabled or disabled +** on a per database connection basis using the +** [sqlite3_extended_result_codes()] API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** 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)) +#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) +#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) +#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) +#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) +#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) +#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) +#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) +#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) +#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) +#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) +#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) +#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) +#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) +#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) +#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) +#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) +#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) +#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) +#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) +#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) +#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) +#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) +#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) +#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) +#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) +#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) +#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) +#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) +#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) + +/* +** CAPI3REF: Flags For File Open Operations +** +** These bit values are intended for use in the +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the [sqlite3_vfs.xOpen] method. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ +#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ + +/* Reserved: 0x00F00000 */ + +/* +** CAPI3REF: Device Characteristics +** +** The xDeviceCharacteristics method of the [sqlite3_io_methods] +** object returns an integer which is a vector of these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** 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(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that +** after reboot following a crash or power loss, the only bytes in a +** file that were written at the application level might have changed +** and that adjacent bytes, even bytes within the same sector are +** guaranteed to be unchanged. +*/ +#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 +#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 +#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 + +/* +** CAPI3REF: File Locking Levels +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#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 +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of +** these integer values as the second argument. +** +** 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. If the lower four bits of the flag +** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. +** If the lower four bits equal SQLITE_SYNC_FULL, that means +** to use Mac OS X style fullsync instead of fsync(). +** +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL +** settings. The [synchronous pragma] determines when calls to the +** xSync VFS method occur and applies uniformly across all platforms. +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how +** energetic or rigorous or forceful the sync operations are and +** only make a difference on Mac OSX for the default SQLite code. +** (Third-party VFS implementations might also make the distinction +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the +** operating systems natively supported by SQLite, only Mac OSX +** cares about the difference.) +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + +/* +** CAPI3REF: OS Interface Open File Handle +** +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | 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 +** +** Every file opened by the [sqlite3_vfs.xOpen] method populates an +** [sqlite3_file] object (or, more commonly, a subclass of the +** [sqlite3_file] object) with a pointer to an instance of this object. +** This object defines the methods used to perform various operations +** against the open file represented by the [sqlite3_file] object. +** +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The +** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] +** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element +** to NULL. +** +** 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 a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] +** 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 checks whether any database connection, +** either in this process or in some other process, is holding a RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. +** +** 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 intended to +** point 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 all 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. VFS implementations should +** return [SQLITE_NOTFOUND] for file control opcodes that they do not +** recognize. +** +** 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(). +** +** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill +** in the unread portions of the buffer with zeros. A VFS that +** fails to zero-fill short reads might seem to work. However, +** failure to zero-fill short reads will eventually lead to +** database corruption. +*/ +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 *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); + int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); + /* Methods above are valid for version 3 */ + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] +** interface. +** +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode causes 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. This capability +** is used during testing and only needs to be supported when SQLITE_TEST +** is defined. +**
    +**
  • [[SQLITE_FCNTL_SIZE_HINT]] +** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS +** layer a hint of how large the database file will grow to be during the +** current transaction. This hint is not guaranteed to be accurate but it +** is often close. The underlying VFS might choose to preallocate database +** file space based on this hint in order to help writes to the database +** file run faster. +** +**
  • [[SQLITE_FCNTL_CHUNK_SIZE]] +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS +** extends and truncates the database file in chunks of a size specified +** by the user. The fourth argument to [sqlite3_file_control()] should +** point to an integer (type int) containing the new chunk-size to use +** for the nominated database. Allocating database file space in large +** chunks (say 1MB at a time), may reduce file-system fragmentation and +** improve performance on some systems. +** +**
  • [[SQLITE_FCNTL_FILE_POINTER]] +** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer +** to the [sqlite3_file] object associated with a particular database +** connection. See the [sqlite3_file_control()] documentation for +** additional information. +** +**
  • [[SQLITE_FCNTL_SYNC_OMITTED]] +** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by +** SQLite and sent to all VFSes in place of a call to the xSync method +** when the database connection has [PRAGMA synchronous] set to OFF.)^ +** Some specialized VFSes need this signal in order to operate correctly +** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most +** VFSes do not need this signal and should silently ignore this opcode. +** Applications should not call [sqlite3_file_control()] with this +** opcode as doing so may disrupt the operation of the specialized VFSes +** that do require it. +** +**
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] +** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic +** retry counts and intervals for certain disk I/O operations for the +** windows [VFS] in order to provide robustness in the presence of +** anti-virus programs. By default, the windows VFS will retry file read, +** file write, and file delete operations up to 10 times, with a delay +** of 25 milliseconds before the first retry and with the delay increasing +** by an additional 25 milliseconds with each subsequent retry. This +** opcode allows these two values (10 retries and 25 milliseconds of delay) +** to be adjusted. The values are changed for all database connections +** within the same process. The argument is a pointer to an array of two +** integers where the first integer i the new retry count and the second +** integer is the delay. If either integer is negative, then the setting +** is not changed but instead the prior value of that setting is written +** into the array entry, allowing the current retry settings to be +** interrogated. The zDbName parameter is ignored. +** +**
  • [[SQLITE_FCNTL_PERSIST_WAL]] +** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the +** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +** write ahead log and shared memory files used for transaction control +** are automatically deleted when the latest connection to the database +** closes. Setting persistent WAL mode causes those files to persist after +** close. Persisting the files is useful when other processes that do not +** have write permission on the directory containing the database file want +** to read the database file, as the WAL and shared memory files must exist +** in order for the database to be readable. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable persistent WAL mode or 1 to enable persistent +** WAL mode. If the integer is -1, then it is overwritten with the current +** WAL persistence setting. +** +**
  • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] +** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the +** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting +** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the +** xDeviceCharacteristics methods. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage +** mode. If the integer is -1, then it is overwritten with the current +** zero-damage mode setting. +** +**
  • [[SQLITE_FCNTL_OVERWRITE]] +** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening +** a write transaction to indicate that, unless it is rolled back for some +** reason, the entire database file will be overwritten by the current +** transaction. This is used by VACUUM operations. +** +**
  • [[SQLITE_FCNTL_VFSNAME]] +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of +** all [VFSes] in the VFS stack. The names are of all VFS shims and the +** final bottom-level VFS are written into memory obtained from +** [sqlite3_malloc()] and the result is stored in the char* variable +** that the fourth parameter of [sqlite3_file_control()] points to. +** The caller is responsible for freeing the memory when done. As with +** all file-control actions, there is no guarantee that this will actually +** do anything. Callers should initialize the char* variable to a NULL +** pointer in case this file-control is not implemented. This file-control +** is intended for diagnostic use only. +** +**
  • [[SQLITE_FCNTL_PRAGMA]] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** file control is sent to the open [sqlite3_file] object corresponding +** to the database file to which the pragma statement refers. ^The argument +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of +** pointers to strings (char**) in which the second element of the array +** is the name of the pragma and the third element is the argument to the +** pragma or NULL if the pragma has no argument. ^The handler for an +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element +** of the char** argument point to a string obtained from [sqlite3_mprintf()] +** or the equivalent and that string will become the result of the pragma or +** the error message if the pragma fails. ^If the +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] +** file control returns [SQLITE_OK], then the parser assumes that the +** VFS has handled the PRAGMA itself and the parser generates a no-op +** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means +** that the VFS encountered an error while handling the [PRAGMA] and the +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] +** file control occurs at the beginning of pragma statement analysis and so +** it is able to override built-in [PRAGMA] statements. +** +**
  • [[SQLITE_FCNTL_BUSYHANDLER]] +** ^The [SQLITE_FCNTL_BUSYHANDLER] +** file-control may be invoked by SQLite on the database file handle +** shortly after it is opened in order to provide a custom VFS with access +** to the connections busy-handler callback. The argument is of type (void **) +** - an array of two (void *) values. The first (void *) actually points +** to a function of type (int (*)(void *)). In order to invoke the connections +** busy-handler, this function should be invoked with the second (void *) in +** the array as the only argument. If it returns non-zero, then the operation +** should be retried. If it returns zero, the custom VFS should abandon the +** current operation. +** +**
  • [[SQLITE_FCNTL_TEMPFILENAME]] +** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** to have SQLite generate a +** temporary filename using the same algorithm that is followed to generate +** temporary filenames for TEMP tables and other internal uses. The +** argument should be a char** which will be filled with the filename +** written into memory obtained from [sqlite3_malloc()]. The caller should +** invoke [sqlite3_free()] on the result to avoid a memory leak. +** +**
  • [[SQLITE_FCNTL_MMAP_SIZE]] +** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the +** maximum number of bytes that will be used for memory-mapped I/O. +** The argument is a pointer to a value of type sqlite3_int64 that +** is an advisory maximum number of bytes in the file to memory map. The +** pointer is overwritten with the old value. The limit is not changed if +** the value originally pointed to is negative, and so the current limit +** can be queried by passing in a pointer to a negative number. This +** file-control is used internally to implement [PRAGMA mmap_size]. +** +**
+*/ +#define SQLITE_FCNTL_LOCKSTATE 1 +#define SQLITE_GET_LOCKPROXYFILE 2 +#define SQLITE_SET_LOCKPROXYFILE 3 +#define SQLITE_LAST_ERRNO 4 +#define SQLITE_FCNTL_SIZE_HINT 5 +#define SQLITE_FCNTL_CHUNK_SIZE 6 +#define SQLITE_FCNTL_FILE_POINTER 7 +#define SQLITE_FCNTL_SYNC_OMITTED 8 +#define SQLITE_FCNTL_WIN32_AV_RETRY 9 +#define SQLITE_FCNTL_PERSIST_WAL 10 +#define SQLITE_FCNTL_OVERWRITE 11 +#define SQLITE_FCNTL_VFSNAME 12 +#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 +#define SQLITE_FCNTL_PRAGMA 14 +#define SQLITE_FCNTL_BUSYHANDLER 15 +#define SQLITE_FCNTL_TEMPFILENAME 16 +#define SQLITE_FCNTL_MMAP_SIZE 18 + +/* +** CAPI3REF: Mutex Handle +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. 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 +** +** An instance of the sqlite3_vfs 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". See +** the [VFS | VFS documentation] for further information. +** +** The value of the iVersion field is initially 1 but may be larger in +** future versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. Note that the structure +** of the sqlite3_vfs object changes in the transaction between +** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +** modified. +** +** 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 sqlite3_vfs objects 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. Neither the application code nor the VFS +** implementation should use the pNext pointer. +** +** The pNext field is the only field 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. +** +** [[sqlite3_vfs.xOpen]] +** ^SQLite guarantees that the zFilename parameter to xOpen +** is either a NULL pointer or string obtained +** from xFullPathname() with an optional suffix added. +** ^If a suffix is added to the zFilename parameter, it will +** consist of a single "-" character followed by no more than +** 11 alphanumeric and/or "-" characters. +** ^SQLite further guarantees that +** the string will be valid and unchanged until xClose() is +** called. Because of the previous sentence, +** the [sqlite3_file] can safely store a pointer to the +** filename if it needs to remember the filename for some reason. +** If the zFilename parameter to xOpen is a NULL pointer then xOpen +** must invent its own temporary name for the file. ^Whenever the +** xFilename parameter is NULL it will also be the case that the +** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. +** +** 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]. +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. +** +** ^(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] +**
  • [SQLITE_OPEN_WAL] +**
)^ +** +** The file I/O implementation can use the object type flags to +** change 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 would +** also be no-ops, and any attempt to read the journal would return +** SQLITE_IOERR. Or the implementation might recognize that a database +** file will be doing page-aligned sector reads and writes in a random +** order and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen method: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases and their journals, transient +** databases, and subjournals. +** +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is not used to indicate the file should be opened +** for exclusive access. +** +** ^At least szOsFile bytes of memory are allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. The xOpen method does not have to +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. +** +** [[sqlite3_vfs.xAccess]] +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to +** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test whether a file is at least readable. The file can be a +** directory. +** +** ^SQLite will always allocate at least mxPathname+1 bytes for the +** output buffer xFullPathname. The exact size of the output buffer +** is also passed as a parameter to both methods. If the output buffer +** is not large enough, [SQLITE_CANTOPEN] should be returned. Since 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(), xCurrentTime(), and xCurrentTimeInt64() +** 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 causes 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 as +** a floating point value. +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). +** ^SQLite will use the xCurrentTimeInt64() method to get the current +** date and time if that method is available (if iVersion is 2 or +** greater and the function pointer is not NULL) and will fall back +** to xCurrentTime() if xCurrentTimeInt64() is unavailable. +** +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces +** are not used by the SQLite core. These optional interfaces are provided +** by some VFSes to facilitate testing of the VFS code. By overriding +** system calls with functions under its control, a test program can +** simulate faults and error conditions that would otherwise be difficult +** or impossible to induce. The set of system calls that can be overridden +** varies from one VFS to another, and from one version of the same VFS to the +** next. Applications that use these interfaces must be prepared for any +** or all of these interfaces to be NULL or for their behavior to change +** from one release to the next. Applications must not attempt to access +** any of these methods if the iVersion of the VFS is less than 3. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +typedef void (*sqlite3_syscall_ptr)(void); +struct sqlite3_vfs { + int iVersion; /* Structure version number (currently 3) */ + 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 *pResOut); + 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); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* + ** The methods above are in version 1 of the sqlite_vfs object + ** definition. Those that follow are added in version 2 or later + */ + int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); + /* + ** The methods above are in versions 1 and 2 of the sqlite_vfs object. + ** Those below are for version 3 and greater. + */ + int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); + sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); + const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); + /* + ** The methods above are in versions 1 through 3 of the sqlite_vfs object. + ** New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. + */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. They determine +** what kind of permissions the xAccess method is looking for. +** With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks whether the file exists. +** With SQLITE_ACCESS_READWRITE, the xAccess method +** checks whether the named directory is both readable and writable +** (in other words, if files can be added, removed, and renamed within +** the directory). +** The SQLITE_ACCESS_READWRITE constant is currently used only by the +** [temp_store_directory pragma], though this could change in a future +** release of SQLite. +** With SQLITE_ACCESS_READ, the xAccess method +** checks whether the file is readable. The SQLITE_ACCESS_READ constant is +** currently unused, though it might be used in a future release of +** SQLite. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ +#define SQLITE_ACCESS_READ 2 /* Unused */ + +/* +** CAPI3REF: Flags for the xShmLock VFS method +** +** These integer constants define the various locking operations +** allowed by the xShmLock method of [sqlite3_io_methods]. The +** following are the only legal combinations of flags to the +** xShmLock method: +** +**
    +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE +**
+** +** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as +** was given no the corresponding lock. +** +** The xShmLock method can transition between unlocked and SHARED or +** between unlocked and EXCLUSIVE. It cannot transition between SHARED +** and EXCLUSIVE. +*/ +#define SQLITE_SHM_UNLOCK 1 +#define SQLITE_SHM_LOCK 2 +#define SQLITE_SHM_SHARED 4 +#define SQLITE_SHM_EXCLUSIVE 8 + +/* +** CAPI3REF: Maximum xShmLock index +** +** The xShmLock method on [sqlite3_io_methods] may use values +** between 0 and this upper bound as its "offset" argument. +** The SQLite core will never attempt to acquire or release a +** lock outside of this range +*/ +#define SQLITE_SHM_NLOCK 8 + + +/* +** CAPI3REF: Initialize The SQLite Library +** +** ^The sqlite3_initialize() routine initializes the +** SQLite library. ^The sqlite3_shutdown() routine +** deallocates any resources that were allocated by sqlite3_initialize(). +** These routines are designed to aid in process initialization and +** shutdown on embedded systems. Workstation applications using +** SQLite normally do not need to invoke either of these routines. +** +** A call to sqlite3_initialize() is an "effective" call if it is +** the first time sqlite3_initialize() is invoked during the lifetime of +** the process, or if it is the first time sqlite3_initialize() is invoked +** following a call to sqlite3_shutdown(). ^(Only an effective call +** of sqlite3_initialize() does any initialization. All other calls +** are harmless no-ops.)^ +** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ +** +** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() +** is not. The sqlite3_shutdown() interface must only be called from a +** single thread. All open [database connections] must be closed and all +** other SQLite resources must be deallocated prior to invoking +** sqlite3_shutdown(). +** +** Among other things, ^sqlite3_initialize() will invoke +** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() +** will invoke sqlite3_os_end(). +** +** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. +** ^If for some reason, sqlite3_initialize() is unable to initialize +** the library (perhaps it is unable to allocate a needed resource such +** as a mutex) it returns an [error code] other than [SQLITE_OK]. +** +** ^The sqlite3_initialize() routine is called internally by many other +** SQLite interfaces so that an application usually does not need to +** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] +** calls sqlite3_initialize() so the SQLite library will be automatically +** initialized when [sqlite3_open()] is called if it has not be initialized +** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] +** compile-time option, then the automatic calls to sqlite3_initialize() +** are omitted and the application must call sqlite3_initialize() directly +** prior to using any other SQLite interface. For maximum portability, +** it is recommended that applications always invoke sqlite3_initialize() +** directly prior to using any other SQLite interface. Future releases +** of SQLite may require this. In other words, the behavior exhibited +** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the +** default behavior in some future release of SQLite. +** +** The sqlite3_os_init() routine does operating-system specific +** initialization of the SQLite library. The sqlite3_os_end() +** routine undoes the effect of sqlite3_os_init(). Typical tasks +** performed by these routines include allocation or deallocation +** of static resources, initialization of global variables, +** setting up a default [sqlite3_vfs] module, or setting up +** a default configuration using [sqlite3_config()]. +** +** The application should never invoke either sqlite3_os_init() +** or sqlite3_os_end() directly. The application should only invoke +** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() +** interface is called automatically by sqlite3_initialize() and +** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate +** implementations for sqlite3_os_init() and sqlite3_os_end() +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time +** option) the application must supply a suitable implementation for +** sqlite3_os_init() and sqlite3_os_end(). An application-supplied +** implementation of sqlite3_os_init() or sqlite3_os_end() +** must return [SQLITE_OK] on success and some other [error code] upon +** failure. +*/ +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); + +/* +** CAPI3REF: Configuring The SQLite Library +** +** The sqlite3_config() interface is used to make global configuration +** changes to SQLite in order to tune SQLite to the specific needs of +** the application. The default configuration is recommended for most +** applications and so this routine is usually not necessary. It is +** provided to support rare applications with unusual needs. +** +** The sqlite3_config() interface is not threadsafe. The application +** must insure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. Furthermore, sqlite3_config() +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** +** The first argument to sqlite3_config() is an integer +** [configuration option] that determines +** what property of SQLite is to be configured. Subsequent arguments +** vary depending on the [configuration option] +** in the first argument. +** +** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. +** ^If the option is unknown or SQLite is unable to set the option +** then this routine returns a non-zero [error code]. +*/ +SQLITE_API int sqlite3_config(int, ...); + +/* +** CAPI3REF: Configure database connections +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. The interface is similar to +** [sqlite3_config()] except that the changes apply to a single +** [database connection] (specified in the first argument). +** +** The second argument to sqlite3_db_config(D,V,...) is the +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** that indicates what aspect of the [database connection] is being configured. +** Subsequent arguments vary depending on the configuration verb. +** +** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if +** the call is considered successful. +*/ +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Memory Allocation Routines +** +** An instance of this object defines the interface between SQLite +** and low-level memory allocation routines. +** +** This object is used in only one place in the SQLite interface. +** A pointer to an instance of this object is the argument to +** [sqlite3_config()] when the configuration option is +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications +** and that this object is only useful to a tiny minority of applications +** with specialized memory allocation requirements. This object is +** also used during testing of SQLite in order to specify an alternative +** memory allocator that simulates memory out-of-memory conditions in +** order to verify that SQLite recovers gracefully from such +** conditions. +** +** The xMalloc, xRealloc, and xFree methods must work like the +** malloc(), realloc() and free() functions from the standard C library. +** ^SQLite guarantees that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** +** xSize should return the allocated size of a memory allocation +** previously obtained from xMalloc or xRealloc. The allocated size +** is always at least as big as the requested size but may be larger. +** +** The xRoundup method returns what would be the allocated size of +** a memory allocation given a particular requested size. Most memory +** allocators round up memory allocations at least to the next multiple +** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. +** +** The xInit method initializes the memory allocator. (For example, +** it might allocate any require mutexes or initialize internal data +** structures. The xShutdown method is invoked (indirectly) by +** [sqlite3_shutdown()] and should deallocate any resources acquired +** by xInit. The pAppData pointer is used as the only parameter to +** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +*/ +typedef struct sqlite3_mem_methods sqlite3_mem_methods; +struct sqlite3_mem_methods { + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ +}; + +/* +** CAPI3REF: Configuration Options +** KEYWORDS: {configuration option} +** +** These constants are the available integer configuration options that +** can be passed as the first argument to the [sqlite3_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_config()] to make sure that +** the call worked. The [sqlite3_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Single-thread. In other words, it disables +** all mutexing and puts SQLite into a mode where it can only be used +** by a single thread. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to change the [threading mode] from its default +** value of Single-thread and so [sqlite3_config()] will return +** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD +** configuration option.
+** +** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Multi-thread. In other words, it disables +** mutexing on [database connection] and [prepared statement] objects. +** The application is responsible for serializing access to +** [database connections] and [prepared statements]. But other mutexes +** are enabled so that SQLite will be safe to use in a multi-threaded +** environment as long as no two threads attempt to use the same +** [database connection] at the same time. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Multi-thread [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_MULTITHREAD configuration option.
+** +** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Serialized. In other words, this option enables +** all mutexes including the recursive +** mutexes on [database connection] and [prepared statement] objects. +** In this mode (which is the default when SQLite is compiled with +** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access +** to [database connections] and [prepared statements] so that the +** application is free to use the same [database connection] or the +** same [prepared statement] in different threads at the same time. +** ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Serialized [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_SERIALIZED configuration option.
+** +** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The argument specifies +** alternative low-level memory allocation routines to be used in place of +** the memory allocation routines built into SQLite.)^ ^SQLite makes +** its own private copy of the content of the [sqlite3_mem_methods] structure +** before the [sqlite3_config()] call returns.
+** +** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] +** structure is filled with the currently defined memory allocation routines.)^ +** This option can be used to overload the default memory allocation +** routines with a wrapper that simulations memory allocation failure or +** tracks memory usage, for example.
+** +** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
+**
^This option takes single argument of type int, interpreted as a +** boolean, which enables or disables the collection of memory allocation +** statistics. ^(When memory allocation statistics are disabled, the +** following SQLite interfaces become non-operational: +**
    +**
  • [sqlite3_memory_used()] +**
  • [sqlite3_memory_highwater()] +**
  • [sqlite3_soft_heap_limit64()] +**
  • [sqlite3_status()] +**
)^ +** ^Memory allocation statistics are enabled by default unless SQLite is +** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory +** allocation statistics are disabled by default. +**
+** +** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
+**
^This option specifies a static memory buffer that SQLite can use for +** scratch memory. There are three arguments: A pointer an 8-byte +** aligned memory buffer from which the scratch allocations will be +** drawn, the size of each scratch allocation (sz), +** and the maximum number of scratch allocations (N). The sz +** argument must be a multiple of 16. +** The first argument must be a pointer to an 8-byte aligned buffer +** of at least sz*N bytes of memory. +** ^SQLite will use no more than two scratch buffers per thread. So +** N should be set to twice the expected maximum number of threads. +** ^SQLite will never require a scratch buffer that is more than 6 +** times the database page size. ^If SQLite needs needs additional +** scratch memory beyond what is provided by this configuration option, then +** [sqlite3_malloc()] will be used to obtain the memory needed.
+** +** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
+**
^This option specifies a static memory buffer that SQLite can use for +** the database page cache with the default page cache implementation. +** This configuration should not be used if an application-define page +** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option. +** There are three arguments to this option: A pointer to 8-byte aligned +** memory, the size of each page buffer (sz), and the number of pages (N). +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 32768) plus a little extra for each +** page header. ^The page header size is 20 to 40 bytes depending on +** the host architecture. ^It is harmless, apart from the wasted memory, +** to make sz a little too large. The first +** argument should point to an allocation of at least sz*N bytes of memory. +** ^SQLite will use the memory provided by the first argument to satisfy its +** memory needs for the first N pages that it adds to cache. ^If additional +** page cache memory is needed beyond what is provided by this option, then +** SQLite goes to [sqlite3_malloc()] for the additional storage space. +** The pointer in the first argument must +** be aligned to an 8-byte boundary or subsequent behavior of SQLite +** will be undefined.
+** +** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
+**
^This option specifies a static memory buffer that SQLite will use +** for all of its dynamic memory allocation needs beyond those provided +** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. +** There are three arguments: An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts +** to using its default memory allocator (the system malloc() implementation), +** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the +** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or +** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined. +** The minimum allocation size is capped at 2**12. Reasonable values +** for the minimum allocation size are 2**5 through 2**8.
+** +** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The argument specifies +** alternative low-level mutex routines to be used in place +** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the +** content of the [sqlite3_mutex_methods] structure before the call to +** [sqlite3_config()] returns. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will +** return [SQLITE_ERROR].
+** +** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The +** [sqlite3_mutex_methods] +** structure is filled with the currently defined mutex routines.)^ +** This option can be used to overload the default mutex allocation +** routines with a wrapper used to track mutex usage for performance +** profiling or testing, for example. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will +** return [SQLITE_ERROR].
+** +** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
+**
^(This option takes two arguments that determine the default +** memory allocation for the lookaside memory allocator on each +** [database connection]. The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.)^ ^(This option sets the +** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.)^
+** +** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
+**
^(This option takes a single argument which is a pointer to +** an [sqlite3_pcache_methods2] object. This object specifies the interface +** to a custom page cache implementation.)^ ^SQLite makes a copy of the +** object and uses it for page cache memory allocations.
+** +** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
+**
^(This option takes a single argument which is a pointer to an +** [sqlite3_pcache_methods2] object. SQLite copies of the current +** page cache implementation into that object.)^
+** +** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
+**
The SQLITE_CONFIG_LOG option is used to configure the SQLite +** global [error log]. +** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,int,const char*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked by [sqlite3_log()] to process each logging event. ^If the +** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. +** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is +** passed through as the first parameter to the application-defined logger +** function whenever that function is invoked. ^The second parameter to +** the logger function is a copy of the first parameter to the corresponding +** [sqlite3_log()] call and is intended to be a [result code] or an +** [extended result code]. ^The third parameter passed to the logger is +** log message after formatting via [sqlite3_snprintf()]. +** The SQLite logging interface is not reentrant; the logger function +** supplied by the application must not invoke any SQLite interface. +** In a multi-threaded application, the application-defined logger +** function must be threadsafe.
+** +** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI +**
This option takes a single argument of type int. If non-zero, then +** URI handling is globally enabled. If the parameter is zero, then URI handling +** is globally disabled. If URI handling is globally enabled, all filenames +** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or +** specified as part of [ATTACH] commands are interpreted as URIs, regardless +** of whether or not the [SQLITE_OPEN_URI] flag is set when the database +** connection is opened. If it is globally disabled, filenames are +** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the +** database connection is opened. By default, URI handling is globally +** disabled. The default value may be changed by compiling with the +** [SQLITE_USE_URI] symbol defined. +** +** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN +**
This option takes a single integer argument which is interpreted as +** a boolean in order to enable or disable the use of covering indices for +** full table scans in the query optimizer. The default setting is determined +** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" +** if that compile-time option is omitted. +** The ability to disable the use of covering indices for full table scans +** is because some incorrectly coded legacy applications might malfunction +** malfunction when the optimization is enabled. Providing the ability to +** disable the optimization allows the older, buggy application code to work +** without change even with newer versions of SQLite. +** +** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] +**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE +**
These options are obsolete and should not be used by new code. +** They are retained for backwards compatibility but are now no-ops. +**
+** +** [[SQLITE_CONFIG_SQLLOG]] +**
SQLITE_CONFIG_SQLLOG +**
This option is only available if sqlite is compiled with the +** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should +** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). +** The second should be of type (void*). The callback is invoked by the library +** in three separate circumstances, identified by the value passed as the +** fourth parameter. If the fourth parameter is 0, then the database connection +** passed as the second argument has just been opened. The third argument +** points to a buffer containing the name of the main database file. If the +** fourth parameter is 1, then the SQL statement that the third parameter +** points to has just been executed. Or, if the fourth parameter is 2, then +** the connection being passed as the second parameter is being closed. The +** third parameter is passed NULL In this case. An example of using this +** configuration option can be seen in the "test_sqllog.c" source file in +** the canonical SQLite source tree.
+** +** [[SQLITE_CONFIG_MMAP_SIZE]] +**
SQLITE_CONFIG_MMAP_SIZE +**
SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values +** that are the default mmap size limit (the default setting for +** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. +** The default setting can be overridden by each database connection using +** either the [PRAGMA mmap_size] command, or by using the +** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size +** cannot be changed at run-time. Nor may the maximum allowed mmap size +** exceed the compile-time maximum mmap size set by the +** [SQLITE_MAX_MMAP_SIZE] compile-time option. +** If either argument to this option is negative, then that argument is +** changed to its compile-time default. +**
+*/ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ +#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ +#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ + +/* +** CAPI3REF: Database Connection Configuration Options +** +** These constants are the available integer configuration options that +** can be passed as the second argument to the [sqlite3_db_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_db_config()] to make sure that +** the call worked. ^The [sqlite3_db_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+**
SQLITE_DBCONFIG_LOOKASIDE
+**
^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. +** ^The first argument (the third parameter to [sqlite3_db_config()] is a +** pointer to a memory buffer to use for lookaside memory. +** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb +** may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the +** size of each lookaside buffer slot. ^The third argument is the number of +** slots. The size of the buffer in the first argument must be greater than +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. ^If the second argument to +** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally +** rounded down to the next smaller multiple of 8. ^(The lookaside memory +** configuration for a database connection can only be changed when that +** connection is not currently using lookaside memory, or in other words +** when the "current value" returned by +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. +** Any attempt to change the lookaside memory configuration when lookaside +** memory is in use leaves the configuration unchanged and returns +** [SQLITE_BUSY].)^
+** +**
SQLITE_DBCONFIG_ENABLE_FKEY
+**
^This option is used to enable or disable the enforcement of +** [foreign key constraints]. There should be two additional arguments. +** The first argument is an integer which is 0 to disable FK enforcement, +** positive to enable FK enforcement or negative to leave FK enforcement +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether FK enforcement is off or on +** following this call. The second parameter may be a NULL pointer, in +** which case the FK enforcement setting is not reported back.
+** +**
SQLITE_DBCONFIG_ENABLE_TRIGGER
+**
^This option is used to enable or disable [CREATE TRIGGER | triggers]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable triggers, +** positive to enable triggers or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether triggers are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the trigger setting is not reported back.
+** +**
+*/ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ +#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ + + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes +** +** ^The sqlite3_extended_result_codes() routine enables or disables the +** [extended result codes] feature of SQLite. ^The extended result +** codes are disabled by default for historical compatibility. +*/ +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid +** +** ^Each entry in an SQLite table has a unique 64-bit signed +** integer key called the [ROWID | "rowid"]. ^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. ^If +** the table has a column of type [INTEGER PRIMARY KEY] then that column +** is another alias for the rowid. +** +** ^This routine returns the [rowid] of the most recent +** successful [INSERT] into the database from the [database connection] +** in the first argument. ^As of SQLite version 3.7.7, this routines +** records the last insert rowid of both ordinary tables and [virtual tables]. +** ^If no successful [INSERT]s +** have ever occurred on that database connection, zero is returned. +** +** ^(If an [INSERT] occurs within a trigger or within a [virtual table] +** method, then this routine will return the [rowid] of the inserted +** row as long as the trigger or virtual table method is running. +** But once the trigger or virtual table method ends, the value returned +** by this routine reverts to what it was before the trigger or virtual +** table method began.)^ +** +** ^An [INSERT] that fails due to a constraint violation is not a +** successful [INSERT] and does not change the value returned by this +** routine. ^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. ^(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.)^ +** +** ^For the purposes of this routine, an [INSERT] is considered to +** be successful even if it is subsequently rolled back. +** +** This function is accessible to SQL statements via the +** [last_insert_rowid() SQL function]. +** +** If a separate thread performs a new [INSERT] on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert [rowid], +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert [rowid]. +*/ +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified +** +** ^This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the [database connection] specified by the first parameter. +** ^(Only changes that are directly specified by the [INSERT], [UPDATE], +** or [DELETE] statement are counted. Auxiliary changes caused by +** triggers or [foreign key actions] are not counted.)^ Use the +** [sqlite3_total_changes()] function to find the total number of changes +** including changes caused by triggers and foreign key actions. +** +** ^Changes to a view that are simulated by an [INSTEAD OF trigger] +** are not counted. Only real table changes are counted. +** +** ^(A "row change" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of [REPLACE] constraint resolution, +** rollback, ABORT processing, [DROP TABLE], or by any other +** mechanisms do not count as direct row changes.)^ +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a [CREATE TRIGGER | trigger]. +** Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** ^This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** ^Thus, when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. ^(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. +** However, the number returned does not include changes +** caused by subtriggers since those have their own context.)^ +** +** See also the [sqlite3_total_changes()] interface, the +** [count_changes pragma], and the [changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified +** +** ^This function returns the number of row changes caused by [INSERT], +** [UPDATE] or [DELETE] statements since the [database connection] was opened. +** ^(The count returned by sqlite3_total_changes() includes all changes +** from all [CREATE TRIGGER | trigger] contexts and changes made by +** [foreign key actions]. However, +** the count does not include changes used to implement [REPLACE] constraints, +** do rollbacks or ABORT processing, or [DROP TABLE] processing. The +** count does not include rows of views that fire an [INSTEAD OF trigger], +** though if the INSTEAD OF trigger makes changes of its own, those changes +** are counted.)^ +** ^The sqlite3_total_changes() function counts the changes as soon as +** the statement that makes them is completed (when the statement handle +** is passed to [sqlite3_reset()] or [sqlite3_finalize()]). +** +** See also the [sqlite3_changes()] interface, the +** [count_changes pragma], and the [total_changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query +** +** ^This function causes any pending database operation to abort and +** return at its earliest opportunity. 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. +** +** ^It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. 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 operation is very nearly finished at the time when +** sqlite3_interrupt() is called, then it might not have an opportunity +** to be interrupted and might continue to completion. +** +** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** ^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. +** +** ^The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. ^Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. ^New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** ^A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. +** +** If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +SQLITE_API void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete +** +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. ^These routines return 1 if the input string +** appears to be a complete SQL statement. ^A statement is judged to be +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. ^Whitespace +** and comments that follow the final semicolon are ignored. +** +** ^These routines return 0 if the statement is incomplete. ^If a +** memory allocation fails, then SQLITE_NOMEM is returned. +** +** ^These routines do not parse the SQL statements thus +** will not detect syntactically incorrect SQL. +** +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete.)^ +** +** The input to [sqlite3_complete()] must be a zero-terminated +** UTF-8 string. +** +** The input to [sqlite3_complete16()] must be a zero-terminated +** UTF-16 string in native byte order. +*/ +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** +** ^This routine sets a callback function that might be invoked whenever +** an attempt is made to open a database table that another thread +** or process has locked. +** +** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] +** is returned immediately upon encountering the lock. ^If the busy callback +** is not NULL, then the callback might be invoked with two arguments. +** +** ^The first argument to the busy handler is a copy of the void* pointer which +** is the third argument to sqlite3_busy_handler(). ^The second argument to +** the busy handler callback is the number of times that the busy handler has +** been invoked for this locking event. ^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. +** ^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. ^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. +** 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. +** +** ^The default busy callback is NULL. +** +** ^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. 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. ^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]. ^This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** ^(There can only be a single busy handler defined for each +** [database connection]. Setting a new busy handler clears any +** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] +** will also set or clear the busy handler. +** +** The busy callback should not take any actions which modify the +** database connection that invoked the busy handler. Any such actions +** result in undefined behavior. +** +** A busy handler must not close the database connection +** or [prepared statement] that invoked the busy handler. +*/ +SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout +** +** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps +** for a specified amount of time when a table is locked. ^The handler +** will sleep multiple times until at least "ms" milliseconds of sleeping +** have accumulated. ^After at least "ms" milliseconds of sleeping, +** the handler returns 0 which causes [sqlite3_step()] to return +** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** ^Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** ^(There can only be a single busy handler for a particular +** [database connection] any any given moment. If another busy handler +** was defined (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared.)^ +*/ +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries +** +** This is a legacy interface that is preserved for backwards compatibility. +** Use of this interface is not recommended. +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated UTF-8 strings. +** There are (N+1)*M elements in the array. The first M pointers point +** to zero-terminated strings that contain the names of the columns. +** The remaining entries all point to query results. NULL values result +** in NULL pointers. All other values are in their UTF-8 zero-terminated +** string representation as returned by [sqlite3_column_text()]. +** +** A result table might consist of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** ^(As an example of the result table format, suppose a query result +** is as follows: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
)^ +** +** ^The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter and returns a result table to the +** pointer given in its 3rd parameter. +** +** After the application has finished with the result from sqlite3_get_table(), +** it must pass the result table pointer to sqlite3_free_table() in order to +** release the memory that was malloced. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +*/ +SQLITE_API int sqlite3_get_table( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ +); +SQLITE_API void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions +** +** These routines are work-alikes of the "printf()" family of functions +** from the standard C library. +** +** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. ^Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** ^(The 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. 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. ^(Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer.)^ 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. +** +** ^As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. ^The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). +** +** 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. +** +** ^(The %q option works like %s in that it substitutes a nul-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal.)^ By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, assume the string variable zText 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. +** +** ^(The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes).)^ 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. +** +** ^(The "%z" formatting option works like "%s" but with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string.)^ +*/ +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); + +/* +** CAPI3REF: Memory Allocation Subsystem +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** Windows VFS uses native malloc() and free() for some operations. +** +** ^The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** ^If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. ^If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** ^Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. ^The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. 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. +** 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_realloc(). +** +** ^(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.)^ ^ 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(). +** ^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(). +** ^sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. +** ^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. +** ^If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. +** +** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() +** is always aligned to at least an 8 byte boundary, or to a +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time +** option is used. +** +** 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. +** +** Prior to SQLite version 3.7.10, the Windows OS interface layer called +** 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 were detected, but +** they were reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else pointers obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have +** not yet been released. +** +** The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +*/ +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void sqlite3_free(void*); + +/* +** CAPI3REF: Memory Allocator Statistics +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** routines, which form the built-in memory allocation subsystem. +** +** ^The [sqlite3_memory_used()] routine returns the number of bytes +** of memory currently outstanding (malloced but not freed). +** ^The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] since the high-water mark +** was last reset. ^The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** ^The memory high-water mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. ^The value returned +** by [sqlite3_memory_highwater(1)] is the high-water mark +** prior to the reset. +*/ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Pseudo-Random Number Generator +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random [ROWID | ROWIDs] when inserting new records into a table that +** already uses the largest possible [ROWID]. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** applications to access the same PRNG for other purposes. +** +** ^A call to this routine stores N bytes of randomness into buffer P. +** +** ^The first time this routine is invoked (either internally or by +** the application) the PRNG is seeded using randomness obtained +** from the xRandomness method of the default [sqlite3_vfs] object. +** ^On all subsequent invocations, the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +*/ +SQLITE_API void sqlite3_randomness(int N, void *P); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks +** +** ^This routine registers an authorizer callback with a particular +** [database connection], supplied in the first argument. +** ^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()]. ^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. ^If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then the [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. ^When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. +** +** ^The first parameter to the authorizer callback is a copy of the third +** parameter to the sqlite3_set_authorizer() interface. ^The second parameter +** to the callback is an integer [SQLITE_COPY | action code] that specifies +** the particular action to be authorized. ^The third through sixth parameters +** to the callback are zero-terminated strings that contain additional +** details about the action to be authorized. +** +** ^If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** ^If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. +** +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted source, to ensure that the SQL statements +** do not try to access data 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 [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. +** +** ^(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.)^ ^Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** The authorizer callback must not do anything that will modify +** the database connection that invoked the authorizer callback. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the +** statement might be re-prepared during [sqlite3_step()] due to a +** schema change. Hence, the application should ensure that the +** correct authorizer callback remains in place during the [sqlite3_step()]. +** +** ^Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. +*/ +SQLITE_API int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes +** +** 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. +** +** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] +** from the [sqlite3_vtab_on_conflict()] interface. +*/ +#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 +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorize certain SQL statement actions. 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. +** +** These action code values signify what kind of operation is to be +** authorized. 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. ^(The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable.)^ ^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 /* Operation 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 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** ^The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the +** SQL statement text as the statement first begins executing. +** ^(Additional sqlite3_trace() callbacks might occur +** as each triggered subprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger.)^ +** +** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit +** the length of [bound parameter] expansion in the output of sqlite3_trace(). +** +** ^The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. ^The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. ^The profile callback +** time is in units of nanoseconds, however the current implementation +** is only capable of millisecond resolution so the six least significant +** digits in the time are meaningless. Future versions of SQLite +** might provide greater resolution on the profiler callback. The +** sqlite3_profile() function is considered experimental and is +** subject to change in future versions of SQLite. +*/ +SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks +** +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback +** function X to be invoked periodically during long running calls to +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for +** database connection D. An example use for this +** interface is to keep a GUI updated during a large query. +** +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the number of +** [virtual machine instructions] that are evaluated between successive +** invocations of the callback X. +** +** ^Only a single progress handler may be defined at one time per +** [database connection]; setting a new progress handler cancels the +** old one. ^Setting parameter X to NULL disables the progress handler. +** ^The progress handler is also disabled by setting N to a value less +** than 1. +** +** ^If the progress callback returns non-zero, the operation is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI progress dialog box. +** +** The progress handler callback must not do anything that will modify +** the database connection that invoked the progress handler. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +*/ +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection +** +** ^These routines open an SQLite database file as specified by the +** filename argument. ^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(). ^(A [database connection] handle is usually +** returned in *ppDb, even if an error occurs. The only exception is that +** 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.)^ ^(If the database is opened (and/or created) successfully, then +** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error following a failure of any +** of the sqlite3_open() routines. +** +** ^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. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [database connection] handle should be released by +** passing it to [sqlite3_close()] when it is no longer required. +** +** The sqlite3_open_v2() interface works like sqlite3_open() +** except that it accepts two additional parameters for additional control +** over the new database connection. ^(The flags parameter to +** sqlite3_open_v2() can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ +** +**
+** ^(
[SQLITE_OPEN_READONLY]
+**
The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE]
+**
The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
+**
The database is opened for reading and writing, and is created if +** it does not already exist. This is the behavior that is always used for +** sqlite3_open() and sqlite3_open16().
)^ +**
+** +** If the 3rd parameter to sqlite3_open_v2() is not one of the +** combinations shown above optionally combined with other +** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] +** then the behavior is undefined. +** +** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. ^If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. ^The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. +** +** ^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. ^If the fourth parameter is +** a NULL pointer then the default [sqlite3_vfs] object is used. +** +** ^If the filename is ":memory:", then a private, temporary in-memory database +** is created for the connection. ^This in-memory database will vanish when +** the database connection is closed. Future versions of SQLite might +** make use of additional special filenames that begin with the ":" character. +** It is recommended that when a database filename actually does begin with +** a ":" character you should prefix the filename with a pathname such as +** "./" to avoid ambiguity. +** +** ^If the filename is an empty string, then a private, temporary +** on-disk database will be created. ^This private database will be +** automatically deleted as soon as the database connection is closed. +** +** [[URI filenames in sqlite3_open()]]

URI Filenames

+** +** ^If [URI filename] interpretation is enabled, and the filename argument +** begins with "file:", then the filename is interpreted as a URI. ^URI +** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +** set in the fourth argument to sqlite3_open_v2(), or if it has +** been enabled globally using the [SQLITE_CONFIG_URI] option with the +** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +** As of SQLite version 3.7.7, URI filename interpretation is turned off +** by default, but future releases of SQLite might enable URI filename +** interpretation by default. See "[URI filenames]" for additional +** information. +** +** URI filenames are parsed according to RFC 3986. ^If the URI contains an +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if +** present, is ignored. +** +** ^SQLite uses the path component of the URI as the name of the disk file +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin +** with a '/' (meaning that the authority section is omitted from the URI) +** then the path is interpreted as a relative path. +** ^On windows, the first component of an absolute path +** is a drive specification (e.g. "C:"). +** +** [[core URI query parameters]] +** The query component of a URI may contain parameters that are interpreted +** either by SQLite itself, or by a [VFS | custom VFS implementation]. +** SQLite interprets the following three query parameters: +** +**
    +**
  • vfs: ^The "vfs" parameter may be used to specify the name of +** a VFS object that provides the operating system interface that should +** be used to access the database file on disk. ^If this option is set to +** an empty string the default VFS object is used. ^Specifying an unknown +** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is +** present, then the VFS specified by the option takes precedence over +** the value passed as the fourth parameter to sqlite3_open_v2(). +** +**
  • mode: ^(The mode parameter may be set to either "ro", "rw", +** "rwc", or "memory". Attempting to set it to any other value is +** an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_open_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is +** set to "memory" then a pure [in-memory database] that never reads +** or writes from disk is used. ^It is an error to specify a value for +** the mode parameter that is less restrictive than that specified by +** the flags passed in the third parameter to sqlite3_open_v2(). +** +**
  • cache: ^The cache parameter may be set to either "shared" or +** "private". ^Setting it to "shared" is equivalent to setting the +** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. +** ^If sqlite3_open_v2() is used and the "cache" parameter is present in +** a URI filename, its value overrides any behavior requested by setting +** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. +**
+** +** ^Specifying an unknown parameter in the query component of a URI is not an +** error. Future versions of SQLite might understand additional query +** parameters. See "[query parameters with special meaning to SQLite]" for +** additional information. +** +** [[URI filename examples]]

URI filename examples

+** +** +**
URI filenames Results +**
file:data.db +** Open the file "data.db" in the current directory. +**
file:/home/fred/data.db
+** file:///home/fred/data.db
+** file://localhost/home/fred/data.db
+** Open the database file "/home/fred/data.db". +**
file://darkstar/home/fred/data.db +** An error. "darkstar" is not a recognized authority. +**
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db +** Windows only: Open the file "data.db" on fred's desktop on drive +** C:. Note that the %20 escaping in this example is not strictly +** necessary - space characters can be used literally +** in URI filenames. +**
file:data.db?mode=ro&cache=private +** Open file "data.db" in the current directory for read-only access. +** Regardless of whether or not shared-cache mode is enabled by +** default, use a private cache. +**
file:/home/fred/data.db?vfs=unix-nolock +** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". +**
file:data.db?mode=readonly +** An error. "readonly" is not a valid option for the "mode" parameter. +**
+** +** ^URI hexadecimal escape sequences (%HH) are supported within the path and +** query components of a URI. A hexadecimal escape sequence consists of a +** percent sign - "%" - followed by exactly two hexadecimal digits +** specifying an octet value. ^Before the path or query components of a +** URI filename are interpreted, they are encoded using UTF-8 and all +** hexadecimal escape sequences replaced by a single byte containing the +** corresponding octet. If this process generates an invalid UTF-8 encoding, +** the results are undefined. +** +** 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(). +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various +** features that require the use of temporary files may fail. +** +** See also: [sqlite3_temp_directory] +*/ +SQLITE_API int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API 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: Obtain Values For URI Parameters +** +** These are utility routines, useful to VFS implementations, that check +** to see if a database file was a URI that contained a specific query +** parameter, and if so obtains the value of that query parameter. +** +** If F is the database filename pointer passed into the xOpen() method of +** a VFS implementation when the flags parameter to xOpen() has one or +** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and +** P is the name of the query parameter, then +** sqlite3_uri_parameter(F,P) returns the value of the P +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F +** has no explicit value, then sqlite3_uri_parameter(F,P) returns +** a pointer to an empty string. +** +** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean +** parameter and returns true (1) or false (0) according to the value +** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the +** value of query parameter P is one of "yes", "true", or "on" in any +** case or if the value begins with a non-zero number. The +** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of +** query parameter P is one of "no", "false", or "off" in any case or +** if the value begins with a numeric zero. If P is not a query +** parameter on F or if the value of P is does not match any of the +** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). +** +** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a +** 64-bit signed integer and returns that integer, or D if P does not +** exist. If the value of P is something other than an integer, then +** zero is returned. +** +** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and +** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and +** is not a database file pathname pointer that SQLite passed into the xOpen +** VFS method, then the behavior of this routine is undefined and probably +** undesirable. +*/ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); + + +/* +** CAPI3REF: Error Codes And Messages +** +** ^The sqlite3_errcode() interface returns the numeric [result code] or +** [extended result code] for the most recent failed sqlite3_* API call +** associated with a [database connection]. If a prior API call failed +** but the most recent API call succeeded, the return value from +** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() +** interface is the same except that it always returns the +** [extended result code] even when extended result codes are +** disabled. +** +** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF-8 or UTF-16 respectively. +** ^(Memory to hold the error message string is managed internally. +** The application does not need to worry about freeing the result. +** However, the error string might be overwritten or deallocated by +** subsequent calls to other SQLite interface functions.)^ +** +** ^The sqlite3_errstr() interface returns the English-language text +** that describes the [result code], as UTF-8. +** ^(Memory to hold the error message string is managed internally +** and must not be freed by the application)^. +** +** When the serialized [threading mode] is in use, it might be the +** case that a second error occurs on a separate thread in between +** the time of the first error and the call to these interfaces. +** When that happens, the second error will be reported since these +** interfaces always report the most recent result. To avoid +** this, each thread can obtain exclusive use of the [database connection] D +** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning +** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after +** all calls to the interfaces listed here are completed. +** +** If an interface fails with SQLITE_MISUSE, that means the interface +** was invoked incorrectly by the application. In that case, the +** error code and message may or may not be set. +*/ +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); + +/* +** CAPI3REF: SQL Statement Object +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represents a single SQL statement. +** 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 the 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: Run-time Limits +** +** ^(This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct.)^ +** +** ^If the new limit is a negative number, the limit is unchanged. +** ^(For each limit category SQLITE_LIMIT_NAME there is a +** [limits | hard upper bound] +** set at compile-time by a C preprocessor macro called +** [limits | SQLITE_MAX_NAME]. +** (The "_LIMIT_" in the name is changed to "_MAX_".))^ +** ^Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper bound. +** +** ^Regardless of whether or not the limit was changed, the +** [sqlite3_limit()] interface returns the prior value of the limit. +** ^Hence, to find the current value of a limit without changing it, +** simply invoke this interface with the third parameter set to -1. +** +** Run-time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** web browser that has its own databases for storing history and +** separate databases controlled by JavaScript applications downloaded +** off the Internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attack. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** New run-time limit categories may be added in future releases. +*/ +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories +** KEYWORDS: {limit category} {*limit categories} +** +** These constants define various performance limits +** that can be lowered at run-time using [sqlite3_limit()]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. +** +**
+** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
+**
The maximum size of any string or BLOB or table row, in bytes.
)^ +** +** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
+**
The maximum length of an SQL statement, in bytes.
)^ +** +** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
+**
The maximum number of columns in a table definition or in the +** result set of a [SELECT] or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
)^ +** +** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
+**
The maximum depth of the parse tree on any expression.
)^ +** +** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
+**
The maximum number of terms in a compound SELECT statement.
)^ +** +** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
+**
The maximum number of instructions in a virtual machine program +** used to implement an SQL statement. This limit is not currently +** enforced, though that might be added in some future release of +** SQLite.
)^ +** +** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
+**
The maximum number of arguments on a function.
)^ +** +** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
+**
The maximum number of [ATTACH | attached databases].)^
+** +** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] +** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
+**
The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
)^ +** +** [[SQLITE_LIMIT_VARIABLE_NUMBER]] +** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
+**
The maximum index number of any [parameter] in an SQL statement.)^ +** +** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
+**
The maximum depth of recursion for triggers.
)^ +**
+*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 + +/* +** CAPI3REF: Compiling An SQL Statement +** KEYWORDS: {SQL statement compiler} +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument, "db", is a [database connection] obtained from a +** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or +** [sqlite3_open16()]. The database connection must not have been closed. +** +** 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 use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. +** +** ^If the nByte argument is less than zero, then zSql is read up to the +** first zero terminator. ^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 +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be gained by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes as this saves SQLite from having to +** make a copy of the input string. +** +** ^If pzTail is not NULL then *pzTail is made to point to the first byte +** past the end of the first SQL statement in zSql. These routines only +** compile the first statement in zSql, so *pzTail is left pointing to +** what remains uncompiled. +** +** ^*ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set +** to NULL. ^If the input text contains no SQL (if the input is an empty +** string or a comment) then *ppStmt is set to NULL. +** The calling procedure is responsible for deleting the compiled +** SQL statement using [sqlite3_finalize()] after it has finished with it. +** ppStmt may not be NULL. +** +** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; +** otherwise an [error code] is returned. +** +** 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. +** ^In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave differently in three ways: +** +**
    +**
  1. +** ^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. As many as [SQLITE_MAX_SCHEMA_RETRY] +** retries will occur before sqlite3_step() gives up and returns an error. +**
  2. +** +**
  3. +** ^When an error occurs, [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. ^The legacy behavior was that +** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code +** and the application would have to make a second call to [sqlite3_reset()] +** in order to find the underlying cause of the problem. With the "v2" prepare +** interfaces, the underlying reason for the error is returned immediately. +**
  4. +** +**
  5. +** ^If the specific value bound to [parameter | host parameter] in the +** WHERE clause might influence the choice of query plan for a statement, +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of WHERE-clause [parameter] might influence the +** choice of query plan if the parameter is the left-hand side of a [LIKE] +** or [GLOB] operator or if the parameter is compared to an indexed column +** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. +** the +**
  6. +**
+*/ +SQLITE_API 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 */ +); +SQLITE_API 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 */ +); +SQLITE_API 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 */ +); +SQLITE_API 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 */ +); + +/* +** CAPI3REF: Retrieving Statement SQL +** +** ^This interface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement] if that statement was +** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +*/ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If An SQL Statement Writes The Database +** +** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if +** and only if the [prepared statement] X makes no direct changes to +** the content of the database file. +** +** Note that [application-defined SQL functions] or +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that +** calls [sqlite3_exec()], then the following SQL statement would +** change the database file through side-effects: +** +**
+**    SELECT eval('DELETE FROM t1') FROM t2;
+** 
+** +** But because the [SELECT] statement does not change the database file +** directly, sqlite3_stmt_readonly() would still return true.)^ +** +** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], +** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, +** since the statements themselves do not actually modify the database but +** rather they control the timing of when other statements modify the +** database. ^The [ATTACH] and [DETACH] statements also cause +** sqlite3_stmt_readonly() to return true since, while those statements +** change the configuration of a database connection, they do not make +** changes to the content of the database files on disk. +*/ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** +** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the +** [prepared statement] S has been stepped at least once using +** [sqlite3_step(S)] but has not run to completion and/or has not +** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) +** interface returns false if S is a NULL pointer. If S is not a +** NULL pointer and is not a pointer to a valid [prepared statement] +** object, then the behavior is undefined and probably undesirable. +** +** This interface can be used in combination [sqlite3_next_stmt()] +** to locate all prepared statements associated with a database +** connection that are in need of being reset. This can be used, +** for example, in diagnostic routines to search for prepared +** statements that are holding a transaction open. +*/ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); + +/* +** CAPI3REF: Dynamically Typed Value Object +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} +** +** SQLite uses the sqlite3_value object to represent all values +** that can be stored in a database table. SQLite uses dynamic typing +** for the values it stores. ^Values stored in sqlite3_value objects +** can be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. An internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +** or if SQLite is run in one of reduced mutex modes +** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +** then there is no distinction between protected and unprotected +** sqlite3_value objects and they can be used interchangeably. However, +** for maximum code portability it is recommended that applications +** still make the distinction between protected and unprotected +** sqlite3_value objects even when not strictly required. +** +** ^The sqlite3_value objects that are passed as parameters into the +** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** The [sqlite3_value_blob | sqlite3_value_type()] family of +** interfaces require protected sqlite3_value objects. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. ^A pointer to an sqlite3_context object +** is always first parameter to [application-defined SQL functions]. +** The application-defined SQL function implementation will pass this +** pointer through into calls to [sqlite3_result_int | sqlite3_result()], +** [sqlite3_aggregate_context()], [sqlite3_user_data()], +** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], +** and/or [sqlite3_set_auxdata()]. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements +** KEYWORDS: {host parameter} {host parameters} {host parameter name} +** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** +** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, +** literals may be replaced by a [parameter] that matches one of following +** templates: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifier.)^ ^The values of these +** parameters (also called "host parameter names" or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** ^The first argument to the sqlite3_bind_*() routines is always +** a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. +** +** ^The second argument is the index of the SQL parameter to be set. +** ^The leftmost SQL parameter has an index of 1. ^When the same named +** SQL parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** ^The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_index()] API if desired. ^The index +** for "?NNN" parameters is the value of NNN. +** ^The NNN value must be between 1 and the [sqlite3_limit()] +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). +** +** ^The third argument is the value to bind to the parameter. +** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter +** is ignored and the end result is the same as sqlite3_bind_null(). +** +** ^(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 value, not the number of characters.)^ +** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** is negative, then the length of the string is +** the number of bytes up to the first zero terminator. +** If the fourth parameter to sqlite3_bind_blob() is negative, then +** the behavior is undefined. +** If a non-negative fourth parameter is provided to sqlite3_bind_text() +** or sqlite3_bind_text16() then that parameter must be the byte offset +** where the NUL terminator would occur assuming the string were NUL +** terminated. If any NUL characters occur at byte offsets less than +** the value of the fourth parameter then the resulting string value will +** contain embedded NULs. The result of expressions involving strings +** with embedded NULs is undefined. +** +** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. ^The destructor is called +** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(), +** sqlite3_bind_text(), or sqlite3_bind_text16() fails. +** ^If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** ^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. +** +** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeroes. ^A zeroblob uses a fixed amount of memory +** (just an integer to hold its size) while it is being processed. +** Zeroblobs are intended to serve as placeholders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | incremental BLOB I/O] routines. +** ^A negative value for the zeroblob results in a zero-length BLOB. +** +** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer +** for the [prepared statement] or with a prepared statement for which +** [sqlite3_step()] has been called more recently than [sqlite3_reset()], +** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() +** routine is passed a [prepared statement] that has been finalized, the +** result is undefined and probably harmful. +** +** ^Bindings are not cleared by the [sqlite3_reset()] routine. +** ^Unbound parameters are interpreted as NULL. +** +** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an +** [error code] if anything goes wrong. +** ^[SQLITE_RANGE] is returned if the parameter +** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of SQL Parameters +** +** ^This routine can be used to find the number of [SQL parameters] +** in a [prepared statement]. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** placeholders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** ^(This routine actually returns the index of the largest (rightmost) +** parameter. For all forms except ?NNN, this will correspond to the +** number of unique parameters. If parameters of the ?NNN form are used, +** there may be gaps in the list.)^ +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter +** +** ^The sqlite3_bind_parameter_name(P,N) interface returns +** the name of the N-th [SQL parameter] in the [prepared statement] P. +** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" +** is included as part of the name.)^ +** ^Parameters of the form "?" without a following integer have no name +** and are referred to as "nameless" or "anonymous parameters". +** +** ^The first host parameter has an index of 1, not 0. +** +** ^If the value N is out of range or if the N-th parameter is +** nameless, then NULL is returned. ^The returned string is +** always in UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name +** +** ^Return the index of an SQL parameter given its name. ^The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero +** is returned if no matching parameter is found. ^The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement +** +** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset +** the [sqlite3_bind_blob | bindings] on a [prepared statement]. +** ^Use this routine to reset all host parameters to NULL. +*/ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set +** +** ^Return the number of columns in the result set returned by the +** [prepared statement]. ^This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). +** +** See also: [sqlite3_data_count()] +*/ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set +** +** ^These routines return the name assigned to a particular column +** in the result set of a [SELECT] statement. ^The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF-8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF-16 string. ^The first parameter is the [prepared statement] +** that implements the [SELECT] statement. ^The second parameter is the +** column number. ^The leftmost column is number 0. +** +** ^The returned string pointer is valid until either the [prepared statement] +** is destroyed by [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the next call to +** sqlite3_column_name() or sqlite3_column_name16() on the same column. +** +** ^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. +** +** ^The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +*/ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result +** +** ^These routines provide a means to determine the database, table, and +** table column that is the origin of a particular result column in +** [SELECT] statement. +** ^The name of the database or table or column can be returned as +** either a UTF-8 or UTF-16 string. ^The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** ^The returned string is valid until the [prepared statement] is destroyed +** using [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the same information is requested +** again in a different encoding. +** +** ^The names returned are the original un-aliased names of the +** database, table, and column. +** +** ^The first argument to these interfaces is a [prepared statement]. +** ^These functions return information about the Nth result column returned by +** the statement, where N is the second function argument. +** ^The left-most column is column 0 for these routines. +** +** ^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. ^These routine might also return NULL if a memory allocation error +** occurs. ^Otherwise, they return the name of the attached database, table, +** or column that query result column was extracted from. +** +** ^As with all other SQLite APIs, those whose names end with "16" return +** UTF-16 encoded strings and the other functions return UTF-8. +** +** ^These APIs are only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. +** +** 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. +** +** If two or more threads call one or more +** [sqlite3_column_database_name | column metadata interfaces] +** for the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result +** +** ^(The first parameter is a [prepared statement]. +** 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.)^ ^If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** ^The returned string is always UTF-8 encoded. +** +** ^(For example, given the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** and the following statement to be compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** 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. +*/ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement +** +** After a [prepared statement] has been prepared using either +** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function +** must be called one or more times to evaluate the statement. +** +** The details of the behavior of the 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 legacy 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 [result codes] or +** [extended result codes] 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 an +** 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 [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 (for example, +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [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 [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. +** +** For all versions of SQLite up to and including 3.6.23.1, a call to +** [sqlite3_reset()] was required after sqlite3_step() returned anything +** other than [SQLITE_ROW] before any subsequent invocation of +** sqlite3_step(). Failure to reset the prepared statement using +** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began +** calling [sqlite3_reset()] automatically in this circumstance rather +** than returning [SQLITE_MISUSE]. This is not considered a compatibility +** break because any application that ever receives an SQLITE_MISUSE error +** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option +** can be used to restore the legacy behavior. +** +** 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 [error 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()] interfaces, +** then the more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +*/ +SQLITE_API int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set +** +** ^The sqlite3_data_count(P) interface returns the number of columns in the +** current row of the result set of [prepared statement] P. +** ^If prepared statement P does not have results ready to return +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of +** interfaces) then sqlite3_data_count(P) returns 0. +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. +** ^The sqlite3_data_count(P) routine returns 0 if the previous call to +** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) +** will return non-zero if previous call to [sqlite3_step](P) returned +** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] +** where it always returns zero since each step of that multi-step +** pragma returns 0 columns of data. +** +** See also: [sqlite3_column_count()] +*/ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes +** KEYWORDS: SQLITE_TEXT +** +** ^(Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
)^ +** +** 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: Result Values From A Query +** KEYWORDS: {column access functions} +** +** These routines form the "result set" interface. +** +** ^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 [prepared 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 leftmost column of the result set has the index 0. +** ^The number of columns in the result can be determined using +** [sqlite3_column_count()]. +** +** If the SQL statement does not currently point to a valid row, or if 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()] have been called 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 the +** [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. +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. +** +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts +** the string to UTF-16 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes16() uses +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. +** +** ^The values returned by [sqlite3_column_bytes()] and +** [sqlite3_column_bytes16()] do not include the zero terminators at the end +** of the string. ^For clarity: the values returned by +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of +** bytes in the string, not the number of characters. +** +** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero-terminated. ^The return +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. +** +** ^The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like [sqlite3_value_int()], [sqlite3_value_text()], +** or [sqlite3_value_bytes()], then the behavior is undefined. +** +** 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 perform 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 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 +** own equivalent 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 references will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometimes they +** are 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 calls +** 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].)^ +*/ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object +** +** ^The sqlite3_finalize() function is called to delete a [prepared statement]. +** ^If the most recent evaluation of the statement encountered no errors +** or if the statement is never been evaluated, then sqlite3_finalize() returns +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then +** sqlite3_finalize(S) returns the appropriate [error code] or +** [extended error code]. +** +** ^The sqlite3_finalize(S) routine can be called at any point during +** the life cycle of [prepared statement] S: +** before statement S is ever evaluated, after +** one or more calls to [sqlite3_reset()], or after any call +** to [sqlite3_step()] regardless of whether or not the statement has +** completed execution. +** +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. +** +** The application must finalize every [prepared statement] in order to avoid +** resource leaks. It is a grievous error for the application to try to use +** a prepared statement after it has been finalized. Any use of a prepared +** statement after it has been finalized can result in undefined and +** undesirable behavior such as segfaults and heap corruption. +*/ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object +** +** The sqlite3_reset() function is called to reset a [prepared 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. +** +** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** ^The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. +*/ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions +** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} +** +** ^These functions (collectively known as "function creation routines") +** are used to add SQL functions or aggregates or to redefine the behavior +** of existing SQL functions or aggregates. The only differences between +** these routines are the text encoding expected for +** the second parameter (the name of the function being created) +** and the presence or absence of a destructor callback for +** the application data pointer. +** +** ^The first parameter is the [database connection] to which the SQL +** function is to be added. ^If an application uses more than one database +** connection then application-defined SQL functions must be added +** to each database connection separately. +** +** ^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 in a UTF-8 +** representation, exclusive of the zero-terminator. ^Note that the name +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** ^Any attempt to create a function with a longer name +** will result in [SQLITE_MISUSE] being returned. +** +** ^The third parameter (nArg) +** is the number of arguments that the SQL function or +** aggregate takes. ^If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. +** +** ^The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Every SQL function implementation must be able to work +** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. ^An application may +** 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 sixth, seventh and eighth 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 must be passed as the xStep and xFinal +** parameters. ^An aggregate SQL function requires an implementation of xStep +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing +** SQL function or aggregate, pass NULL pointers for all three function +** callbacks. +** +** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +** then it is destructor for the application data pointer. +** The destructor is invoked when the function is deleted, either by being +** overloaded or when the database connection closes.)^ +** ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. +** ^When the destructor callback of the tenth parameter is invoked, it +** is passed a single argument which is a copy of the application data +** pointer which was the fifth parameter to sqlite3_create_function_v2(). +** +** ^It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing preferred text encodings. ^SQLite will use +** the implementation that most closely matches the way in which the +** SQL function is used. ^A function implementation with a non-negative +** nArg parameter is a better match than a function implementation with +** a negative nArg. ^A function where the preferred text encoding +** matches the database encoding is a better +** match than a function where the encoding is different. +** ^A function where the encoding difference is between UTF16le and UTF16be +** is a closer match than a function where the encoding difference is +** between UTF8 and UTF16. +** +** ^Built-in functions may be overloaded by new application-defined functions. +** +** ^An application-defined function is permitted to call other +** SQLite interfaces. However, such calls must not +** close the database connection nor finalize or reset the prepared +** statement in which the function is running. +*/ +SQLITE_API int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function_v2( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) +); + +/* +** CAPI3REF: Text Encodings +** +** 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: Deprecated Functions +** DEPRECATED +** +** These functions are [deprecated]. In order to maintain +** backwards compatibility with older code, these functions continue +** to be supported. However, new applications should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you what they do. +*/ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), + void*,sqlite3_int64); +#endif + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values +** +** 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 3rd parameter to these callbacks is an array of pointers to +** [protected 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 only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** +** ^These routines work just like the corresponding [column access functions] +** except that these routines take a single [protected sqlite3_value] object +** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. +** +** ^The sqlite3_value_text16() interface extracts a UTF-16 string +** in the native byte-order of the host machine. ^The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF-16 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 performed. Otherwise no conversion occurs. +** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ +** +** Please pay particular attention to the fact that the pointer 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. +*/ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context +** +** Implementations of aggregate SQL functions use this +** routine to allocate memory for storing their state. +** +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite +** allocates N of memory, zeroes out that memory, and returns a pointer +** to the new memory. ^On second and subsequent calls to +** sqlite3_aggregate_context() for the same aggregate function instance, +** the same buffer is returned. Sqlite3_aggregate_context() is normally +** called once for each invocation of the xStep callback and then one +** last time when the xFinal callback is invoked. ^(When no rows match +** an aggregate query, the xStep() callback of the aggregate function +** implementation is never called and xFinal() is called exactly once. +** In those cases, sqlite3_aggregate_context() might be called for the +** first time from within xFinal().)^ +** +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer +** when first called if N is less than or equal to zero or if a memory +** allocate error occurs. +** +** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is +** determined by the N parameter on first successful call. Changing the +** value of N in subsequent call to sqlite3_aggregate_context() within +** the same aggregate function instance will not resize the memory +** allocation.)^ Within the xFinal callback, it is customary to set +** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** pointless memory allocations occur. +** +** ^SQLite automatically frees the memory allocated by +** sqlite3_aggregate_context() when the aggregate query concludes. +** +** The first parameter must be a copy of the +** [sqlite3_context | SQL function context] that is the first parameter +** to the xStep or xFinal callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions +** +** ^The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** This routine must be called from the same thread in which +** the application-defined function is running. +*/ +SQLITE_API void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Database Connection For Functions +** +** ^The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data +** +** The following two functions may be used by scalar SQL functions to +** associate metadata 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 metadata 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 +** metadata 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. +** +** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. ^If no metadata has been ever +** been set for the Nth argument of the function, or if the corresponding +** function parameter has changed since the meta-data was set, +** then sqlite3_get_auxdata() returns a NULL pointer. +** +** ^The sqlite3_set_auxdata() interface saves the metadata +** pointed to by its 3rd parameter as the metadata for the N-th +** argument of the application-defined function. Subsequent +** calls to sqlite3_get_auxdata() might return this data, if it has +** not been destroyed. +** ^If it is not NULL, SQLite will invoke the destructor +** function given by the 4th parameter to sqlite3_set_auxdata() on +** the metadata when the corresponding function parameter changes +** or when the SQL statement completes, whichever comes first. +** +** SQLite is free to call the destructor and drop metadata on any +** parameter of any function at any time. ^The only guarantee is that +** the destructor will be called before the metadata is dropped. +** +** ^(In practice, metadata is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and [parameters].)^ +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior +** +** These are special values 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. +*/ +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 +** +** 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 [parameter binding] family of +** functions used to bind values to host parameters in prepared statements. +** Refer to the [SQL parameter] documentation for additional information. +** +** ^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. +** +** ^The sqlite3_result_zeroblob() interfaces 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. +** +** ^The sqlite3_result_double() interface sets the result from +** an application-defined function to be a floating point value specified +** by its 2nd argument. +** +** ^The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** ^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. ^SQLite interprets the error +** message string from sqlite3_result_error() as UTF-8. ^SQLite +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. ^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. +** ^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. +** ^The sqlite3_result_error() and sqlite3_result_error16() +** routines make a private copy of the error message text before +** they return. Hence, the calling function can deallocate or +** modify the text after they return without harm. +** ^The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. ^By default, +** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. +** +** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an +** error indicating that a string or BLOB is too long to represent. +** +** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an +** error indicating that a memory allocation failed. +** +** ^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. +** ^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. +** +** ^The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** ^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. +** ^SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** ^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. +** ^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. If the 3rd parameter is non-negative, then it +** must be the byte offset into the string where the NUL terminator would +** appear if the string where NUL terminated. If any NUL characters occur +** in the string at a byte offset that is less than the value of the 3rd +** parameter, then the resulting string will contain embedded NULs and the +** result of expressions operating on strings with embedded NULs is undefined. +** ^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. +** ^If the 4th parameter to the sqlite3_result_text* interfaces or to +** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite +** assumes that the text or BLOB result is in constant space and does not +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. +** ^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. +** +** ^The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy the +** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that the [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** ^A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. +** +** If these routines are called from within the different thread +** than the one containing the application-defined function that received +** the [sqlite3_context] pointer, the results are undefined. +*/ +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences +** +** ^These functions add, remove, or modify a [collation] associated +** with the [database connection] specified as the first argument. +** +** ^The name of the collation is a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are +** considered to be the same name. +** +** ^(The third argument (eTextRep) must be one of the constants: +**
    +**
  • [SQLITE_UTF8], +**
  • [SQLITE_UTF16LE], +**
  • [SQLITE_UTF16BE], +**
  • [SQLITE_UTF16], or +**
  • [SQLITE_UTF16_ALIGNED]. +**
)^ +** ^The eTextRep argument determines the encoding of strings passed +** to the collating function callback, xCallback. +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep +** force strings to be UTF16 with native byte order. +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin +** on an even byte address. +** +** ^The fourth argument, pArg, is an application data pointer that is passed +** through as the first argument to the collating function callback. +** +** ^The fifth argument, xCallback, is a pointer to the collating function. +** ^Multiple collating functions can be registered using the same name but +** with different eTextRep parameters and SQLite will use whichever +** function requires the least amount of data transformation. +** ^If the xCallback argument is NULL then the collating function is +** deleted. ^When all collating functions having the same name are deleted, +** that collation is no longer usable. +** +** ^The collating function callback is invoked with a copy of the pArg +** application data pointer and with two strings in the encoding specified +** by the eTextRep argument. The collating function must return an +** integer that is negative, zero, or positive +** if the first string is less than, equal to, or greater than the second, +** respectively. A collating function must always return the same answer +** given the same inputs. If two or more collating functions are registered +** to the same collation name (using different eTextRep values) then all +** must give an equivalent answer when invoked with equivalent strings. +** The collating function must obey the following properties for all +** strings A, B, and C: +** +**
    +**
  1. If A==B then B==A. +**
  2. If A==B and B==C then A==C. +**
  3. If A<B THEN B>A. +**
  4. If A<B and B<C then A<C. +**
+** +** If a collating function fails any of the above constraints and that +** collating function is registered and used, then the behavior of SQLite +** is undefined. +** +** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** with the addition that the xDestroy callback is invoked on pArg when +** the collating function is deleted. +** ^Collating functions are deleted when they are overridden by later +** calls to the collation creation functions or when the +** [database connection] is closed using [sqlite3_close()]. +** +** ^The xDestroy callback is not called if the +** sqlite3_create_collation_v2() function fails. Applications that invoke +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** check the return code and dispose of the application data pointer +** themselves rather than expecting SQLite to deal with it for them. +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards +** compatibility. +** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. +*/ +SQLITE_API int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); +SQLITE_API int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +SQLITE_API int sqlite3_create_collation16( + sqlite3*, + const void *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks +** +** ^To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** [database connection] to be invoked whenever an undefined collation +** sequence is required. +** +** ^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. ^If sqlite3_collation_needed16() is used, +** the names are passed as UTF-16 in machine native byte order. +** ^A call to either function replaces the existing collation-needed callback. +** +** ^(When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], +** or [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence.)^ +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +SQLITE_API int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +SQLITE_API int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +#ifdef SQLITE_HAS_CODEC +/* +** 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. +*/ +SQLITE_API 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. +*/ +SQLITE_API int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +/* +** Specify the activation key for a SEE database. Unless +** activated, none of the SEE routines will work. +*/ +SQLITE_API void sqlite3_activate_see( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +#ifdef SQLITE_ENABLE_CEROD +/* +** Specify the activation key for a CEROD database. Unless +** activated, none of the CEROD routines will work. +*/ +SQLITE_API void sqlite3_activate_cerod( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +/* +** CAPI3REF: Suspend Execution For A Short Time +** +** The sqlite3_sleep() function causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** ^SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. If the xSleep() method +** of the default VFS is not implemented correctly, or not implemented at +** all, then the behavior of sqlite3_sleep() may deviate from the description +** in the previous paragraphs. +*/ +SQLITE_API int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all temporary files +** created by SQLite when using a built-in [sqlite3_vfs | VFS] +** will be placed in that directory.)^ ^If this variable +** is a NULL pointer, then SQLite performs a search for an appropriate +** temporary file directory. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [temp_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [temp_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [temp_store_directory pragma] should be avoided. +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various +** features that require the use of temporary files may fail. Here is an +** example of how to do this using C++ with the Windows Runtime: +** +**
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+**       TemporaryFolder->Path->Data();
+** char zPathBuf[MAX_PATH + 1];
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+**       NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** 
+*/ +SQLITE_API char *sqlite3_temp_directory; + +/* +** CAPI3REF: Name Of The Folder Holding Database Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all database files +** specified with a relative pathname and created or accessed by +** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed +** to be relative to that directory.)^ ^If this variable is a NULL +** pointer, then SQLite assumes that all database files specified +** with a relative pathname are relative to the current directory +** for the process. Only the windows VFS makes use of this global +** variable; it is ignored by the unix VFS. +** +** Changing the value of this variable while a database connection is +** open can result in a corrupt database. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [data_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [data_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [data_store_directory pragma] should be avoided. +*/ +SQLITE_API char *sqlite3_data_directory; + +/* +** CAPI3REF: Test For Auto-Commit Mode +** KEYWORDS: {autocommit mode} +** +** ^The sqlite3_get_autocommit() interface returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. ^Autocommit mode is on by default. +** ^Autocommit mode is disabled by a [BEGIN] statement. +** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out whether SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +SQLITE_API int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement +** +** ^The sqlite3_db_handle interface returns the [database connection] handle +** to which a [prepared statement] belongs. ^The [database connection] +** returned by sqlite3_db_handle is the same [database connection] +** that was the first argument +** to the [sqlite3_prepare_v2()] call (or its variants) that was used to +** create the statement in the first place. +*/ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + +/* +** CAPI3REF: Return The Filename For A Database Connection +** +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database +** connection D, or if database N is a temporary or in-memory database, then +** a NULL pointer is returned. +** +** ^The filename returned by this function is the output of the +** xFullPathname method of the [VFS]. ^In other words, the filename +** will be an absolute pathname, even if the filename used +** to open the database originally was a URI or relative pathname. +*/ +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Determine if a database is read-only +** +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N +** of connection D is read-only, 0 if it is read/write, or -1 if N is not +** the name of a database on connection D. +*/ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Find the next prepared statement +** +** ^This interface returns a pointer to the next [prepared statement] after +** pStmt associated with the [database connection] pDb. ^If pStmt is NULL +** then this interface returns a pointer to the first prepared statement +** associated with the database connection pDb. ^If no prepared statement +** satisfies the conditions of this routine, it returns NULL. +** +** The [database connection] pointer D in a call to +** [sqlite3_next_stmt(D,S)] must refer to an open database +** connection and in particular must not be a NULL pointer. +*/ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks +** +** ^The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is [COMMIT | committed]. +** ^Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** ^The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. +** ^Any callback set by a previous call to sqlite3_rollback_hook() +** for the same database connection is overridden. +** ^The pArg argument is passed through to the callback. +** ^If the callback on a commit hook function returns non-zero, +** then the commit is converted into a rollback. +** +** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions +** return the P argument from the previous call of the same function +** on the same [database connection] D, or NULL for +** the first call for each function on D. +** +** The commit and rollback hook callbacks are not reentrant. +** The callback implementation must not do anything that will modify +** the database connection that invoked the callback. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the commit +** or rollback hook in the first place. +** Note that running any other SQL statements, including SELECT statements, +** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify +** the database connections for the meaning of "modify" in this paragraph. +** +** ^Registering a NULL function disables the callback. +** +** ^When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. ^If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** ^The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** +** ^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. +** ^The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** +** See also the [sqlite3_update_hook()] interface. +*/ +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks +** +** ^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. +** ^Any callback set by a previous call to this function +** for the same database connection is overridden. +** +** ^The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. +** ^The first argument to the callback is a copy of the third argument +** to sqlite3_update_hook(). +** ^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. +** ^The third and fourth arguments to the callback contain pointers to the +** database and table name containing the affected row. +** ^The final callback parameter is the [rowid] of the row. +** ^In the case of an update, this is the [rowid] after the update takes place. +** +** ^(The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence).)^ +** +** ^In the current implementation, the update hook +** is not invoked when duplication rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** +** The update hook implementation must not do anything that will modify +** the database connection that invoked the update hook. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the update hook. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^The sqlite3_update_hook(D,C,P) function +** returns the P argument from the previous call +** on the same [database connection] D, or NULL for +** the first call on D. +** +** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] +** interfaces. +*/ +SQLITE_API void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache +** +** ^(This routine enables or disables the sharing of the database cache +** and schema data structures between [database connection | connections] +** to the same database. Sharing is enabled if the argument is true +** and disabled if the argument is false.)^ +** +** ^Cache sharing is enabled and disabled for an entire process. +** 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. +** +** ^(The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue use the sharing mode +** that was in effect at the time they were opened.)^ +** +** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled +** successfully. An [error code] is returned otherwise.)^ +** +** ^Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +** +** This interface is threadsafe on processors where writing a +** 32-bit integer is atomic. +** +** See Also: [SQLite Shared-Cache Mode] +*/ +SQLITE_API int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory +** +** ^The sqlite3_release_memory() interface attempts to free N bytes +** of heap memory by deallocating non-essential memory allocations +** held by the database library. Memory used to cache database +** pages to improve performance is an example of non-essential memory. +** ^sqlite3_release_memory() returns the number of bytes actually freed, +** which might be more or less than the amount requested. +** ^The sqlite3_release_memory() routine is a no-op returning zero +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** See also: [sqlite3_db_release_memory()] +*/ +SQLITE_API int sqlite3_release_memory(int); + +/* +** CAPI3REF: Free Memory Used By A Database Connection +** +** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap +** memory as possible from database connection D. Unlike the +** [sqlite3_release_memory()] interface, this interface is effect even +** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is +** omitted. +** +** See also: [sqlite3_release_memory()] +*/ +SQLITE_API int sqlite3_db_release_memory(sqlite3*); + +/* +** CAPI3REF: Impose A Limit On Heap Size +** +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the +** soft limit on the amount of heap memory that may be allocated by SQLite. +** ^SQLite strives to keep heap memory utilization below the soft heap +** limit by reducing the number of pages held in the page cache +** as heap memory usages approaches the limit. +** ^The soft heap limit is "soft" because even though SQLite strives to stay +** below the limit, it will exceed the limit rather than generate +** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** is advisory only. +** +** ^The return value from sqlite3_soft_heap_limit64() is the size of +** the soft heap limit prior to the call, or negative in the case of an +** error. ^If the argument N is negative +** then no change is made to the soft heap limit. Hence, the current +** size of the soft heap limit can be determined by invoking +** sqlite3_soft_heap_limit64() with a negative argument. +** +** ^If the argument N is zero then the soft heap limit is disabled. +** +** ^(The soft heap limit is not enforced in the current implementation +** if one or more of following conditions are true: +** +**
    +**
  • The soft heap limit is set to zero. +**
  • Memory accounting is disabled using a combination of the +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. +**
  • An alternative page cache implementation is specified using +** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). +**
  • The page cache allocates from its own memory pool supplied +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than +** from the heap. +**
)^ +** +** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], +** the soft heap limit is enforced on every memory allocation. Without +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced +** when memory is allocated by the page cache. Testing suggests that because +** the page cache is the predominate memory user in SQLite, most +** applications will achieve adequate soft heap limit enforcement without +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** The circumstances under which SQLite will enforce the soft heap limit may +** changes in future releases of SQLite. +*/ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); + +/* +** CAPI3REF: Deprecated Soft Heap Limit Interface +** DEPRECATED +** +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] +** interface. This routine is provided for historical compatibility +** only. All new applications should use the +** [sqlite3_soft_heap_limit64()] interface rather than this one. +*/ +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); + + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table +** +** ^This routine returns metadata about a specific column of a specific +** database table accessible using the [database 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 used by the database engine 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. +** +** ^Metadata 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 metadata is omitted. +** +** ^(
+** +**
Parameter Output
Type
Description +** +**
5th const char* Data type +**
6th const char* Name of default collation sequence +**
7th int True if column has a NOT NULL constraint +**
8th int True if column is part of the PRIMARY KEY +**
9th int True if 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, an [error code] 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 [INTEGER PRIMARY KEY] 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 [error code] is returned and an error message left +** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ +** +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. +*/ +SQLITE_API 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 +** +** ^This interface loads an SQLite extension library from the named file. +** +** ^The sqlite3_load_extension() interface attempts to load an +** [SQLite extension] library contained in the file zFile. If +** the file cannot be loaded directly, attempts are made to load +** with various operating-system specific extensions added. +** So for example, if "samplelib" cannot be loaded, then names like +** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might +** be tried also. +** +** ^The entry point is zProc. +** ^(zProc may be 0, in which case SQLite will try to come up with an +** entry point name on its own. It first tries "sqlite3_extension_init". +** If that does not work, it constructs a name "sqlite3_X_init" where the +** X is consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ +** ^The sqlite3_load_extension() interface returns +** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** ^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()]. The calling function +** should free this memory by calling [sqlite3_free()]. +** +** ^Extension loading must be enabled using +** [sqlite3_enable_load_extension()] prior to calling this API, +** otherwise an error will be returned. +** +** See also the [load_extension() SQL function]. +*/ +SQLITE_API 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 +** +** ^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. +** +** ^Extension loading is off by default. +** ^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. +*/ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Automatically Load Statically Linked Extensions +** +** ^This interface causes the xEntryPoint() function to be invoked for +** each new [database connection] that is created. The idea here is that +** xEntryPoint() is the entry point for a statically linked [SQLite extension] +** that is to be automatically loaded into all new database connections. +** +** ^(Even though the function prototype shows that xEntryPoint() takes +** no arguments and returns void, SQLite invokes xEntryPoint() with three +** arguments and expects and integer result as if the signature of the +** entry point where as follows: +** +**
+**    int xEntryPoint(
+**      sqlite3 *db,
+**      const char **pzErrMsg,
+**      const struct sqlite3_api_routines *pThunk
+**    );
+** 
)^ +** +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg +** is NULL before calling the xEntryPoint(). ^SQLite will invoke +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. +** +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already +** on the list of automatic extensions is a harmless no-op. ^No entry point +** will be called more than once for each database connection that is opened. +** +** See also: [sqlite3_reset_auto_extension()]. +*/ +SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Reset Automatic Extension Loading +** +** ^This interface disables all automatic extensions previously +** registered using [sqlite3_auto_extension()]. +*/ +SQLITE_API void sqlite3_reset_auto_extension(void); + +/* +** 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 stabilizes, 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; + +/* +** CAPI3REF: Virtual Table Object +** KEYWORDS: sqlite3_module {virtual table module} +** +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual tables]. +** This structure consists mostly of methods for the module. +** +** ^A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** ^The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. +*/ +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 methods above are in version 1 of the sqlite_module object. Those + ** below are for version 2 and greater. */ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); +}; + +/* +** CAPI3REF: Virtual Table Indexing Information +** KEYWORDS: sqlite3_index_info +** +** The sqlite3_index_info structure and its substructures is used as part +** of the [virtual table] interface to +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table 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 using one of the +** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ +** ^(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 that are +** relevant 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 the +** [xFilter] method. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. +** +** ^The orderByConsumed means that output from [xFilter]/[xNext] 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 */ +}; + +/* +** CAPI3REF: Virtual Table Constraint Operator Codes +** +** These macros defined the allowed values for the +** [sqlite3_index_info].aConstraint[].op field. Each value represents +** an operator that is part of a constraint term in the wHERE clause of +** a query that uses a [virtual table]. +*/ +#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 + +/* +** CAPI3REF: Register A Virtual Table Implementation +** +** ^These routines are used to register a new [virtual table module] name. +** ^Module names must be registered before +** creating a new [virtual table] using the module and before using a +** preexisting [virtual table] for the module. +** +** ^The module name is registered on the [database connection] specified +** by the first parameter. ^The name of the module is given by the +** second parameter. ^The third parameter is a pointer to +** the implementation of the [virtual table module]. ^The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** ^The sqlite3_create_module_v2() interface has a fifth parameter which +** is a pointer to a destructor for the pClientData. ^SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. ^The destructor will also +** be invoked if the call to sqlite3_create_module_v2() fails. +** ^The sqlite3_create_module() +** interface is equivalent to sqlite3_create_module_v2() with a NULL +** destructor. +*/ +SQLITE_API int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ +); +SQLITE_API int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** CAPI3REF: Virtual Table Instance Object +** KEYWORDS: sqlite3_vtab +** +** Every [virtual table module] implementation uses a subclass +** of this object to describe a particular instance +** of the [virtual table]. 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. +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* NO LONGER USED */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Virtual Table Cursor Object +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** +** Every [virtual table 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 +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cursors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** 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 */ +}; + +/* +** CAPI3REF: Declare The Schema Of A Virtual Table +** +** ^The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); + +/* +** CAPI3REF: Overload A Function For A Virtual Table +** +** ^(Virtual tables can provide alternative implementations of functions +** using the [xFindFunction] method of the [virtual table module]. +** 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 placeholder function that can be overloaded +** by a [virtual table]. +*/ +SQLITE_API 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. +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB +** KEYWORDS: {BLOB handle} {BLOB handles} +** +** An instance of this object represents an open BLOB on which +** [sqlite3_blob_open | incremental BLOB I/O] can be performed. +** ^Objects of this type are 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 +** +** ^(This interfaces opens a [BLOB handle | 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;
+** 
)^ +** +** ^If the flags parameter is non-zero, then the BLOB is opened for read +** and write access. ^If it is zero, the BLOB is opened for read access. +** ^It is not possible to open a column that is part of an index or primary +** key for writing. ^If [foreign key constraints] are enabled, it is +** not possible to open a column that is part of a [child key] for writing. +** +** ^Note that the database name is not the filename that contains +** the database but rather the symbolic name of the database that +** appears after the AS keyword when the database is connected using [ATTACH]. +** ^For the main database file, the database name is "main". +** ^For TEMP tables, the database name is "temp". +** +** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written +** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set +** to be a null pointer.)^ +** ^This function sets the [database connection] error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related +** functions. ^Note that the *ppBlob variable is always initialized in a +** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob +** regardless of the success or failure of this routine. +** +** ^(If the row that a BLOB handle points to is modified by an +** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects +** then the BLOB handle is marked as "expired". +** This is true if any column of the row is changed, even a column +** other than the one the BLOB handle is open on.)^ +** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for +** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. +** ^(Changes written into a BLOB prior to the BLOB expiring are not +** rolled back by the expiration of the BLOB. Such changes will eventually +** commit if the transaction continues to completion.)^ +** +** ^Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. ^The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function can be used, if desired, +** to create an empty, zero-filled blob in which to read or write using +** this interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. +*/ +SQLITE_API int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Move a BLOB Handle to a New Row +** +** ^This function is used to move an existing blob handle so that it points +** to a different row of the same database table. ^The new row is identified +** by the rowid value passed as the second argument. Only the row can be +** changed. ^The database, table and column on which the blob handle is open +** remain the same. Moving an existing blob handle to a new row can be +** faster than closing the existing handle and opening a new one. +** +** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - +** it must exist and there must be either a blob or text value stored in +** the nominated column.)^ ^If the new row is not present in the table, or if +** it does not contain a blob or text value, or if another error occurs, an +** SQLite error code is returned and the blob handle is considered aborted. +** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or +** [sqlite3_blob_reopen()] on an aborted blob handle immediately return +** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle +** always returns zero. +** +** ^This function sets the database handle error code and message. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); + +/* +** CAPI3REF: Close A BLOB Handle +** +** ^Closes an open [BLOB handle]. +** +** ^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]. +** ^If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. +** +** ^(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. Any errors that occur during +** closing are reported as a non-zero return value.)^ +** +** ^(The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed.)^ +** +** ^Calling this routine with a null pointer (such as would be returned +** by a failed call to [sqlite3_blob_open()]) is a harmless no-op. +*/ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB +** +** ^Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. ^The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +*/ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally +** +** ^(This function is used to read data from an open [BLOB handle] into a +** caller-supplied buffer. N bytes of data are copied into buffer Z +** from the open BLOB, starting at offset iOffset.)^ +** +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is +** less than zero, [SQLITE_ERROR] is returned and no data is read. +** ^The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to read from an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. +** +** ^(On success, sqlite3_blob_read() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. +*/ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally +** +** ^This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. ^N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset. +** +** ^If the [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]. +** +** ^This function may only modify the contents of the BLOB; it is +** not possible to increase the size of a BLOB using this API. +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is written. ^If N is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** The size of the BLOB (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to write to an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred +** before the [BLOB handle] expired are not rolled back by the +** expiration of the handle, though of course those changes might +** have been overwritten by the statement that expired the BLOB handle +** or by other independent statements. +** +** ^(On success, sqlite3_blob_write() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. +*/ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most SQLite 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. +** +** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. +** ^Names are case sensitive. +** ^Names are zero-terminated UTF-8 strings. +** ^If there is no match, a NULL pointer is returned. +** ^If zVfsName is NULL then the default VFS is returned. +** +** ^New VFSes are registered with sqlite3_vfs_register(). +** ^Each new VFS becomes the default VFS if the makeDflt flag is set. +** ^The same VFS can be registered multiple times without injury. +** ^To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. If two different VFSes with the +** same name are registered, the behavior is undefined. If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. +** ^(If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary.)^ +*/ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes +** +** 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_PTHREADS +**
  • 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_PTHREADS and +** SQLITE_MUTEX_W32 implementations are appropriate for use on 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. In this case the +** application must supply a custom mutex implementation using the +** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function +** before calling sqlite3_initialize() or any other public sqlite3_ +** function that calls sqlite3_initialize().)^ +** +** ^The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. ^If it returns NULL +** that means that a mutex could not be allocated. ^SQLite +** will unwind its stack and return an error. ^(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 +**
  • SQLITE_MUTEX_STATIC_LRU2 +**
)^ +** +** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) +** 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. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. ^SQLite will only request a recursive mutex in +** cases where it really needs one. ^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. +** +** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other +** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return +** a pointer to a static preexisting mutex. ^Six 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. +** +** ^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. ^But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +** +** ^The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. ^SQLite is careful to deallocate every +** dynamic mutex that it allocates. The dynamic mutexes must not be in +** use when they are deallocated. Attempting to deallocate a static +** mutex results in undefined behavior. ^SQLite never deallocates +** a static mutex. +** +** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. ^If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] +** upon successful entry. ^(Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter.)^ ^(If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** SQLite will never exhibit +** such behavior in its own use of mutexes.)^ +** +** ^(Some systems (for example, Windows 95) do not support the operation +** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() +** will always return SQLITE_BUSY. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^ +** +** ^The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. ^(The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. SQLite will +** never do either.)^ +** +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Methods Object +** +** An instance of this structure defines the low-level routines +** used to allocate and use mutexes. +** +** Usually, the default mutex implementations provided by SQLite are +** sufficient, however the user has the option of substituting a custom +** implementation for specialized deployments or systems for which SQLite +** does not provide a suitable implementation. In this case, the user +** creates and populates an instance of this structure to pass +** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. +** Additionally, an instance of this structure can be used as an +** output variable when querying the system for the current mutex +** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. +** +** ^The xMutexInit method defined by this structure is invoked as +** part of system initialization by the sqlite3_initialize() function. +** ^The xMutexInit routine is called by SQLite exactly once for each +** effective call to [sqlite3_initialize()]. +** +** ^The xMutexEnd method defined by this structure is invoked as +** part of system shutdown by the sqlite3_shutdown() function. The +** implementation of this method is expected to release all outstanding +** resources obtained by the mutex methods implementation, especially +** those obtained by the xMutexInit method. ^The xMutexEnd() +** interface is invoked exactly once for each call to [sqlite3_shutdown()]. +** +** ^(The remaining seven methods defined by this structure (xMutexAlloc, +** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and +** xMutexNotheld) implement the following interfaces (respectively): +** +**
    +**
  • [sqlite3_mutex_alloc()]
  • +**
  • [sqlite3_mutex_free()]
  • +**
  • [sqlite3_mutex_enter()]
  • +**
  • [sqlite3_mutex_try()]
  • +**
  • [sqlite3_mutex_leave()]
  • +**
  • [sqlite3_mutex_held()]
  • +**
  • [sqlite3_mutex_notheld()]
  • +**
)^ +** +** The only difference is that the public sqlite3_XXX functions enumerated +** above silently ignore any invocations that pass a NULL pointer instead +** of a valid mutex handle. The implementations of the methods defined +** by this structure are not required to handle this case, the results +** of passing a NULL pointer instead of a valid mutex handle are undefined +** (i.e. it is acceptable to provide an implementation that segfaults if +** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. ^It must be harmless to +** invoke xMutexInit() multiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. ^However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. +*/ +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods { + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + +/* +** CAPI3REF: Mutex Verification Routines +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. ^The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. ^The SQLite core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. ^External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** ^These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. +** +** ^The implementation is not required to provide 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. +** +** ^If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But +** 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. ^The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +#ifndef NDEBUG +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); +#endif + +/* +** CAPI3REF: Mutex Types +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +** +** The set of static mutexes may change from one SQLite release to the +** next. Applications that override the built-in mutex logic must be +** prepared to accommodate additional static mutexes. +*/ +#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 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ + +/* +** CAPI3REF: Retrieve the mutex for a database connection +** +** ^This interface returns a pointer the [sqlite3_mutex] object that +** serializes access to the [database connection] given in the argument +** when the [threading mode] is Serialized. +** ^If the [threading mode] is Single-thread or Multi-thread then this +** routine returns a NULL pointer. +*/ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); + +/* +** CAPI3REF: Low-Level Control Of Database Files +** +** ^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. ^The +** name of the database is "main" for the main database or "temp" for the +** TEMP database, or the name that appears after the AS keyword for +** databases that are added using the [ATTACH] SQL command. +** ^A NULL pointer can be used in place of "main" to refer to the +** main database file. +** ^The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. ^The return value of the xFileControl +** method becomes the return value of this routine. +** +** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** a pointer to the underlying [sqlite3_file] object to be written into +** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** case is a short-circuit path which does not actually invoke the +** underlying sqlite3_io_methods.xFileControl method. +** +** ^If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. ^This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. The underlying xFileControl method might +** also return SQLITE_ERROR. There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface +** +** ^The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. ^The first parameter is an operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +SQLITE_API int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meanings are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FIRST 5 +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 +#define SQLITE_TESTCTRL_FAULT_INSTALL 9 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 +#define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 +#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 +#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 +#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 +#define SQLITE_TESTCTRL_LAST 19 + +/* +** CAPI3REF: SQLite Runtime Status +** +** ^This interface is used to retrieve runtime status information +** about the performance of SQLite, and optionally to reset various +** highwater marks. ^The first argument is an integer code for +** the specific parameter to measure. ^(Recognized integer codes +** are of the form [status parameters | SQLITE_STATUS_...].)^ +** ^The current value of the parameter is returned into *pCurrent. +** ^The highest recorded value is returned in *pHighwater. ^If the +** resetFlag is true, then the highest record value is reset after +** *pHighwater is written. ^(Some parameters do not record the highest +** value. For those parameters +** nothing is written into *pHighwater and the resetFlag is ignored.)^ +** ^(Other parameters record only the highwater mark and not the current +** value. For these latter parameters nothing is written into *pCurrent.)^ +** +** ^The sqlite3_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** This routine is threadsafe but is not atomic. This routine can be +** called while other threads are running the same or different SQLite +** interfaces. However the values returned in *pCurrent and +** *pHighwater reflect the status of SQLite at different points in time +** and it is possible that another thread might change the parameter +** in between the times when *pCurrent and *pHighwater are written. +** +** See also: [sqlite3_db_status()] +*/ +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); + + +/* +** CAPI3REF: Status Parameters +** KEYWORDS: {status parameters} +** +** These integer constants designate various run-time status parameters +** that can be returned by [sqlite3_status()]. +** +**
+** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
+**
This parameter is the current amount of memory checked out +** using [sqlite3_malloc()], either directly or indirectly. The +** figure includes calls made to [sqlite3_malloc()] by the application +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in +** this parameter. The amount returned is the sum of the allocation +** sizes as reported by the xSize method in [sqlite3_mem_methods].
)^ +** +** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
+**
This parameter records the largest memory allocation request +** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their +** internal equivalents). Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
+**
This parameter records the number of separate memory allocations +** currently checked out.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
+**
This parameter returns the number of pages used out of the +** [pagecache memory allocator] that was configured using +** [SQLITE_CONFIG_PAGECACHE]. The +** value returned is in pages, not in bytes.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
+**
This parameter returns the number of bytes of page cache +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] +** buffer and where forced to overflow to [sqlite3_malloc()]. The +** returned value includes allocations that overflowed because they +** where too large (they were larger than the "sz" parameter to +** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because +** no space was left in the page cache.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
+**
This parameter records the largest memory allocation request +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_SCRATCH_USED]] ^(
SQLITE_STATUS_SCRATCH_USED
+**
This parameter returns the number of allocations used out of the +** [scratch memory allocator] configured using +** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +** in bytes. Since a single thread may only have one scratch allocation +** outstanding at time, this parameter also reports the number of threads +** using scratch memory at the same time.
)^ +** +** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
+**
This parameter returns the number of bytes of scratch memory +** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] +** buffer and where forced to overflow to [sqlite3_malloc()]. The values +** returned include overflows because the requested allocation was too +** larger (that is, because the requested allocation was larger than the +** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +** slots were available. +**
)^ +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
SQLITE_STATUS_SCRATCH_SIZE
+**
This parameter records the largest memory allocation request +** handed to [scratch memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
+**
This parameter records the deepest parser stack. It is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ +**
+** +** New status parameters may be added from time to time. +*/ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 +#define SQLITE_STATUS_MALLOC_COUNT 9 + +/* +** CAPI3REF: Database Connection Status +** +** ^This interface is used to retrieve runtime status information +** about a single [database connection]. ^The first argument is the +** database connection object to be interrogated. ^The second argument +** is an integer constant, taken from the set of +** [SQLITE_DBSTATUS options], that +** determines the parameter to interrogate. The set of +** [SQLITE_DBSTATUS options] is likely +** to grow in future releases of SQLite. +** +** ^The current value of the requested parameter is written into *pCur +** and the highest instantaneous value is written into *pHiwtr. ^If +** the resetFlg is true, then the highest instantaneous value is +** reset back down to the current value. +** +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. +*/ +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); + +/* +** CAPI3REF: Status Parameters for database connections +** KEYWORDS: {SQLITE_DBSTATUS options} +** +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. +** +**
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
+**
This parameter returns the number of lookaside memory slots currently +** checked out.
)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
+**
This parameter returns the number malloc attempts that were +** satisfied using lookaside memory. Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
+**
This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to the amount of +** memory requested being larger than the lookaside slot size. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
+**
This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to all lookaside +** memory already being in use. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
SQLITE_DBSTATUS_CACHE_USED
+**
This parameter returns the approximate number of of bytes of heap +** memory used by all pager caches associated with the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. +** +** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
+**
This parameter returns the approximate number of of bytes of heap +** memory used to store the schema for all databases associated +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** ^The full amount of memory used by the schemas is reported, even if the +** schema memory is shared with other database connections due to +** [shared cache mode] being enabled. +** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. +** +** [[SQLITE_DBSTATUS_STMT_USED]] ^(
SQLITE_DBSTATUS_STMT_USED
+**
This parameter returns the approximate number of of bytes of heap +** and lookaside memory used by all prepared statements associated with +** the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
+**
This parameter returns the number of pager cache hits that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
+**
This parameter returns the number of pager cache misses that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
+**
This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
+**
+*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 +#define SQLITE_DBSTATUS_CACHE_USED 1 +#define SQLITE_DBSTATUS_SCHEMA_USED 2 +#define SQLITE_DBSTATUS_STMT_USED 3 +#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 +#define SQLITE_DBSTATUS_CACHE_HIT 7 +#define SQLITE_DBSTATUS_CACHE_MISS 8 +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ + + +/* +** CAPI3REF: Prepared Statement Status +** +** ^(Each prepared statement maintains various +** [SQLITE_STMTSTATUS counters] that measure the number +** of times it has performed specific operations.)^ These counters can +** be used to monitor the performance characteristics of the prepared +** statements. For example, if the number of table steps greatly exceeds +** the number of table searches or result rows, that would tend to indicate +** that the prepared statement is using a full table scan rather than +** an index. +** +** ^(This interface is used to retrieve and reset counter values from +** a [prepared statement]. The first argument is the prepared statement +** object to be interrogated. The second argument +** is an integer code for a specific [SQLITE_STMTSTATUS counter] +** to be interrogated.)^ +** ^The current value of the requested counter is returned. +** ^If the resetFlg is true, then the counter is reset to zero after this +** interface call returns. +** +** See also: [sqlite3_status()] and [sqlite3_db_status()]. +*/ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); + +/* +** CAPI3REF: Status Parameters for prepared statements +** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} +** +** These preprocessor macros define integer codes that name counter +** values associated with the [sqlite3_stmt_status()] interface. +** The meanings of the various counters are as follows: +** +**
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
+**
^This is the number of times that SQLite has stepped forward in +** a table as part of a full table scan. Large numbers for this counter +** may indicate opportunities for performance improvement through +** careful use of indices.
+** +** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
+**
^This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
+** +** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
+**
^This is the number of rows inserted into transient indices that +** were created automatically in order to help joins run faster. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance by adding permanent indices that do not +** need to be reinitialized each time the statement is run.
+**
+*/ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 +#define SQLITE_STMTSTATUS_AUTOINDEX 3 + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache type is opaque. It is implemented by +** the pluggable module. The SQLite core has no knowledge of +** its size or internal structure and never deals with the +** sqlite3_pcache object except by holding and passing pointers +** to the object. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache sqlite3_pcache; + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache_page object represents a single page in the +** page cache. The page cache will allocate instances of this +** object. Various methods of the page cache use pointers to instances +** of this object as parameters or as their return value. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache_page sqlite3_pcache_page; +struct sqlite3_pcache_page { + void *pBuf; /* The content of the page */ + void *pExtra; /* Extra information associated with the page */ +}; + +/* +** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} +** +** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can +** register an alternative page cache implementation by passing in an +** instance of the sqlite3_pcache_methods2 structure.)^ +** In many applications, most of the heap memory allocated by +** SQLite is used for the page cache. +** By implementing a +** custom page cache using this API, an application can better control +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for +** how long. +** +** The alternative page cache mechanism is an +** extreme measure that is only needed by the most demanding applications. +** The built-in page cache is recommended for most uses. +** +** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns.)^ +** +** [[the xInit() page cache method]] +** ^(The xInit() method is called once for each effective +** call to [sqlite3_initialize()])^ +** (usually only once during the lifetime of the process). ^(The xInit() +** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the +** built-in default page cache is used instead of the application defined +** page cache.)^ +** +** [[the xShutdown() page cache method]] +** ^The xShutdown() method is called by [sqlite3_shutdown()]. +** It can be used to clean up +** any outstanding resources before process shutdown, if required. +** ^The xShutdown() method may be NULL. +** +** ^SQLite automatically serializes calls to the xInit method, +** so the xInit method need not be threadsafe. ^The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** ^SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** [[the xCreate() page cache methods]] +** ^SQLite invokes the xCreate() method to construct a new cache instance. +** SQLite will typically create one cache instance for each open database file, +** though this is not guaranteed. ^The +** first parameter, szPage, is the size in bytes of the pages that must +** be allocated by the cache. ^szPage will always a power of two. ^The +** second parameter szExtra is a number of bytes of extra storage +** associated with each page cache entry. ^The szExtra parameter will +** a number less than 250. SQLite will use the +** extra szExtra bytes on each page to store metadata about the underlying +** database page on disk. The value passed into szExtra depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** ^The third argument to xCreate(), bPurgeable, is true if the cache being +** created will be used to cache database pages of a file stored on disk, or +** false if it is used for an in-memory database. The cache implementation +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to +** false will always have the "discard" flag set to true. +** ^Hence, a cache created with bPurgeable false will +** never contain any unpinned pages. +** +** [[the xCachesize() page cache method]] +** ^(The xCachesize() method may be called at any time by SQLite to set the +** suggested maximum cache-size (number of pages stored by) the cache +** instance passed as the first argument. This is the value configured using +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable +** parameter, the implementation is not required to do anything with this +** value; it is advisory only. +** +** [[the xPagecount() page cache methods]] +** The xPagecount() method must return the number of pages currently +** stored in the cache, both pinned and unpinned. +** +** [[the xFetch() page cache methods]] +** The xFetch() method locates a page in the cache and returns a pointer to +** an sqlite3_pcache_page object associated with that page, or a NULL pointer. +** The pBuf element of the returned sqlite3_pcache_page object will be a +** pointer to a buffer of szPage bytes used to store the content of a +** single database page. The pExtra element of sqlite3_pcache_page will be +** a pointer to the szExtra bytes of extra storage that SQLite has requested +** for each entry in the page cache. +** +** The page to be fetched is determined by the key. ^The minimum key value +** is 1. After it has been retrieved using xFetch, the page is considered +** to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** cache implementation should use the value of the createFlag +** parameter to help it determined what action to take: +** +** +**
createFlag Behavior when page is not already in cache +**
0 Do not allocate a new page. Return NULL. +**
1 Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +**
2 Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. +**
+** +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite +** will only use a createFlag of 2 after a prior call with a createFlag of 1 +** failed.)^ In between the to xFetch() calls, SQLite may +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. +** +** [[the xUnpin() page cache method]] +** ^xUnpin() is called by SQLite with a pointer to a currently pinned page +** as its second argument. If the third parameter, discard, is non-zero, +** then the page must be evicted from the cache. +** ^If the discard parameter is +** zero, then the page may be discarded or retained at the discretion of +** page cache implementation. ^The page cache implementation +** may choose to evict unpinned pages at any time. +** +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls +** to xFetch(). +** +** [[the xRekey() page cache methods]] +** The xRekey() method is used to change the key value associated with the +** page passed as the second argument. If the cache +** previously contains an entry associated with newKey, it must be +** discarded. ^Any prior cache entry associated with newKey is guaranteed not +** to be pinned. +** +** When SQLite calls the xTruncate() method, the cache must discard all +** existing cache entries with page numbers (keys) greater than or equal +** to the value of the iLimit parameter passed to xTruncate(). If any +** of these pages are pinned, they are implicitly unpinned, meaning that +** they can be safely discarded. +** +** [[the xDestroy() page cache method]] +** ^The xDestroy() method is used to delete a cache allocated by xCreate(). +** All resources associated with the specified cache should be freed. ^After +** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] +** handle invalid, and will not use it with any other sqlite3_pcache_methods2 +** functions. +** +** [[the xShrink() page cache method]] +** ^SQLite invokes the xShrink() method when it wants the page cache to +** free up as much of heap memory as possible. The page cache implementation +** is not obligated to free any memory, but well-behaved implementations should +** do their best. +*/ +typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; +struct sqlite3_pcache_methods2 { + int iVersion; + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); + void (*xShrink)(sqlite3_pcache*); +}; + +/* +** This is the obsolete pcache_methods object that has now been replaced +** by sqlite3_pcache_methods2. This object is not used by SQLite. It is +** retained in the header file for backwards compatibility only. +*/ +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; +struct sqlite3_pcache_methods { + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + + +/* +** CAPI3REF: Online Backup Object +** +** The sqlite3_backup object records state information about an ongoing +** online backup operation. ^The sqlite3_backup object is created by +** a call to [sqlite3_backup_init()] and is destroyed by a call to +** [sqlite3_backup_finish()]. +** +** See Also: [Using the SQLite Online Backup API] +*/ +typedef struct sqlite3_backup sqlite3_backup; + +/* +** CAPI3REF: Online Backup API. +** +** The backup API copies the content of one database into another. +** It is useful either for creating backups of databases or +** for copying in-memory databases to or from persistent files. +** +** See Also: [Using the SQLite Online Backup API] +** +** ^SQLite holds a write transaction open on the destination database file +** for the duration of the backup operation. +** ^The source database is read-locked only while it is being read; +** it is not locked continuously for the entire backup operation. +** ^Thus, the backup may be performed on a live source database without +** preventing other database connections from +** reading or writing to the source database while the backup is underway. +** +** ^(To perform a backup operation: +**
    +**
  1. sqlite3_backup_init() is called once to initialize the +** backup, +**
  2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
  3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
)^ +** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** [[sqlite3_backup_init()]] sqlite3_backup_init() +** +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database +** and the database name, respectively. +** ^The database name is "main" for the main database, "temp" for the +** temporary database, or the name specified after the AS keyword in +** an [ATTACH] statement for an attached database. +** ^The S and M arguments passed to +** sqlite3_backup_init(D,N,S,M) identify the [database connection] +** and database name of the source database, respectively. +** ^The source and destination [database connections] (parameters S and D) +** must be different or else sqlite3_backup_init(D,N,S,M) will fail with +** an error. +** +** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is +** returned and an error code and error message are stored in the +** destination [database connection] D. +** ^The error code and message for the failed call to sqlite3_backup_init() +** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or +** [sqlite3_errmsg16()] functions. +** ^A successful call to sqlite3_backup_init() returns a pointer to an +** [sqlite3_backup] object. +** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and +** sqlite3_backup_finish() functions to perform the specified backup +** operation. +** +** [[sqlite3_backup_step()]] sqlite3_backup_step() +** +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** the source and destination databases specified by [sqlite3_backup] object B. +** ^If N is negative, all remaining source pages are copied. +** ^If sqlite3_backup_step(B,N) successfully copies N pages and there +** are still more pages to be copied, then the function returns [SQLITE_OK]. +** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages +** from source to destination, then it returns [SQLITE_DONE]. +** ^If an error occurs while running sqlite3_backup_step(B,N), +** then an [error code] is returned. ^As well as [SQLITE_OK] and +** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], +** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. +** +** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if +**
    +**
  1. the destination database was opened read-only, or +**
  2. the destination database is using write-ahead-log journaling +** and the destination and source page sizes differ, or +**
  3. the destination database is an in-memory database and the +** destination and source page sizes differ. +**
)^ +** +** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then +** the [sqlite3_busy_handler | busy-handler function] +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then +** [SQLITE_BUSY] is returned to the caller. ^In this case the call to +** sqlite3_backup_step() can be retried later. ^If the source +** [database connection] +** is being used to write to the source database when sqlite3_backup_step() +** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this +** case the call to sqlite3_backup_step() can be retried later on. ^(If +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle +** to the sqlite3_backup_finish() to release associated resources. +** +** ^The first call to sqlite3_backup_step() obtains an exclusive lock +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete +** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to +** sqlite3_backup_step() obtains a [shared lock] on the source database that +** lasts for the duration of the sqlite3_backup_step() call. +** ^Because the source database is not locked between calls to +** sqlite3_backup_step(), the source database may be modified mid-way +** through the backup process. ^If the source database is modified by an +** external process or via a database connection other than the one being +** used by the backup operation, then the backup will be automatically +** restarted by the next call to sqlite3_backup_step(). ^If the source +** database is modified by the using the same database connection as is used +** by the backup operation, then the backup database is automatically +** updated at the same time. +** +** [[sqlite3_backup_finish()]] sqlite3_backup_finish() +** +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** application wishes to abandon the backup operation, the application +** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). +** ^The sqlite3_backup_finish() interfaces releases all +** resources associated with the [sqlite3_backup] object. +** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any +** active write-transaction on the destination database is rolled back. +** The [sqlite3_backup] object is invalid +** and may not be used following a call to sqlite3_backup_finish(). +** +** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no +** sqlite3_backup_step() errors occurred, regardless or whether or not +** sqlite3_backup_step() completed. +** ^If an out-of-memory condition or IO error occurred during any prior +** sqlite3_backup_step() call on the same [sqlite3_backup] object, then +** sqlite3_backup_finish() returns the corresponding [error code]. +** +** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() +** is not a permanent error and does not affect the return value of +** sqlite3_backup_finish(). +** +** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] +** sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** +** ^Each call to sqlite3_backup_step() sets two values inside +** the [sqlite3_backup] object: the number of pages still to be backed +** up and the total number of pages in the source database file. +** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces +** retrieve these two values, respectively. +** +** ^The values returned by these functions are only updated by +** sqlite3_backup_step(). ^If the source database is modified during a backup +** operation, then the values are not updated to account for any extra +** pages that need to be updated or the size of the source database file +** changing. +** +** Concurrent Usage of Database Handles +** +** ^The source [database connection] may be used by the application for other +** purposes while a backup operation is underway or being initialized. +** ^If SQLite is compiled and configured to support threadsafe database +** connections, then the source database connection may be used concurrently +** from within other threads. +** +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after +** sqlite3_backup_init() is called and before the corresponding call to +** sqlite3_backup_finish(). SQLite does not currently check to see +** if the application incorrectly accesses the destination [database connection] +** and so no error code is reported, but the operations may malfunction +** nevertheless. Use of the destination database connection while a +** backup is in progress might also also cause a mutex deadlock. +** +** If running in [shared cache mode], the application must +** guarantee that the shared cache used by the destination database +** is not accessed while the backup is running. In practice this means +** that the application must guarantee that the disk file being +** backed up to is not accessed by any connection within the process, +** not just the specific connection that was passed to sqlite3_backup_init(). +** +** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** threads may safely make multiple concurrent calls to sqlite3_backup_step(). +** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** APIs are not strictly speaking threadsafe. If they are invoked at the +** same time as another thread is invoking sqlite3_backup_step() it is +** possible that they return invalid values. +*/ +SQLITE_API sqlite3_backup *sqlite3_backup_init( + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ +); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); + +/* +** CAPI3REF: Unlock Notification +** +** ^When running in shared-cache mode, a database operation may fail with +** an [SQLITE_LOCKED] error if the required locks on the shared-cache or +** individual tables within the shared-cache cannot be obtained. See +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke +** when the connection currently holding the required lock relinquishes it. +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. +** +** See Also: [Using the SQLite Unlock Notification Feature]. +** +** ^Shared-cache locks are released when a database connection concludes +** its current transaction, either by committing it or rolling it back. +** +** ^When a connection (known as the blocked connection) fails to obtain a +** shared-cache lock and SQLITE_LOCKED is returned to the caller, the +** identity of the database connection (the blocking connection) that +** has locked the required resource is stored internally. ^After an +** application receives an SQLITE_LOCKED error, it may call the +** sqlite3_unlock_notify() method with the blocked connection handle as +** the first argument to register for a callback that will be invoked +** when the blocking connections current transaction is concluded. ^The +** callback is invoked from within the [sqlite3_step] or [sqlite3_close] +** call that concludes the blocking connections transaction. +** +** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, +** there is a chance that the blocking connection will have already +** concluded its transaction by the time sqlite3_unlock_notify() is invoked. +** If this happens, then the specified callback is invoked immediately, +** from within the call to sqlite3_unlock_notify().)^ +** +** ^If the blocked connection is attempting to obtain a write-lock on a +** shared-cache table, and more than one other connection currently holds +** a read-lock on the same table, then SQLite arbitrarily selects one of +** the other connections to use as the blocking connection. +** +** ^(There may be at most one unlock-notify callback registered by a +** blocked connection. If sqlite3_unlock_notify() is called when the +** blocked connection already has a registered unlock-notify callback, +** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is +** called with a NULL pointer as its second argument, then any existing +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked +** connection using [sqlite3_close()]. +** +** The unlock-notify callback is not reentrant. If an application invokes +** any sqlite3_xxx API functions from within an unlock-notify callback, a +** crash or deadlock may be the result. +** +** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always +** returns SQLITE_OK. +** +** Callback Invocation Details +** +** When an unlock-notify callback is registered, the application provides a +** single void* pointer that is passed to the callback when it is invoked. +** However, the signature of the callback function allows SQLite to pass +** it an array of void* context pointers. The first argument passed to +** an unlock-notify callback is a pointer to an array of void* pointers, +** and the second is the number of entries in the array. +** +** When a blocking connections transaction is concluded, there may be +** more than one blocked connection that has registered for an unlock-notify +** callback. ^If two or more such blocked connections have specified the +** same callback function, then instead of invoking the callback function +** multiple times, it is invoked once with the set of void* context pointers +** specified by the blocked connections bundled together into an array. +** This gives the application an opportunity to prioritize any actions +** related to the set of unblocked database connections. +** +** Deadlock Detection +** +** Assuming that after registering for an unlock-notify callback a +** database waits for the callback to be issued before taking any further +** action (a reasonable assumption), then using this API may cause the +** application to deadlock. For example, if connection X is waiting for +** connection Y's transaction to be concluded, and similarly connection +** Y is waiting on connection X's transaction, then neither connection +** will proceed and the system may remain deadlocked indefinitely. +** +** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +** detection. ^If a given call to sqlite3_unlock_notify() would put the +** system in a deadlocked state, then SQLITE_LOCKED is returned and no +** unlock-notify callback is registered. The system is said to be in +** a deadlocked state if connection A has registered for an unlock-notify +** callback on the conclusion of connection B's transaction, and connection +** B has itself registered for an unlock-notify callback when connection +** A's transaction is concluded. ^Indirect deadlock is also detected, so +** the system is also considered to be deadlocked if connection B has +** registered for an unlock-notify callback on the conclusion of connection +** C's transaction, where connection C is waiting on connection A. ^Any +** number of levels of indirection are allowed. +** +** The "DROP TABLE" Exception +** +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** always appropriate to call sqlite3_unlock_notify(). There is however, +** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, +** SQLite checks if there are any currently executing SELECT statements +** that belong to the same connection. If there are, SQLITE_LOCKED is +** returned. In this case there is no "blocking connection", so invoking +** sqlite3_unlock_notify() results in the unlock-notify callback being +** invoked immediately. If the application then re-attempts the "DROP TABLE" +** or "DROP INDEX" query, an infinite loop might be the result. +** +** One way around this problem is to check the extended error code returned +** by an sqlite3_step() call. ^(If there is a blocking connection, then the +** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in +** the special "DROP TABLE/INDEX" case, the extended error code is just +** SQLITE_LOCKED.)^ +*/ +SQLITE_API int sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); + + +/* +** CAPI3REF: String Comparison +** +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications +** and extensions to compare the contents of two buffers containing UTF-8 +** strings in a case-independent fashion, using the same definition of "case +** independence" that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); + +/* +** CAPI3REF: String Globbing +* +** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches +** the glob pattern P, and it returns non-zero if string X does not match +** the glob pattern P. ^The definition of glob pattern matching used in +** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the +** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case +** sensitive. +** +** Note that this routine returns zero on a match and non-zero if the strings +** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. +*/ +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); + +/* +** CAPI3REF: Error Logging Interface +** +** ^The [sqlite3_log()] interface writes a message into the [error log] +** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. +** ^If logging is enabled, the zFormat string and subsequent arguments are +** used with [sqlite3_snprintf()] to generate the final output string. +** +** The sqlite3_log() interface is intended for use by extensions such as +** virtual tables, collating functions, and SQL functions. While there is +** nothing to prevent an application from calling sqlite3_log(), doing so +** is considered bad form. +** +** The zFormat string must not be NULL. +** +** To avoid deadlocks and other threading problems, the sqlite3_log() routine +** will not use dynamically allocated memory. The log message is stored in +** a fixed-length buffer on the stack. If the log message is longer than +** a few hundred characters, it will be truncated to the length of the +** buffer. +*/ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); + +/* +** CAPI3REF: Write-Ahead Log Commit Hook +** +** ^The [sqlite3_wal_hook()] function is used to register a callback that +** will be invoked each time a database connection commits data to a +** [write-ahead log] (i.e. whenever a transaction is committed in +** [journal_mode | journal_mode=WAL mode]). +** +** ^The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released, so the implementation +** may read, write or [checkpoint] the database as required. +** +** ^The first parameter passed to the callback function when it is invoked +** is a copy of the third parameter passed to sqlite3_wal_hook() when +** registering the callback. ^The second is a copy of the database handle. +** ^The third parameter is the name of the database that was written to - +** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter +** is the number of pages currently in the write-ahead log file, +** including those that were just committed. +** +** The callback function should normally return [SQLITE_OK]. ^If an error +** code is returned, that error will propagate back up through the +** SQLite code base to cause the statement that provoked the callback +** to report an error, though the commit will have still occurred. If the +** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value +** that does not correspond to any valid SQLite error code, the results +** are undefined. +** +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^Note that the +** [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** those overwrite any prior [sqlite3_wal_hook()] settings. +*/ +SQLITE_API void *sqlite3_wal_hook( + sqlite3*, + int(*)(void *,sqlite3*,const char*,int), + void* +); + +/* +** CAPI3REF: Configure an auto-checkpoint +** +** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around +** [sqlite3_wal_hook()] that causes any database on [database connection] D +** to automatically [checkpoint] +** after committing a transaction if there are N or +** more frames in the [write-ahead log] file. ^Passing zero or +** a negative value as the nFrame parameter disables automatic +** checkpoints entirely. +** +** ^The callback registered by this function replaces any existing callback +** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback +** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism +** configured by this function. +** +** ^The [wal_autocheckpoint pragma] can be used to invoke this interface +** from SQL. +** +** ^Every new [database connection] defaults to having the auto-checkpoint +** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. +*/ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); + +/* +** CAPI3REF: Checkpoint a database +** +** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X +** on [database connection] D to be [checkpointed]. ^If X is NULL or an +** empty string, then a checkpoint is run on all databases of +** connection D. ^If the database connection D is not in +** [WAL | write-ahead log mode] then this interface is a harmless no-op. +** +** ^The [wal_checkpoint pragma] can be used to invoke this interface +** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] can be used to cause this interface to be +** run whenever the WAL reaches a certain size threshold. +** +** See also: [sqlite3_wal_checkpoint_v2()] +*/ +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); + +/* +** CAPI3REF: Checkpoint a database +** +** Run a checkpoint operation on WAL database zDb attached to database +** handle db. The specific operation is determined by the value of the +** eMode parameter: +** +**
+**
SQLITE_CHECKPOINT_PASSIVE
+** Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish. Sync the db file if all frames in the log +** are checkpointed. This mode is the same as calling +** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. +** +**
SQLITE_CHECKPOINT_FULL
+** This mode blocks (calls the busy-handler callback) until there is no +** database writer and all readers are reading from the most recent database +** snapshot. It then checkpoints all frames in the log file and syncs the +** database file. This call blocks database writers while it is running, +** but not database readers. +** +**
SQLITE_CHECKPOINT_RESTART
+** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after +** checkpointing the log file it blocks (calls the busy-handler callback) +** until all readers are reading from the database file only. This ensures +** that the next client to write to the database file restarts the log file +** from the beginning. This call blocks database writers while it is running, +** but not database readers. +**
+** +** If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to +** the total number of checkpointed frames (including any that were already +** checkpointed when this function is called). *pnLog and *pnCkpt may be +** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. +** If no values are available because of an error, they are both set to -1 +** before returning to communicate this to the caller. +** +** All calls obtain an exclusive "checkpoint" lock on the database file. If +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a +** busy-handler configured, it will not be invoked in this case. +** +** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive +** "writer" lock on the database file. If the writer lock cannot be obtained +** immediately, and a busy-handler is configured, it is invoked and the writer +** lock retried until either the busy-handler returns 0 or the lock is +** successfully obtained. The busy-handler is also invoked while waiting for +** database readers as described above. If the busy-handler returns 0 before +** the writer lock is obtained or while waiting for database readers, the +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** without blocking any further. SQLITE_BUSY is returned in this case. +** +** If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned to the caller. If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code returned to the caller immediately. If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** databases, SQLITE_OK is returned. +** +** If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If +** zDb is not NULL (or a zero length string) and is not the name of any +** attached database, SQLITE_ERROR is returned to the caller. +*/ +SQLITE_API int sqlite3_wal_checkpoint_v2( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of attached database (or NULL) */ + int eMode, /* SQLITE_CHECKPOINT_* value */ + int *pnLog, /* OUT: Size of WAL log in frames */ + int *pnCkpt /* OUT: Total number of frames checkpointed */ +); + +/* +** CAPI3REF: Checkpoint operation parameters +** +** These constants can be used as the 3rd parameter to +** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] +** documentation for additional information about the meaning and use of +** each of these values. +*/ +#define SQLITE_CHECKPOINT_PASSIVE 0 +#define SQLITE_CHECKPOINT_FULL 1 +#define SQLITE_CHECKPOINT_RESTART 2 + +/* +** CAPI3REF: Virtual Table Interface Configuration +** +** This function may be called by either the [xConnect] or [xCreate] method +** of a [virtual table] implementation to configure +** various facets of the virtual table interface. +** +** If this interface is invoked outside the context of an xConnect or +** xCreate virtual table method then the behavior is undefined. +** +** At present, there is only one option that may be configured using +** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options +** may be added in the future. +*/ +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Virtual Table Configuration Options +** +** These macros define the various options to the +** [sqlite3_vtab_config()] interface that [virtual table] implementations +** can use to customize and optimize their behavior. +** +**
+**
SQLITE_VTAB_CONSTRAINT_SUPPORT +**
Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +** where X is an integer. If X is zero, then the [virtual table] whose +** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not +** support constraints. In this configuration (which is the default) if +** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire +** statement is rolled back as if [ON CONFLICT | OR ABORT] had been +** specified as part of the users SQL statement, regardless of the actual +** ON CONFLICT mode specified. +** +** If X is non-zero, then the virtual table implementation guarantees +** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before +** any modifications to internal or persistent data structures have been made. +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** is able to roll back a statement or database transaction, and abandon +** or continue processing the current SQL statement as appropriate. +** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns +** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode +** had been ABORT. +** +** Virtual table implementations that are required to handle OR REPLACE +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should +** silently replace the appropriate rows within the xUpdate callback and +** return SQLITE_OK. Or, if this is not possible, it may return +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** constraint handling. +**
+*/ +#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 + +/* +** CAPI3REF: Determine The Virtual Table Conflict Policy +** +** This function may only be called from within a call to the [xUpdate] method +** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The +** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], +** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode +** of the SQL statement that triggered the call to the [xUpdate] method of the +** [virtual table]. +*/ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); + +/* +** CAPI3REF: Conflict resolution modes +** +** These constants are returned by [sqlite3_vtab_on_conflict()] to +** inform a [virtual table] implementation what the [ON CONFLICT] mode +** is for the SQL statement being evaluated. +** +** Note that the [SQLITE_IGNORE] constant is also used as a potential +** return value from the [sqlite3_set_authorizer()] callback and that +** [SQLITE_ABORT] is also a [result code]. +*/ +#define SQLITE_ROLLBACK 1 +/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ +#define SQLITE_FAIL 3 +/* #define SQLITE_ABORT 4 // Also an error code */ +#define SQLITE_REPLACE 5 + + + +/* +** 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 + +/* +** 2010 August 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. +** +************************************************************************* +*/ + +#ifndef _SQLITE3RTREE_H_ +#define _SQLITE3RTREE_H_ + + +#if 0 +extern "C" { +#endif + +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; + +/* +** Register a geometry callback named zGeom that can be used as part of an +** R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zGeom(... params ...) +*/ +SQLITE_API int sqlite3_rtree_geometry_callback( + sqlite3 *db, + const char *zGeom, +#ifdef SQLITE_RTREE_INT_ONLY + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), +#else + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), +#endif + void *pContext +); + + +/* +** A pointer to a structure of the following type is passed as the first +** argument to callbacks registered using rtree_geometry_callback(). +*/ +struct sqlite3_rtree_geometry { + void *pContext; /* Copy of pContext passed to s_r_g_c() */ + int nParam; /* Size of array aParam[] */ + double *aParam; /* Parameters passed to SQL geom function */ + void *pUser; /* Callback implementation user data */ + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ +}; + + +#if 0 +} /* end of the 'extern "C"' block */ +#endif + +#endif /* ifndef _SQLITE3RTREE_H_ */ + + +/************** End of sqlite3.h *********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include hash.h in the middle of sqliteInt.h ******************/ +/************** Begin file 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 implementation +** used in SQLite. +*/ +#ifndef _SQLITE_HASH_H_ +#define _SQLITE_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* 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, some of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +** +** All elements of the hash table are on a single doubly-linked list. +** Hash.first points to the head of this list. +** +** There are Hash.htsize buckets. Each bucket points to a spot in +** the global doubly-linked list. The contents of the bucket are the +** element pointed to plus the next _ht.count-1 elements in the list. +** +** Hash.htsize and Hash.ht may be zero. In that case lookup is done +** by a linear search of the global list. For small tables, the +** Hash.ht table is never allocated because if there are few elements +** in the table, it is faster to do a linear search than to manage +** the hash table. +*/ +struct Hash { + unsigned int htsize; /* Number of buckets in the hash table */ + unsigned int count; /* Number of entries in this table */ + HashElem *first; /* The first element of the array */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *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 HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + const char *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +SQLITE_PRIVATE void sqlite3HashInit(Hash*); +SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); +SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); +SQLITE_PRIVATE void sqlite3HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ +** SomeStructure *pData = sqliteHashData(p); +** // do something with pData +** } +*/ +#define sqliteHashFirst(H) ((H)->first) +#define sqliteHashNext(E) ((E)->next) +#define sqliteHashData(E) ((E)->data) +/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ +/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ + +/* +** Number of entries in a hash table +*/ +/* #define sqliteHashCount(H) ((H)->count) // NOT USED */ + +#endif /* _SQLITE_HASH_H_ */ + +/************** End of hash.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include parse.h in the middle of sqliteInt.h *****************/ +/************** Begin file parse.h *******************************************/ +#define TK_SEMI 1 +#define TK_EXPLAIN 2 +#define TK_QUERY 3 +#define TK_PLAN 4 +#define TK_BEGIN 5 +#define TK_TRANSACTION 6 +#define TK_DEFERRED 7 +#define TK_IMMEDIATE 8 +#define TK_EXCLUSIVE 9 +#define TK_COMMIT 10 +#define TK_END 11 +#define TK_ROLLBACK 12 +#define TK_SAVEPOINT 13 +#define TK_RELEASE 14 +#define TK_TO 15 +#define TK_TABLE 16 +#define TK_CREATE 17 +#define TK_IF 18 +#define TK_NOT 19 +#define TK_EXISTS 20 +#define TK_TEMP 21 +#define TK_LP 22 +#define TK_RP 23 +#define TK_AS 24 +#define TK_COMMA 25 +#define TK_ID 26 +#define TK_INDEXED 27 +#define TK_ABORT 28 +#define TK_ACTION 29 +#define TK_AFTER 30 +#define TK_ANALYZE 31 +#define TK_ASC 32 +#define TK_ATTACH 33 +#define TK_BEFORE 34 +#define TK_BY 35 +#define TK_CASCADE 36 +#define TK_CAST 37 +#define TK_COLUMNKW 38 +#define TK_CONFLICT 39 +#define TK_DATABASE 40 +#define TK_DESC 41 +#define TK_DETACH 42 +#define TK_EACH 43 +#define TK_FAIL 44 +#define TK_FOR 45 +#define TK_IGNORE 46 +#define TK_INITIALLY 47 +#define TK_INSTEAD 48 +#define TK_LIKE_KW 49 +#define TK_MATCH 50 +#define TK_NO 51 +#define TK_KEY 52 +#define TK_OF 53 +#define TK_OFFSET 54 +#define TK_PRAGMA 55 +#define TK_RAISE 56 +#define TK_REPLACE 57 +#define TK_RESTRICT 58 +#define TK_ROW 59 +#define TK_TRIGGER 60 +#define TK_VACUUM 61 +#define TK_VIEW 62 +#define TK_VIRTUAL 63 +#define TK_REINDEX 64 +#define TK_RENAME 65 +#define TK_CTIME_KW 66 +#define TK_ANY 67 +#define TK_OR 68 +#define TK_AND 69 +#define TK_IS 70 +#define TK_BETWEEN 71 +#define TK_IN 72 +#define TK_ISNULL 73 +#define TK_NOTNULL 74 +#define TK_NE 75 +#define TK_EQ 76 +#define TK_GT 77 +#define TK_LE 78 +#define TK_LT 79 +#define TK_GE 80 +#define TK_ESCAPE 81 +#define TK_BITAND 82 +#define TK_BITOR 83 +#define TK_LSHIFT 84 +#define TK_RSHIFT 85 +#define TK_PLUS 86 +#define TK_MINUS 87 +#define TK_STAR 88 +#define TK_SLASH 89 +#define TK_REM 90 +#define TK_CONCAT 91 +#define TK_COLLATE 92 +#define TK_BITNOT 93 +#define TK_STRING 94 +#define TK_JOIN_KW 95 +#define TK_CONSTRAINT 96 +#define TK_DEFAULT 97 +#define TK_NULL 98 +#define TK_PRIMARY 99 +#define TK_UNIQUE 100 +#define TK_CHECK 101 +#define TK_REFERENCES 102 +#define TK_AUTOINCR 103 +#define TK_ON 104 +#define TK_INSERT 105 +#define TK_DELETE 106 +#define TK_UPDATE 107 +#define TK_SET 108 +#define TK_DEFERRABLE 109 +#define TK_FOREIGN 110 +#define TK_DROP 111 +#define TK_UNION 112 +#define TK_ALL 113 +#define TK_EXCEPT 114 +#define TK_INTERSECT 115 +#define TK_SELECT 116 +#define TK_DISTINCT 117 +#define TK_DOT 118 +#define TK_FROM 119 +#define TK_JOIN 120 +#define TK_USING 121 +#define TK_ORDER 122 +#define TK_GROUP 123 +#define TK_HAVING 124 +#define TK_LIMIT 125 +#define TK_WHERE 126 +#define TK_INTO 127 +#define TK_VALUES 128 +#define TK_INTEGER 129 +#define TK_FLOAT 130 +#define TK_BLOB 131 +#define TK_REGISTER 132 +#define TK_VARIABLE 133 +#define TK_CASE 134 +#define TK_WHEN 135 +#define TK_THEN 136 +#define TK_ELSE 137 +#define TK_INDEX 138 +#define TK_ALTER 139 +#define TK_ADD 140 +#define TK_TO_TEXT 141 +#define TK_TO_BLOB 142 +#define TK_TO_NUMERIC 143 +#define TK_TO_INT 144 +#define TK_TO_REAL 145 +#define TK_ISNOT 146 +#define TK_END_OF_FILE 147 +#define TK_ILLEGAL 148 +#define TK_SPACE 149 +#define TK_UNCLOSED_STRING 150 +#define TK_FUNCTION 151 +#define TK_COLUMN 152 +#define TK_AGG_FUNCTION 153 +#define TK_AGG_COLUMN 154 +#define TK_CONST_FUNC 155 +#define TK_UMINUS 156 +#define TK_UPLUS 157 + +/************** End of parse.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +#include +#include +#include +#include +#include + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define float sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +# undef SQLITE_HAVE_ISNAN +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. +*/ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 4 +#endif + +/* +** Determine whether triggers are recursive by default. This can be +** changed at run-time using a pragma. +*/ +#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS +# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 +#endif + +/* +** Provide a default value for SQLITE_TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef SQLITE_TEMP_STORE +# define SQLITE_TEMP_STORE 1 +# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */ +#endif + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# ifdef HAVE_UINT32_T +# define UINT32_TYPE uint32_t +# else +# define UINT32_TYPE unsigned int +# endif +#endif +#ifndef UINT16_TYPE +# ifdef HAVE_UINT16_T +# define UINT16_TYPE uint16_t +# else +# define UINT16_TYPE unsigned short int +# endif +#endif +#ifndef INT16_TYPE +# ifdef HAVE_INT16_T +# define INT16_TYPE int16_t +# else +# define INT16_TYPE short int +# endif +#endif +#ifndef UINT8_TYPE +# ifdef HAVE_UINT8_T +# define UINT8_TYPE uint8_t +# else +# define UINT8_TYPE unsigned char +# endif +#endif +#ifndef INT8_TYPE +# ifdef HAVE_INT8_T +# define INT8_TYPE int8_t +# else +# define INT8_TYPE signed char +# endif +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ +typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ +typedef INT16_TYPE i16; /* 2-byte signed integer */ +typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ +typedef INT8_TYPE i8; /* 1-byte signed integer */ + +/* +** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value +** that can be stored in a u32 without loss of data. The value +** is 0x00000000ffffffff. But because of quirks of some compilers, we +** have to specify the value in the less intuitive manner shown: +*/ +#define SQLITE_MAX_U32 ((((u64)1)<<32)-1) + +/* +** The datatype used to store estimates of the number of rows in a +** table or index. This is an unsigned integer type. For 99.9% of +** the world, a 32-bit integer is sufficient. But a 64-bit integer +** can be used at compile-time if desired. +*/ +#ifdef SQLITE_64BIT_STATS + typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ +#else + typedef u32 tRowcnt; /* 32-bit is the default */ +#endif + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +#ifdef SQLITE_AMALGAMATION +const int sqlite3one = 1; +#else +const int sqlite3one; +#endif +#if defined(i386) || defined(__i386__) || defined(_M_IX86)\ + || defined(__x86_64) || defined(__x86_64__) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +/* +** Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) (((x)+7)&~7) + +/* +** Round down to the nearest multiple of 8 +*/ +#define ROUNDDOWN8(x) ((x)&~7) + +/* +** Assert that the pointer X is aligned to an 8-byte boundary. This +** macro is used only within assert() to verify that the code gets +** all alignment restrictions correct. +** +** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the +** underlying malloc() implemention might return us 4-byte aligned +** pointers. In that case, only verify 4-byte alignment. +*/ +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) +#else +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) +#endif + +/* +** Disable MMAP on platforms where it is known to not work +*/ +#if defined(__OpenBSD__) || defined(__QNXNTO__) +# undef SQLITE_MAX_MMAP_SIZE +# define SQLITE_MAX_MMAP_SIZE 0 +#endif + +/* +** Default maximum size of memory used by memory-mapped I/O in the VFS +*/ +#ifdef __APPLE__ +# include +# if TARGET_OS_IPHONE +# undef SQLITE_MAX_MMAP_SIZE +# define SQLITE_MAX_MMAP_SIZE 0 +# endif +#endif +#ifndef SQLITE_MAX_MMAP_SIZE +# if defined(__linux__) \ + || defined(_WIN32) \ + || (defined(__APPLE__) && defined(__MACH__)) \ + || defined(__sun) +# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ +# else +# define SQLITE_MAX_MMAP_SIZE 0 +# endif +# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ +#endif + +/* +** The default MMAP_SIZE is zero on all platforms. Or, even if a larger +** default MMAP_SIZE is specified at compile-time, make sure that it does +** not exceed the maximum mmap size. +*/ +#ifndef SQLITE_DEFAULT_MMAP_SIZE +# define SQLITE_DEFAULT_MMAP_SIZE 0 +# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */ +#endif +#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE +# undef SQLITE_DEFAULT_MMAP_SIZE +# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE +#endif + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) + +/* +** Determine if the argument is a power of two +*/ +#define IsPowerOfTwo(X) (((X)&((X)-1))==0) + +/* +** The following value as a destructor means to use sqlite3DbFree(). +** The sqlite3DbFree() routine requires two parameters instead of the +** one parameter that destructors normally want. So we have to introduce +** this magic value that the code knows to handle differently. Any +** pointer will work here as long as it is distinct from SQLITE_STATIC +** and SQLITE_TRANSIENT. +*/ +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize) + +/* +** When SQLITE_OMIT_WSD is defined, it means that the target platform does +** not support Writable Static Data (WSD) such as global and static variables. +** All variables must either be on the stack or dynamically allocated from +** the heap. When WSD is unsupported, the variable declarations scattered +** throughout the SQLite code must become constants instead. The SQLITE_WSD +** macro is used for this purpose. And instead of referencing the variable +** directly, we use its constant as a key to lookup the run-time allocated +** buffer that holds real variable. The constant is also the initializer +** for the run-time allocated buffer. +** +** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL +** macros become no-ops and have zero performance impact. +*/ +#ifdef SQLITE_OMIT_WSD + #define SQLITE_WSD const + #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) + #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) +SQLITE_API int sqlite3_wsd_init(int N, int J); +SQLITE_API void *sqlite3_wsd_find(void *K, int L); +#else + #define SQLITE_WSD + #define GLOBAL(t,v) v + #define sqlite3GlobalConfig sqlite3Config +#endif + +/* +** The following macros are used to suppress compiler warnings and to +** make it clear to human readers when a function parameter is deliberately +** left unused within the body of a function. This usually happens when +** a function is called via a function pointer. For example the +** implementation of an SQL aggregate step callback may not use the +** parameter indicating the number of arguments passed to the aggregate, +** if it knows that this is enforced elsewhere. +** +** When a function parameter is not used at all within the body of a function, +** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. +** However, these macros may also be used to suppress warnings related to +** parameters that may or may not be used depending on compilation options. +** For example those parameters only used in assert() statements. In these +** cases the parameters are named as per the usual conventions. +*/ +#define UNUSED_PARAMETER(x) (void)(x) +#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct AutoincInfo AutoincInfo; +typedef struct Bitvec Bitvec; +typedef struct CollSeq CollSeq; +typedef struct Column Column; +typedef struct Db Db; +typedef struct Schema Schema; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct ExprSpan ExprSpan; +typedef struct FKey FKey; +typedef struct FuncDestructor FuncDestructor; +typedef struct FuncDef FuncDef; +typedef struct FuncDefHash FuncDefHash; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct IndexSample IndexSample; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Lookaside Lookaside; +typedef struct LookasideSlot LookasideSlot; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct RowSet RowSet; +typedef struct Savepoint Savepoint; +typedef struct Select Select; +typedef struct SelectDest SelectDest; +typedef struct SrcList SrcList; +typedef struct StrAccum StrAccum; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct Trigger Trigger; +typedef struct TriggerPrg TriggerPrg; +typedef struct TriggerStep TriggerStep; +typedef struct UnpackedRecord UnpackedRecord; +typedef struct VTable VTable; +typedef struct VtabCtx VtabCtx; +typedef struct Walker Walker; +typedef struct WherePlan WherePlan; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque +** pointer types (i.e. FuncDef) defined above. +*/ +/************** Include btree.h in the middle of sqliteInt.h *****************/ +/************** Begin file btree.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 B-Tree file +** subsystem. See comments in the source code for a detailed description +** of what each interface routine does. +*/ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +/* TODO: This definition is just included so other modules compile. It +** needs to be revisited. +*/ +#define SQLITE_N_BTREE_META 10 + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_AUTOVACUUM + #define SQLITE_DEFAULT_AUTOVACUUM 0 +#endif + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; + + +SQLITE_PRIVATE int sqlite3BtreeOpen( + sqlite3_vfs *pVfs, /* VFS to use with this b-tree */ + const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ + Btree **ppBtree, /* Return open Btree* here */ + int flags, /* Flags */ + int vfsFlags /* Flags passed through to VFS open */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +** +** NOTE: These values must match the corresponding PAGER_ values in +** pager.h. +*/ +#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ +#define BTREE_MEMORY 2 /* This is an in-memory DB */ +#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */ +#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */ + +SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); +SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); +SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); +SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); +SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) +SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); +#endif +SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); +SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); +SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); +SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); +SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); +SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); + +SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); +SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); + +SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); + +/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR +** of the flags shown below. +** +** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. +** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data +** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With +** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored +** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL +** indices.) +*/ +#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ +#define BTREE_BLOBKEY 2 /* Table has keys only - no data */ + +SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); +SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); + +SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); +SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); + +SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); + +/* +** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta +** should be one of the following values. The integer values are assigned +** to constants so that the offset of the corresponding field in an +** SQLite database header may be found using the following formula: +** +** offset = 36 + (idx * 4) +** +** For example, the free-page-count field is located at byte offset 36 of +** the database file header. The incr-vacuum-flag field is located at +** byte offset 64 (== 36+4*7). +*/ +#define BTREE_FREE_PAGE_COUNT 0 +#define BTREE_SCHEMA_VERSION 1 +#define BTREE_FILE_FORMAT 2 +#define BTREE_DEFAULT_CACHE_SIZE 3 +#define BTREE_LARGEST_ROOT_PAGE 4 +#define BTREE_TEXT_ENCODING 5 +#define BTREE_USER_VERSION 6 +#define BTREE_INCR_VACUUM 7 +#define BTREE_APPLICATION_ID 8 + +/* +** Values that may be OR'd together to form the second argument of an +** sqlite3BtreeCursorHints() call. +*/ +#define BTREE_BULKLOAD 0x00000001 + +SQLITE_PRIVATE int sqlite3BtreeCursor( + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ +); +SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); +SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); + +SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( + BtCursor*, + UnpackedRecord *pUnKey, + i64 intKey, + int bias, + int *pRes +); +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias, int seekResult); +SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); +SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); +SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); +SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); + +SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); +SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); + +SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *); +SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); +SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); +SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); + +#ifndef NDEBUG +SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); +#endif + +#ifndef SQLITE_OMIT_BTREECOUNT +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); +#endif + +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); +#endif + +/* +** If we are not using shared cache, then there is no need to +** use mutexes to access the BtShared structures. So make the +** Enter and Leave procedures no-ops. +*/ +#ifndef SQLITE_OMIT_SHARED_CACHE +SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); +#else +# define sqlite3BtreeEnter(X) +# define sqlite3BtreeEnterAll(X) +#endif + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE +SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); +SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*); +SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*); +#ifndef NDEBUG + /* These routines are used inside assert() statements only. */ +SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*); +SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*); +SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); +#endif +#else + +# define sqlite3BtreeSharable(X) 0 +# define sqlite3BtreeLeave(X) +# define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeLeaveCursor(X) +# define sqlite3BtreeLeaveAll(X) + +# define sqlite3BtreeHoldsMutex(X) 1 +# define sqlite3BtreeHoldsAllMutexes(X) 1 +# define sqlite3SchemaMutexHeld(X,Y,Z) 1 +#endif + + +#endif /* _BTREE_H_ */ + +/************** End of btree.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include vdbe.h in the middle of sqliteInt.h ******************/ +/************** Begin file vdbe.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. +** +************************************************************************* +** Header file for the Virtual DataBase Engine (VDBE) +** +** This header defines the interface to the virtual database engine +** or VDBE. The VDBE implements an abstract machine that runs a +** simple program to access and modify the underlying database. +*/ +#ifndef _SQLITE_VDBE_H_ +#define _SQLITE_VDBE_H_ +/* #include */ + +/* +** A single VDBE is an opaque structure named "Vdbe". Only routines +** in the source file sqliteVdbe.c are allowed to see the insides +** of this structure. +*/ +typedef struct Vdbe Vdbe; + +/* +** The names of the following types declared in vdbeInt.h are required +** for the VdbeOp definition. +*/ +typedef struct VdbeFunc VdbeFunc; +typedef struct Mem Mem; +typedef struct SubProgram SubProgram; + +/* +** A single instruction of the virtual machine has an opcode +** and as many as three operands. The instruction is recorded +** as an instance of the following structure: +*/ +struct VdbeOp { + u8 opcode; /* What operation to perform */ + signed char p4type; /* One of the P4_xxx constants for p4 */ + u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */ + u8 p5; /* Fifth parameter is an unsigned character */ + int p1; /* First operand */ + int p2; /* Second parameter (often the jump destination) */ + int p3; /* The third parameter */ + union { /* fourth parameter */ + int i; /* Integer value if p4type==P4_INT32 */ + void *p; /* Generic pointer */ + char *z; /* Pointer to data for string (char array) types */ + i64 *pI64; /* Used when p4type is P4_INT64 */ + double *pReal; /* Used when p4type is P4_REAL */ + FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ + VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ + CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ + Mem *pMem; /* Used when p4type is P4_MEM */ + VTable *pVtab; /* Used when p4type is P4_VTAB */ + KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ + int *ai; /* Used when p4type is P4_INTARRAY */ + SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ + int (*xAdvance)(BtCursor *, int *); + } p4; +#ifdef SQLITE_DEBUG + char *zComment; /* Comment to improve readability */ +#endif +#ifdef VDBE_PROFILE + int cnt; /* Number of times this instruction was executed */ + u64 cycles; /* Total time spent executing this instruction */ +#endif +}; +typedef struct VdbeOp VdbeOp; + + +/* +** A sub-routine used to implement a trigger program. +*/ +struct SubProgram { + VdbeOp *aOp; /* Array of opcodes for sub-program */ + int nOp; /* Elements in aOp[] */ + int nMem; /* Number of memory cells required */ + int nCsr; /* Number of cursors required */ + int nOnce; /* Number of OP_Once instructions */ + void *token; /* id that may be used to recursive triggers */ + SubProgram *pNext; /* Next sub-program already visited */ +}; + +/* +** A smaller version of VdbeOp used for the VdbeAddOpList() function because +** it takes up less space. +*/ +struct VdbeOpList { + u8 opcode; /* What operation to perform */ + signed char p1; /* First operand */ + signed char p2; /* Second parameter (often the jump destination) */ + signed char p3; /* Third parameter */ +}; +typedef struct VdbeOpList VdbeOpList; + +/* +** Allowed values of VdbeOp.p4type +*/ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ +#define P4_STATIC (-2) /* Pointer to a static string */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ + +/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure +** is made. That copy is freed when the Vdbe is finalized. But if the +** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still +** gets freed when the Vdbe is finalized so it still should be obtained +** from a single sqliteMalloc(). But no copy is made and the calling +** function should *not* try to free the KeyInfo. +*/ +#define P4_KEYINFO_HANDOFF (-16) +#define P4_KEYINFO_STATIC (-17) + +/* +** The Vdbe.aColName array contains 5n Mem structures, where n is the +** number of columns of data returned by the statement. +*/ +#define COLNAME_NAME 0 +#define COLNAME_DECLTYPE 1 +#define COLNAME_DATABASE 2 +#define COLNAME_TABLE 3 +#define COLNAME_COLUMN 4 +#ifdef SQLITE_ENABLE_COLUMN_METADATA +# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#else +# ifdef SQLITE_OMIT_DECLTYPE +# define COLNAME_N 1 /* Store only the name */ +# else +# define COLNAME_N 2 /* Store the name and decltype */ +# endif +#endif + +/* +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that +** sqlite3VdbeAddOpList() knows that the address is relative. Calling +** the macro again restores the address. +*/ +#define ADDR(X) (-1-(X)) + +/* +** The makefile scans the vdbe.c source file and creates the "opcodes.h" +** header file that defines a number for each opcode used by the VDBE. +*/ +/************** Include opcodes.h in the middle of vdbe.h ********************/ +/************** Begin file opcodes.h *****************************************/ +/* Automatically generated. Do not edit */ +/* See the mkopcodeh.awk script for details */ +#define OP_Goto 1 +#define OP_Gosub 2 +#define OP_Return 3 +#define OP_Yield 4 +#define OP_HaltIfNull 5 +#define OP_Halt 6 +#define OP_Integer 7 +#define OP_Int64 8 +#define OP_Real 130 /* same as TK_FLOAT */ +#define OP_String8 94 /* same as TK_STRING */ +#define OP_String 9 +#define OP_Null 10 +#define OP_Blob 11 +#define OP_Variable 12 +#define OP_Move 13 +#define OP_Copy 14 +#define OP_SCopy 15 +#define OP_ResultRow 16 +#define OP_Concat 91 /* same as TK_CONCAT */ +#define OP_Add 86 /* same as TK_PLUS */ +#define OP_Subtract 87 /* same as TK_MINUS */ +#define OP_Multiply 88 /* same as TK_STAR */ +#define OP_Divide 89 /* same as TK_SLASH */ +#define OP_Remainder 90 /* same as TK_REM */ +#define OP_CollSeq 17 +#define OP_Function 18 +#define OP_BitAnd 82 /* same as TK_BITAND */ +#define OP_BitOr 83 /* same as TK_BITOR */ +#define OP_ShiftLeft 84 /* same as TK_LSHIFT */ +#define OP_ShiftRight 85 /* same as TK_RSHIFT */ +#define OP_AddImm 20 +#define OP_MustBeInt 21 +#define OP_RealAffinity 22 +#define OP_ToText 141 /* same as TK_TO_TEXT */ +#define OP_ToBlob 142 /* same as TK_TO_BLOB */ +#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/ +#define OP_ToInt 144 /* same as TK_TO_INT */ +#define OP_ToReal 145 /* same as TK_TO_REAL */ +#define OP_Eq 76 /* same as TK_EQ */ +#define OP_Ne 75 /* same as TK_NE */ +#define OP_Lt 79 /* same as TK_LT */ +#define OP_Le 78 /* same as TK_LE */ +#define OP_Gt 77 /* same as TK_GT */ +#define OP_Ge 80 /* same as TK_GE */ +#define OP_Permutation 23 +#define OP_Compare 24 +#define OP_Jump 25 +#define OP_And 69 /* same as TK_AND */ +#define OP_Or 68 /* same as TK_OR */ +#define OP_Not 19 /* same as TK_NOT */ +#define OP_BitNot 93 /* same as TK_BITNOT */ +#define OP_Once 26 +#define OP_If 27 +#define OP_IfNot 28 +#define OP_IsNull 73 /* same as TK_ISNULL */ +#define OP_NotNull 74 /* same as TK_NOTNULL */ +#define OP_Column 29 +#define OP_Affinity 30 +#define OP_MakeRecord 31 +#define OP_Count 32 +#define OP_Savepoint 33 +#define OP_AutoCommit 34 +#define OP_Transaction 35 +#define OP_ReadCookie 36 +#define OP_SetCookie 37 +#define OP_VerifyCookie 38 +#define OP_OpenRead 39 +#define OP_OpenWrite 40 +#define OP_OpenAutoindex 41 +#define OP_OpenEphemeral 42 +#define OP_SorterOpen 43 +#define OP_OpenPseudo 44 +#define OP_Close 45 +#define OP_SeekLt 46 +#define OP_SeekLe 47 +#define OP_SeekGe 48 +#define OP_SeekGt 49 +#define OP_Seek 50 +#define OP_NotFound 51 +#define OP_Found 52 +#define OP_IsUnique 53 +#define OP_NotExists 54 +#define OP_Sequence 55 +#define OP_NewRowid 56 +#define OP_Insert 57 +#define OP_InsertInt 58 +#define OP_Delete 59 +#define OP_ResetCount 60 +#define OP_SorterCompare 61 +#define OP_SorterData 62 +#define OP_RowKey 63 +#define OP_RowData 64 +#define OP_Rowid 65 +#define OP_NullRow 66 +#define OP_Last 67 +#define OP_SorterSort 70 +#define OP_Sort 71 +#define OP_Rewind 72 +#define OP_SorterNext 81 +#define OP_Prev 92 +#define OP_Next 95 +#define OP_SorterInsert 96 +#define OP_IdxInsert 97 +#define OP_IdxDelete 98 +#define OP_IdxRowid 99 +#define OP_IdxLT 100 +#define OP_IdxGE 101 +#define OP_Destroy 102 +#define OP_Clear 103 +#define OP_CreateIndex 104 +#define OP_CreateTable 105 +#define OP_ParseSchema 106 +#define OP_LoadAnalysis 107 +#define OP_DropTable 108 +#define OP_DropIndex 109 +#define OP_DropTrigger 110 +#define OP_IntegrityCk 111 +#define OP_RowSetAdd 112 +#define OP_RowSetRead 113 +#define OP_RowSetTest 114 +#define OP_Program 115 +#define OP_Param 116 +#define OP_FkCounter 117 +#define OP_FkIfZero 118 +#define OP_MemMax 119 +#define OP_IfPos 120 +#define OP_IfNeg 121 +#define OP_IfZero 122 +#define OP_AggStep 123 +#define OP_AggFinal 124 +#define OP_Checkpoint 125 +#define OP_JournalMode 126 +#define OP_Vacuum 127 +#define OP_IncrVacuum 128 +#define OP_Expire 129 +#define OP_TableLock 131 +#define OP_VBegin 132 +#define OP_VCreate 133 +#define OP_VDestroy 134 +#define OP_VOpen 135 +#define OP_VFilter 136 +#define OP_VColumn 137 +#define OP_VNext 138 +#define OP_VRename 139 +#define OP_VUpdate 140 +#define OP_Pagecount 146 +#define OP_MaxPgcnt 147 +#define OP_Trace 148 +#define OP_Noop 149 +#define OP_Explain 150 + + +/* Properties such as "out2" or "jump" that are specified in +** comments following the "case" for each opcode in the vdbe.c +** are encoded into bitvectors as follows: +*/ +#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ +#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */ +#define OPFLG_IN1 0x0004 /* in1: P1 is an input */ +#define OPFLG_IN2 0x0008 /* in2: P2 is an input */ +#define OPFLG_IN3 0x0010 /* in3: P3 is an input */ +#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */ +#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */ +#define OPFLG_INITIALIZER {\ +/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\ +/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\ +/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\ +/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\ +/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\ +/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\ +/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\ +/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\ +/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ +/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\ +/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\ +/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\ +/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\ +/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\ +/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\ +/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,} + +/************** End of opcodes.h *********************************************/ +/************** Continuing where we left off in vdbe.h ***********************/ + +/* +** Prototypes for the VDBE interface. See comments on the implementation +** for a description of what each of these routines does. +*/ +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*); +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); +SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); +SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr); +SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); +SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); +SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); +SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); +#endif +SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); +SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); +SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); +SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); +SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); +SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); +#ifndef SQLITE_OMIT_TRACE +SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); +#endif + +SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); + +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); +#endif + + +#ifndef NDEBUG +SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); +# define VdbeComment(X) sqlite3VdbeComment X +SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); +# define VdbeNoopComment(X) sqlite3VdbeNoopComment X +#else +# define VdbeComment(X) +# define VdbeNoopComment(X) +#endif + +#endif + +/************** End of vdbe.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pager.h in the middle of sqliteInt.h *****************/ +/************** Begin file pager.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 page cache +** subsystem. The page cache subsystem reads and writes a file a page +** at a time and provides a journal for rollback. +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** Default maximum size for persistent journal files. A negative +** value means no limit. This value may be overridden using the +** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef u32 Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() in pager.c +** for details. +*/ +#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: These values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_MEMORY 0x0002 /* In-memory database */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** Numeric constants that encode the journalmode. +*/ +#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ +#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ +#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ +#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ + +/* +** Flags that make up the mask passed to sqlite3PagerAcquire(). +*/ +#define PAGER_ACQUIRE_NOCONTENT 0x01 /* Do not load data from disk */ +#define PAGER_ACQUIRE_READONLY 0x02 /* Read-only page is acceptable */ + +/* +** The remainder of this file contains the declarations of the functions +** that make up the Pager sub-system API. See source code comments for +** a detailed description of each routine. +*/ + +/* Open and close a Pager connection. */ +SQLITE_PRIVATE int sqlite3PagerOpen( + sqlite3_vfs*, + Pager **ppPager, + const char*, + int, + int, + int, + void(*)(DbPage*) +); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); + +/* Functions used to configure a Pager object. */ +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); +SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); +SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); +SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); +SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); +SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); +SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); + +/* Functions used to obtain and release page references. */ +SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); + +/* Operations on page references. */ +SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); +SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); +SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); +SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); +SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); +SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); + +/* Functions used to manage pager transactions and savepoints. */ +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); +SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); +SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); +SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); +SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); + +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); +SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); +#endif + +#ifdef SQLITE_ENABLE_ZIPVFS +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); +#endif + +/* Functions used to query pager state and configuration. */ +SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); +SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); +SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); +SQLITE_PRIVATE int sqlite3PagerNosync(Pager*); +SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); +SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); +SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *); +SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); + +/* Functions used to truncate the database file. */ +SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); + +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) +SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *); +#endif + +/* Functions to support testing and debugging. */ +#if !defined(NDEBUG) || defined(SQLITE_TEST) +SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); +SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); +#endif +#ifdef SQLITE_TEST +SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); +SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); + void disable_simulated_io_errors(void); + void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ + +/************** End of pager.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pcache.h in the middle of sqliteInt.h ****************/ +/************** Begin file pcache.h ******************************************/ +/* +** 2008 August 05 +** +** 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 page cache +** subsystem. +*/ + +#ifndef _PCACHE_H_ + +typedef struct PgHdr PgHdr; +typedef struct PCache PCache; + +/* +** Every page in the cache is controlled by an instance of the following +** structure. +*/ +struct PgHdr { + sqlite3_pcache_page *pPage; /* Pcache object page handle */ + void *pData; /* Page data */ + void *pExtra; /* Extra content */ + PgHdr *pDirty; /* Transient list of dirty pages */ + Pager *pPager; /* The pager this page is part of */ + Pgno pgno; /* Page number for this page */ +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; /* Hash of page content */ +#endif + u16 flags; /* PGHDR flags defined below */ + + /********************************************************************** + ** Elements above are public. All that follows is private to pcache.c + ** and should not be accessed by other modules. + */ + i16 nRef; /* Number of users of this page */ + PCache *pCache; /* Cache that owns this page */ + + PgHdr *pDirtyNext; /* Next element in list of dirty pages */ + PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ +}; + +/* Bit values for PgHdr.flags */ +#define PGHDR_DIRTY 0x002 /* Page has changed */ +#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before + ** writing this page to the database */ +#define PGHDR_NEED_READ 0x008 /* Content is unread */ +#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ +#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ + +#define PGHDR_MMAP 0x040 /* This is an mmap page object */ + +/* Initialize and shutdown the page cache subsystem */ +SQLITE_PRIVATE int sqlite3PcacheInitialize(void); +SQLITE_PRIVATE void sqlite3PcacheShutdown(void); + +/* Page cache buffer management: +** These routines implement SQLITE_CONFIG_PAGECACHE. +*/ +SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); + +/* Create a new pager cache. +** Under memory stress, invoke xStress to try to make pages clean. +** Only clean and unpinned pages can be reclaimed. +*/ +SQLITE_PRIVATE void sqlite3PcacheOpen( + int szPage, /* Size of every page */ + int szExtra, /* Extra space associated with each page */ + int bPurgeable, /* True if pages are on backing store */ + int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */ + void *pStress, /* Argument to xStress */ + PCache *pToInit /* Preallocated space for the PCache */ +); + +/* Modify the page-size after the cache has been created. */ +SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int); + +/* Return the size in bytes of a PCache object. Used to preallocate +** storage space. +*/ +SQLITE_PRIVATE int sqlite3PcacheSize(void); + +/* One release per successful fetch. Page is pinned until released. +** Reference counted. +*/ +SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**); +SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); + +SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ +SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ +SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ +SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ + +/* Change a page number. Used by incr-vacuum. */ +SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); + +/* Remove all pages with pgno>x. Reset the cache if x==0 */ +SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x); + +/* Get a list of all dirty pages in the cache, sorted by page number */ +SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); + +/* Reset and close the cache object */ +SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); + +/* Clear flags from pages of the page cache */ +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); + +/* Discard the contents of the cache */ +SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); + +/* Return the total number of outstanding page references */ +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); + +/* Increment the reference count of an existing page */ +SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); + +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); + +/* Return the total number of pages stored in the cache */ +SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); + +#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) +/* Iterate through all dirty pages currently stored in the cache. This +** interface is only available if SQLITE_CHECK_PAGES is defined when the +** library is built. +*/ +SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); +#endif + +/* Set and get the suggested cache-size for the specified pager-cache. +** +** If no global maximum is configured, then the system attempts to limit +** the total number of pages cached by purgeable pager-caches to the sum +** of the suggested cache-sizes. +*/ +SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); +#endif + +/* Free up as much memory as possible from the page cache */ +SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*); + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* Try to return memory used by the pcache module to the main memory heap */ +SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); +#endif + +SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); + +#endif /* _PCACHE_H_ */ + +/************** End of pcache.h **********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/************** Include os.h in the middle of sqliteInt.h ********************/ +/************** Begin file os.h **********************************************/ +/* +** 2001 September 16 +** +** 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 (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. After the following block of preprocess macros, +** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER +** will defined to either 1 or 0. One of the four will be 1. The other +** three will be 0. +*/ +#if defined(SQLITE_OS_OTHER) +# if SQLITE_OS_OTHER==1 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# else +# undef SQLITE_OS_OTHER +# endif +#endif +#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +# define SQLITE_OS_OTHER 0 +# ifndef SQLITE_OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) +# define SQLITE_OS_WIN 1 +# define SQLITE_OS_UNIX 0 +# else +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 1 +# endif +# else +# define SQLITE_OS_UNIX 0 +# endif +#else +# ifndef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# endif +#endif + +#if SQLITE_OS_WIN +# include +#endif + +/* +** Determine if we are dealing with Windows NT. +** +** We ought to be able to determine if we are compiling for win98 or winNT +** using the _WIN32_WINNT macro as follows: +** +** #if defined(_WIN32_WINNT) +** # define SQLITE_OS_WINNT 1 +** #else +** # define SQLITE_OS_WINNT 0 +** #endif +** +** However, vs2005 does not set _WIN32_WINNT by default, as it ought to, +** so the above test does not work. We'll just assume that everything is +** winNT unless the programmer explicitly says otherwise by setting +** SQLITE_OS_WINNT to 0. +*/ +#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT) +# define SQLITE_OS_WINNT 1 +#endif + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define SQLITE_OS_WINCE 1 +#else +# define SQLITE_OS_WINCE 0 +#endif + +/* +** Determine if we are dealing with WinRT, which provides only a subset of +** the full Win32 API. +*/ +#if !defined(SQLITE_OS_WINRT) +# define SQLITE_OS_WINRT 0 +#endif + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 4096 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** a random byte is selected for a shared lock. The pool of bytes for +** shared locks begins at SHARED_FIRST. +** +** The same locking strategy and +** byte ranges are used for Unix. This leaves open the possiblity of having +** clients on win95, winNT, and unix all talking to the same shared file +** and all locking correctly. To do so would require that samba (or whatever +** tool is being used for file sharing) implements locks correctly between +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#ifdef SQLITE_OMIT_WSD +# define PENDING_BYTE (0x40000000) +#else +# define PENDING_BYTE sqlite3PendingByte +#endif +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Wrapper around OS specific sqlite3_os_init() function. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void); + +/* +** Functions for accessing sqlite3_file methods +*/ +SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); +SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); +SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); +SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*); +#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 +SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); +SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); +SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); + + +/* +** Functions for accessing sqlite3_vfs methods +*/ +SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); +SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); +SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); + +#endif /* _SQLITE_OS_H_ */ + +/************** End of os.h **************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include mutex.h in the middle of sqliteInt.h *****************/ +/************** Begin file mutex.h *******************************************/ +/* +** 2007 August 28 +** +** 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 contains the common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +*/ + + +/* +** Figure out what version of the code to use. The choices are +** +** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The +** mutexes implemention cannot be overridden +** at start-time. +** +** SQLITE_MUTEX_NOOP For single-threaded applications. No +** mutual exclusion is provided. But this +** implementation can be overridden at +** start-time. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. +*/ +#if !SQLITE_THREADSAFE +# define SQLITE_MUTEX_OMIT +#endif +#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) +# if SQLITE_OS_UNIX +# define SQLITE_MUTEX_PTHREADS +# elif SQLITE_OS_WIN +# define SQLITE_MUTEX_W32 +# else +# define SQLITE_MUTEX_NOOP +# endif +#endif + +#ifdef SQLITE_MUTEX_OMIT +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) ((void)(X),1) +#define sqlite3_mutex_notheld(X) ((void)(X),1) +#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) +#define sqlite3MutexInit() SQLITE_OK +#define sqlite3MutexEnd() +#define MUTEX_LOGIC(X) +#else +#define MUTEX_LOGIC(X) X +#endif /* defined(SQLITE_MUTEX_OMIT) */ + +/************** End of mutex.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +struct Db { + char *zName; /* Name of this database */ + Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at syncing data to disk */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +** +** Most Schema objects are associated with a Btree. The exception is +** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. +** In shared cache mode, a single Schema object can be shared by multiple +** Btrees that refer to the same underlying BtShared object. +** +** Schema objects are automatically deallocated when the last Btree that +** references them is destroyed. The TEMP Schema is manually freed by +** sqlite3_close(). +* +** A thread must be holding a mutex on the corresponding Btree in order +** to access Schema content. This implies that the thread must also be +** holding a mutex on the sqlite3 connection pointer that owns the Btree. +** For a TEMP Schema, only the connection mutex is required. +*/ +struct Schema { + int schema_cookie; /* Database schema version number for this file */ + int iGeneration; /* Generation counter. Incremented with each change */ + Hash tblHash; /* All tables indexed by name */ + Hash idxHash; /* All (named) indices indexed by name */ + Hash trigHash; /* All triggers indexed by name */ + Hash fkeyHash; /* All foreign keys by referenced table name */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.pSchema->flags field. +*/ +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) + +/* +** Allowed values for the DB.pSchema->flags field. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ +#define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ + +/* +** The number of different kinds of things that can be limited +** using the sqlite3_limit() interface. +*/ +#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1) + +/* +** Lookaside malloc is a set of fixed-size buffers that can be used +** to satisfy small transient memory allocation requests for objects +** associated with a particular database connection. The use of +** lookaside malloc provides a significant performance enhancement +** (approx 10%) by avoiding numerous malloc/free requests while parsing +** SQL statements. +** +** The Lookaside structure holds configuration information about the +** lookaside malloc subsystem. Each available memory allocation in +** the lookaside subsystem is stored on a linked list of LookasideSlot +** objects. +** +** Lookaside allocations are only allowed for objects that are associated +** with a particular database connection. Hence, schema information cannot +** be stored in lookaside because in shared cache mode the schema information +** is shared by multiple database connections. Therefore, while parsing +** schema information, the Lookaside.bEnabled flag is cleared so that +** lookaside allocations are not used to construct the schema objects. +*/ +struct Lookaside { + u16 sz; /* Size of each buffer in bytes */ + u8 bEnabled; /* False to disable new lookaside allocations */ + u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ + int nOut; /* Number of buffers currently checked out */ + int mxOut; /* Highwater mark for nOut */ + int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ + LookasideSlot *pFree; /* List of available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +}; +struct LookasideSlot { + LookasideSlot *pNext; /* Next buffer in the list of free buffers */ +}; + +/* +** A hash table for function definitions. +** +** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. +** Collisions are on the FuncDef.pHash chain. +*/ +struct FuncDefHash { + FuncDef *a[23]; /* Hash table for functions */ +}; + +/* +** Each database connection is an instance of the following structure. +*/ +struct sqlite3 { + sqlite3_vfs *pVfs; /* OS Interface */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + sqlite3_mutex *mutex; /* Connection mutex */ + Db *aDb; /* All backends */ + int nDb; /* Number of backends currently in use */ + int flags; /* Miscellaneous flags. See below */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 szMmap; /* Default mmap_size setting */ + unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u16 dbOptFlags; /* Flags to enable/disable optimizations */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 dfltLockMode; /* Default locking-mode for attached dbs */ + signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + u8 suppressErr; /* Do not issue error messages if true */ + u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + u32 magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + int aLimit[SQLITE_N_LIMIT]; /* Limits */ + struct sqlite3InitInfo { /* Information used during initialization */ + int newTnum; /* Rootpage of table being initialized */ + u8 iDb; /* Which db file is being initialized */ + u8 busy; /* TRUE if currently initializing */ + u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ + } init; + int activeVdbeCnt; /* Number of VDBEs currently executing */ + int writeVdbeCnt; /* Number of active VDBEs that are writing */ + int vdbeExecCnt; /* Number of nested calls to VdbeExec() */ + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared library handles */ + void (*xTrace)(void*,const char*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ + void (*xProfile)(void*,const char*,u64); /* Profiling function */ + void *pProfileArg; /* Argument to profile function */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); +#ifndef SQLITE_OMIT_WAL + int (*xWalCallback)(void *, sqlite3 *, const char *, int); + void *pWalArg; +#endif + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); + void *pCollNeededArg; + sqlite3_value *pErr; /* Most recent error message */ + char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ + char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; + Lookaside lookaside; /* Lookaside malloc configuration */ +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + int nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + int nVTrans; /* Allocated size of aVTrans */ + Hash aModule; /* populated by sqlite3_create_module() */ + VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ + VTable **aVTrans; /* Virtual tables with open transactions */ + VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ +#endif + FuncDefHash aFunc; /* Hash table of connection functions */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ + Savepoint *pSavepoint; /* List of active savepoints */ + int busyTimeout; /* Busy handler timeout, in msec */ + int nSavepoint; /* Number of non-transaction savepoints */ + int nStatement; /* Number of nested statement-transactions */ + i64 nDeferredCons; /* Net deferred constraints this transaction. */ + int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ + +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY + /* The following variables are all protected by the STATIC_MASTER + ** mutex, not by sqlite3.mutex. They are used by code in notify.c. + ** + ** When X.pUnlockConnection==Y, that means that X is waiting for Y to + ** unlock so that it can proceed. + ** + ** When X.pBlockingConnection==Y, that means that something that X tried + ** tried to do recently failed with an SQLITE_LOCKED error due to locks + ** held by Y. + */ + sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */ + sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ + void *pUnlockArg; /* Argument to xUnlockNotify */ + void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ + sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ +#endif +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + +/* +** Possible values for the sqlite3.flags. +*/ +#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ +#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */ +#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */ +#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */ +#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */ +#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */ +#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ +#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ +#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ +#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ +#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ +#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ + +/* +** Bits of the sqlite3.dbOptFlags field that are used by the +** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to +** selectively disable various optimizations. +*/ +#define SQLITE_QueryFlattener 0x0001 /* Query flattening */ +#define SQLITE_ColumnCache 0x0002 /* Column cache */ +#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ +#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ +#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ +#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ +#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ +#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ +#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ +#define SQLITE_Transitive 0x0200 /* Transitive constraints */ +#define SQLITE_AllOpts 0xffff /* All optimizations */ + +/* +** Macros for testing whether or not optimizations are enabled or disabled. +*/ +#ifndef SQLITE_OMIT_BUILTIN_TEST +#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) +#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) +#else +#define OptimizationDisabled(db, mask) 0 +#define OptimizationEnabled(db, mask) 1 +#endif + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ +#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ + u8 flags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */ + char *zName; /* SQL name of the function. */ + FuncDef *pHash; /* Next with a different name but the same hash */ + FuncDestructor *pDestructor; /* Reference counted destructor function */ +}; + +/* +** This structure encapsulates a user-function destructor callback (as +** configured using create_function_v2()) and a reference counter. When +** create_function_v2() is called to create a function with a destructor, +** a single object of this type is allocated. FuncDestructor.nRef is set to +** the number of FuncDef objects created (either 1 or 3, depending on whether +** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor +** member of each of the new FuncDef objects is set to point to the allocated +** FuncDestructor. +** +** Thereafter, when one of the FuncDef objects is deleted, the reference +** count on this object is decremented. When it reaches 0, the destructor +** is invoked and the FuncDestructor structure freed. +*/ +struct FuncDestructor { + int nRef; + void (*xDestroy)(void *); + void *pUserData; +}; + +/* +** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF +** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There +** are assert() statements in the code to verify this. +*/ +#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */ +#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */ + +/* +** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are +** used to create the initializers for the FuncDef structures. +** +** FUNCTION(zName, nArg, iArg, bNC, xFunc) +** Used to create a scalar function definition of a function zName +** implemented by C function xFunc that accepts nArg arguments. The +** value passed as iArg is cast to a (void*) and made available +** as the user-data (sqlite3_user_data()) for the function. If +** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. +** +** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) +** Used to create an aggregate function definition implemented by +** the C functions xStep and xFinal. The first four parameters +** are interpreted in the same way as the first 4 parameters to +** FUNCTION(). +** +** LIKEFUNC(zName, nArg, pArg, flags) +** Used to create a scalar function definition of a function zName +** that accepts nArg arguments and is implemented by a call to C +** function likeFunc. Argument pArg is cast to a (void *) and made +** available as the function user-data (sqlite3_user_data()). The +** FuncDef.flags variable is set to the value passed as the flags +** parameter. +*/ +#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ + {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + pArg, 0, xFunc, 0, 0, #zName, 0, 0} +#define LIKEFUNC(zName, nArg, arg, flags) \ + {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} +#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ + {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ + SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} + +/* +** All current savepoints are stored in a linked list starting at +** sqlite3.pSavepoint. The first element in the list is the most recently +** opened savepoint. Savepoints are added to the list by the vdbe +** OP_Savepoint instruction. +*/ +struct Savepoint { + char *zName; /* Savepoint name (nul-terminated) */ + i64 nDeferredCons; /* Number of deferred fk violations */ + Savepoint *pNext; /* Parent savepoint (if any) */ +}; + +/* +** The following are used as the second parameter to sqlite3Savepoint(), +** and as the P1 argument to the OP_Savepoint instruction. +*/ +#define SAVEPOINT_BEGIN 0 +#define SAVEPOINT_RELEASE 1 +#define SAVEPOINT_ROLLBACK 2 + + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zDflt; /* Original text of the default value */ + char *zType; /* Data type for this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ + char affinity; /* One of the SQLITE_AFF_... values */ + u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ +}; + +/* Allowed values for Column.colFlags: +*/ +#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ +#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** If CollSeq.xCmp is NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by numbering the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'a'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P4 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. +*/ +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' + +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x67 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +*/ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ +#define SQLITE_NULLEQ 0x80 /* NULL=NULL */ + +/* +** An object of this type is created for each virtual table present in +** the database schema. +** +** If the database schema is shared, then there is one instance of this +** structure for each database connection (sqlite3*) that uses the shared +** schema. This is because each database connection requires its own unique +** instance of the sqlite3_vtab* handle used to access the virtual table +** implementation. sqlite3_vtab* handles can not be shared between +** database connections, even when the rest of the in-memory database +** schema is shared, as the implementation often stores the database +** connection handle passed to it via the xConnect() or xCreate() method +** during initialization internally. This database connection handle may +** then be used by the virtual table implementation to access real tables +** within the database. So that they appear as part of the callers +** transaction, these accesses need to be made via the same database +** connection as that used to execute SQL operations on the virtual table. +** +** All VTable objects that correspond to a single table in a shared +** database schema are initially stored in a linked-list pointed to by +** the Table.pVTable member variable of the corresponding Table object. +** When an sqlite3_prepare() operation is required to access the virtual +** table, it searches the list for the VTable that corresponds to the +** database connection doing the preparing so as to use the correct +** sqlite3_vtab* handle in the compiled query. +** +** When an in-memory Table object is deleted (for example when the +** schema is being reloaded for some reason), the VTable objects are not +** deleted and the sqlite3_vtab* handles are not xDisconnect()ed +** immediately. Instead, they are moved from the Table.pVTable list to +** another linked list headed by the sqlite3.pDisconnect member of the +** corresponding sqlite3 structure. They are then deleted/xDisconnected +** next time a statement is prepared using said sqlite3*. This is done +** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. +** Refer to comments above function sqlite3VtabUnlockList() for an +** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect +** list without holding the corresponding sqlite3.mutex mutex. +** +** The memory for objects of this type is always allocated by +** sqlite3DbMalloc(), using the connection handle stored in VTable.db as +** the first argument. +*/ +struct VTable { + sqlite3 *db; /* Database connection associated with this table */ + Module *pMod; /* Pointer to module implementation */ + sqlite3_vtab *pVtab; /* Pointer to vtab instance */ + int nRef; /* Number of pointers to this structure */ + u8 bConstraint; /* True if constraints are supported */ + int iSavepoint; /* Depth of the SAVEPOINT stack */ + VTable *pNext; /* Next in linked list (see above) */ +}; + +/* +** Each SQL table is represented in memory by an instance of the +** following structure. +** +** Table.zName is the name of the table. The case of the original +** CREATE TABLE statement is stored, but case is not significant for +** comparisons. +** +** Table.nCol is the number of columns in this table. Table.aCol is a +** pointer to an array of Column structures, one for each column. +** +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of +** the column that is that key. Otherwise Table.iPKey is negative. Note +** that the datatype of the PRIMARY KEY must be INTEGER for this field to +** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of +** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid +** is generated for each row of the table. TF_HasPrimaryKey is set if +** the table has any PRIMARY KEY, INTEGER or otherwise. +** +** Table.tnum is the page number for the root BTree page of the table in the +** database file. If Table.iDb is the index of the database table backend +** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that +** holds temporary tables and indices. If TF_Ephemeral is set +** then the table is stored in a file that is automatically deleted +** when the VDBE cursor to the table is closed. In this case Table.tnum +** refers VDBE cursor number that holds the table open, not to the root +** page number. Transient tables are used to hold the results of a +** sub-query that appears instead of a real table name in the FROM clause +** of a SELECT statement. +*/ +struct Table { + char *zName; /* Name of the table or view */ + Column *aCol; /* Information about each column */ + Index *pIndex; /* List of SQL indexes on this table. */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ + char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + ExprList *pCheck; /* All CHECK constraints */ +#endif + tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ + int tnum; /* Root BTree node for this table (see note above) */ + i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ + i16 nCol; /* Number of columns in this table */ + u16 nRef; /* Number of pointers to this Table */ + u8 tabFlags; /* Mask of TF_* values */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ + VTable *pVTable; /* List of VTable objects. */ +#endif + Trigger *pTrigger; /* List of triggers stored in pSchema */ + Schema *pSchema; /* Schema that contains this table */ + Table *pNextZombie; /* Next on the Parse.pZombieTab list */ +}; + +/* +** Allowed values for Tabe.tabFlags. +*/ +#define TF_Readonly 0x01 /* Read-only system table */ +#define TF_Ephemeral 0x02 /* An ephemeral table */ +#define TF_HasPrimaryKey 0x04 /* Table has a primary key */ +#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ +#define TF_Virtual 0x10 /* Is a virtual table */ + + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existence of the to-table is not checked. +*/ +struct FKey { + Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */ + FKey *pNextFrom; /* Next foreign key in pFrom */ + char *zTo; /* Name of table that the key points to (aka: Parent) */ + FKey *pNextTo; /* Next foreign key on table named zTo */ + FKey *pPrevTo; /* Previous foreign key on table named zTo */ + int nCol; /* Number of columns in this key */ + /* EV: R-30323-21917 */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ + Trigger *apTrigger[2]; /* Triggers for aAction[] actions */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } aCol[1]; /* One entry for each of nCol column s */ +}; + +/* +** SQLite supports many different ways to resolve a constraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 99 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +*/ +struct KeyInfo { + sqlite3 *db; /* The database connection */ + u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ + u16 nField; /* Number of entries in aColl[] */ + u8 *aSortOrder; /* Sort order for each column. May be NULL */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassembled by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constituent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u8 flags; /* Boolean settings. UNPACKED_... below */ + i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */ + Mem *aMem; /* Values */ +}; + +/* +** Allowed values of UnpackedRecord.flags +*/ +#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */ +#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */ +#define UNPACKED_PREFIX_SEARCH 0x04 /* Ignore final (rowid) field */ + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +*/ +struct Index { + char *zName; /* Name of this index */ + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ + tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ + int tnum; /* DB Page containing root of this index */ + u16 nColumn; /* Number of columns in table used by this index */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ + unsigned bUnordered:1; /* Use this index for == or IN queries only */ +#ifdef SQLITE_ENABLE_STAT3 + int nSample; /* Number of elements in aSample[] */ + tRowcnt avgEq; /* Average nEq value for key values not in aSample */ + IndexSample *aSample; /* Samples of the left-most key */ +#endif +}; + +/* +** Each sample stored in the sqlite_stat3 table is represented in memory +** using a structure of this type. See documentation at the top of the +** analyze.c source file for additional information. +*/ +struct IndexSample { + union { + char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */ + double r; /* Value if eType is SQLITE_FLOAT */ + i64 i; /* Value if eType is SQLITE_INTEGER */ + } u; + u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */ + int nByte; /* Size in byte of text or blob. */ + tRowcnt nEq; /* Est. number of rows where the key equals this sample */ + tRowcnt nLt; /* Est. number of rows where key is less than this sample */ + tRowcnt nDLt; /* Est. number of distinct keys less than this sample */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assumptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const char *z; /* Text of the token. Not NULL-terminated! */ + unsigned int n; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + int sortingIdxPTab; /* Cursor number of pseudo-table */ + int nSortingColumn; /* Number of columns in the sorting index */ + ExprList *pGroupBy; /* The group by clause */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephemeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ +}; + +/* +** The datatype ynVar is a signed integer, either 16-bit or 32-bit. +** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater +** than 32767 we have to make it 32-bit. 16-bit is preferred because +** it uses less memory in the Expr object, which is a big memory user +** in systems with lots of prepared statements. And few applications +** need more than about 10 or 20 variables. But some extreme users want +** to have prepared statements with over 32767 variables, and for them +** the option is available (at compile-time). +*/ +#if SQLITE_MAX_VARIABLE_NUMBER<=32767 +typedef i16 ynVar; +#else +typedef int ynVar; +#endif + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, +** or TK_STRING), then Expr.token contains the text of the SQL literal. If +** the expression is a variable (TK_VARIABLE), then Expr.token contains the +** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), +** then Expr.token contains the name of the function. +** +** Expr.pRight and Expr.pLeft are the left and right subexpressions of a +** binary operator. Either or both may be NULL. +** +** Expr.x.pList is a list of arguments if the expression is an SQL function, +** a CASE expression or an IN expression of the form " IN (, ...)". +** Expr.x.pSelect is used if the expression is a sub-select or an expression of +** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the +** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is +** valid. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is an unbound variable marker (a question mark +** character '?' in the original SQL) then the Expr.iTable holds the index +** number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +** +** ALLOCATION NOTES: +** +** Expr objects can use a lot of memory space in database schema. To +** help reduce memory requirements, sometimes an Expr object will be +** truncated. And to reduce the number of memory allocations, sometimes +** two or more Expr objects will be stored in a single memory allocation, +** together with Expr.zToken strings. +** +** If the EP_Reduced and EP_TokenOnly flags are set when +** an Expr object is truncated. When EP_Reduced is set, then all +** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees +** are contained within the same memory allocation. Note, however, that +** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately +** allocated, regardless of whether or not EP_Reduced is set. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + u16 flags; /* Various flags. EP_* See below */ + union { + char *zToken; /* Token value. Zero terminated and dequoted */ + int iValue; /* Non-negative integer value if EP_IntValue */ + } u; + + /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no + ** space is allocated for the fields below this point. An attempt to + ** access them will result in a segfault or malfunction. + *********************************************************************/ + + Expr *pLeft; /* Left subnode */ + Expr *pRight; /* Right subnode */ + union { + ExprList *pList; /* Function arguments or in " IN ( IN (
" - "" - ""); - return MG_TRUE; // Tell mongoose to close this connection - } -} - -// Mongoose sends MG_RECV for every received POST chunk. -// When last POST chunk is received, Mongoose sends MG_REQUEST, then MG_CLOSE. -static int handle_recv(struct mg_connection *conn) { - FILE *fp = (FILE *) conn->connection_param; - - // Open temporary file where we going to write data - if (fp == NULL && ((conn->connection_param = fp = tmpfile())) == NULL) { - return -1; // Close connection on error - } - - // Return number of bytes written to a temporary file: that is how many - // bytes we want to discard from the receive buffer - return fwrite(conn->content, 1, conn->content_len, fp); -} - -// Make sure we free all allocated resources -static int handle_close(struct mg_connection *conn) { - if (conn->connection_param != NULL) { - fclose((FILE *) conn->connection_param); - conn->connection_param = NULL; - } - return MG_TRUE; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: return handle_request(conn); - case MG_RECV: return handle_recv(conn); - case MG_CLOSE: return handle_close(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - - for (;;) { - mg_poll_server(server, 1000); - } - - mg_destroy_server(&server); - return 0; -} diff --git a/examples/captive_dns_server/Makefile b/examples/captive_dns_server/Makefile new file mode 100644 index 00000000..aabf5ac5 --- /dev/null +++ b/examples/captive_dns_server/Makefile @@ -0,0 +1,4 @@ +PROG = captive_dns_server +MODULE_CFLAGS=-DNS_ENABLE_DNS_SERVER + +include ../rules.mk diff --git a/examples/captive_dns_server/captive_dns_server.c b/examples/captive_dns_server/captive_dns_server.c new file mode 100644 index 00000000..fb4a668a --- /dev/null +++ b/examples/captive_dns_server/captive_dns_server.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * Try it out with: + * $ dig -t A www.google.com -4 @localhost -p 5533 + */ + +#include "../../mongoose.h" + +#include + +static int s_exit_flag = 0; +static in_addr_t s_our_ip_addr; +static const char *s_listening_addr = "udp://:5533"; + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct mg_dmg_message *msg; + struct mg_dmg_resource_record *rr; + struct mg_dmg_reply reply; + int i; + + switch (ev) { + case NS_DNS_MESSAGE: + msg = (struct mg_dmg_message *) ev_data; + reply = mg_dmg_create_reply(&nc->send_mbuf, msg); + + for (i = 0; i < msg->num_questions; i++) { + rr = &msg->questions[i]; + if (rr->rtype == NS_DNS_A_RECORD) { + mg_dmg_reply_record(&reply, rr, NULL, rr->rtype, 3600, + &s_our_ip_addr, 4); + } + } + + /* + * We don't set the error flag even if there were no answers + * maching the NS_DNS_A_RECORD query type. + * This indicates that we have (syntetic) answers for NS_DNS_A_RECORD. + * See http://goo.gl/QWvufr for a distinction between NXDOMAIN and NODATA. + */ + + mg_dmg_send_reply(nc, &reply); + break; + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + int i; + + mg_mgr_init(&mgr, NULL); + s_our_ip_addr = inet_addr("127.0.0.1"); + + /* Parse command line arguments */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-D") == 0) { + mgr.hexdump_file = argv[++i]; + } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) { + s_listening_addr = argv[++i]; + } else { + s_our_ip_addr = inet_addr(argv[i]); + } + } + + fprintf(stderr, "Listening on '%s'\n", s_listening_addr); + if ((nc = mg_bind(&mgr, s_listening_addr, ev_handler)) == NULL) { + fprintf(stderr, "cannot bind to socket\n"); + exit(1); + } + mg_set_protocol_dns(nc); + + while (s_exit_flag == 0) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/coap_client/Makefile b/examples/coap_client/Makefile new file mode 100644 index 00000000..312fbeb1 --- /dev/null +++ b/examples/coap_client/Makefile @@ -0,0 +1,14 @@ +PROG = coap_client +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. $(CFLAGS_EXTRA) -DNS_ENABLE_COAP + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/coap_client/coap_client.c b/examples/coap_client/coap_client.c new file mode 100644 index 00000000..f36b2fa0 --- /dev/null +++ b/examples/coap_client/coap_client.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + * + * This program sends CoAP CON-message to server (coap.me by default) + * and waits for answer. + */ + +#include "mongoose.h" + +static int s_time_to_exit = 0; +static char* s_default_address = "udp://coap.me:5683"; + +static void coap_handler(struct mg_connection *nc, int ev, void *p) { + switch (ev) { + case NS_CONNECT: { + struct mg_coap_message cm; + uint32_t res; + + memset(&cm, 0, sizeof(cm)); + cm.msg_id = 1; + cm.msg_type = NS_COAP_MSG_CON; + printf("Sending CON...\n"); + res = mg_coap_send_message(nc, &cm); + if (res == 0) { + printf("Sent CON with msg_id = %d\n", cm.msg_id); + } else { + printf("Error: %d\n", res); + s_time_to_exit = 1; + } + break; + } + case NS_COAP_ACK: + case NS_COAP_RST: { + struct mg_coap_message *cm = (struct mg_coap_message *)p; + printf("ACK/RST for message with msg_id = %d received\n", + cm->msg_id); + s_time_to_exit = 1; + break; + } + } +} + +int main(int argc, char* argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + char *address = s_default_address; + + if (argc > 1) { + address = argv[1]; + } + + printf("Using %s as CoAP server\n", address); + + mg_mgr_init(&mgr, 0); + + nc = mg_connect(&mgr, address, coap_handler); + if (nc == NULL) { + printf("Unable to connect to %s\n", address); + return -1; + } + + mg_set_protocol_coap(nc); + + while (!s_time_to_exit) { + mg_mgr_poll(&mgr, 1); + } + + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/coap_server/Makefile b/examples/coap_server/Makefile new file mode 100644 index 00000000..2990a47f --- /dev/null +++ b/examples/coap_server/Makefile @@ -0,0 +1,14 @@ +PROG = coap_server +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. $(CFLAGS_EXTRA) -DNS_ENABLE_COAP + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/coap_server/coap_server.c b/examples/coap_server/coap_server.c new file mode 100644 index 00000000..34e99fbc --- /dev/null +++ b/examples/coap_server/coap_server.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + * + * This program listens on 5683 for CoAP messages, + * sends ACK is nessesary and dump everything received. + * It is possible to use ../coap_client to send message. + */ + +#include "mongoose.h" + +static char* s_default_address = "udp://:5683"; +static int s_sig_received = 0; + +static void signal_handler(int sig_num) { + signal(sig_num, signal_handler); + s_sig_received = sig_num; +} + +static void coap_handler(struct mg_connection *nc, int ev, void *p) { + switch (ev) { + case NS_COAP_CON: { + uint32_t res; + struct mg_coap_message *cm = (struct mg_coap_message *)p; + printf("CON with msg_id = %d received\n", cm->msg_id); + res = mg_coap_send_ack(nc, cm->msg_id); + if (res == 0) { + printf("Successfully sent ACK for message with msg_id = %d\n", + cm->msg_id); + } else { + printf("Error: %d\n", res); + } + break; + } + case NS_COAP_NOC: + case NS_COAP_ACK: + case NS_COAP_RST: { + struct mg_coap_message *cm = (struct mg_coap_message *)p; + printf("ACK/RST/NOC with msg_id = %d received\n", + cm->msg_id); + break; + } + } +} + +int main() { + struct mg_mgr mgr; + struct mg_connection *nc; + + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + + mg_mgr_init(&mgr, 0); + + nc = mg_bind(&mgr, s_default_address, coap_handler); + if (nc == NULL) { + printf("Unable to start listener at %s\n", s_default_address); + return -1; + } + + printf("Listening for CoAP messages at %s\n", s_default_address); + + mg_set_protocol_coap(nc); + + while (!s_sig_received) { + mg_mgr_poll(&mgr, 1); + } + + printf("Exiting on signal %d\n", s_sig_received); + + mg_mgr_free(&mgr); + return 0; +} diff --git a/examples/cookie_authentication/Makefile b/examples/cookie_authentication/Makefile deleted file mode 100644 index 1eb0652b..00000000 --- a/examples/cookie_authentication/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = cookie_auth -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/cookie_authentication/cookie_auth.c b/examples/cookie_authentication/cookie_auth.c deleted file mode 100644 index c35e0445..00000000 --- a/examples/cookie_authentication/cookie_auth.c +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved - -#include -#include -#include -#include "mongoose.h" - -static const char *s_login_uri = "/login.html"; -static const char *s_secret = ":-)"; // Must be known only to server - -static void generate_ssid(const char *user_name, const char *expiration_date, - char *ssid, size_t ssid_size) { - char hash[33]; - mg_md5(hash, user_name, ":", expiration_date, ":", s_secret, NULL); - snprintf(ssid, ssid_size, "%s|%s|%s", user_name, expiration_date, hash); -} - -static int check_auth(struct mg_connection *conn) { - char ssid[100], calculated_ssid[100], name[100], expire[100]; - - // Always authenticate requests to login page - if (strcmp(conn->uri, s_login_uri) == 0) { - return MG_TRUE; - } - - // Look for session ID in the Cookie. - // That session ID can be validated against the database that stores - // current active sessions. - mg_parse_header(mg_get_header(conn, "Cookie"), "ssid", ssid, sizeof(ssid)); - if (sscanf(ssid, "%[^|]|%[^|]|", name, expire) == 2) { - generate_ssid(name, expire, calculated_ssid, sizeof(calculated_ssid)); - if (strcmp(ssid, calculated_ssid) == 0) { - return MG_TRUE; // Authenticate - } - } - - // Auth failed, do NOT authenticate, redirect to login page - mg_printf(conn, "HTTP/1.1 302 Moved\r\nLocation: %s\r\n\r\n", s_login_uri); - return MG_FALSE; -} - -static int check_login_form_submission(struct mg_connection *conn) { - char name[100], password[100], ssid[100], expire[100], expire_epoch[100]; - - mg_get_var(conn, "name", name, sizeof(name)); - mg_get_var(conn, "password", password, sizeof(password)); - - // A real authentication mechanism should be employed here. - // Also, the whole site should be served through HTTPS. - if (strcmp(name, "Joe") == 0 && strcmp(password, "Doe") == 0) { - // Generate expiry date - time_t t = time(NULL) + 3600; // Valid for 1 hour - snprintf(expire_epoch, sizeof(expire_epoch), "%lu", (unsigned long) t); - strftime(expire, sizeof(expire), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t)); - generate_ssid(name, expire_epoch, ssid, sizeof(ssid)); - // Set "session id" cookie, there could be some data encoded in it. - mg_printf(conn, - "HTTP/1.1 302 Moved\r\n" - "Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n" - "Content-Length: 0\r\n" - "Location: /\r\n\r\n", - ssid, expire); - return MG_TRUE; - } - return MG_FALSE; -} - -static int serve_request(struct mg_connection *conn) { - if (strcmp(conn->uri, s_login_uri) == 0 && - strcmp(conn->request_method, "POST") == 0) { - return check_login_form_submission(conn); - } - return MG_FALSE; // Serve files in the document_root -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return check_auth(conn); - case MG_REQUEST: return serve_request(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - mg_set_option(server, "document_root", "."); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/cookie_authentication/login.html b/examples/cookie_authentication/login.html deleted file mode 100644 index d3ff7056..00000000 --- a/examples/cookie_authentication/login.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - WebSocket Test - - - - -
-

Mongoose Cookie Based Authentication

-

Use name "Joe", password "Doe" to login.

-
-
- - -
- - -
- -
-
- - \ No newline at end of file diff --git a/examples/csharp/example.cs b/examples/csharp/example.cs deleted file mode 100644 index 3b0ced68..00000000 --- a/examples/csharp/example.cs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of mongoose web server project, -// https://github.com/cesanta/mongoose - -using System; - -public class Program { - static private int EventHandler(IntPtr conn_ptr, int ev) { - MongooseConnection conn = (MongooseConnection) - System.Runtime.InteropServices.Marshal.PtrToStructure( - conn_ptr , typeof(MongooseConnection)); - - if (ev == 102) { - // MG_AUTH - return 1; - } else if (ev == 103) { - // MG_REQUEST - Mongoose.send_data(conn_ptr, "Hello from C#!\n"); - Mongoose.send_data(conn_ptr, "URI: " + conn.uri + "\n"); - Mongoose.send_data(conn_ptr, "HTTP Headers:\n"); - - for (int i = 0; i < conn.num_headers; i++) { - IntPtr name = conn.http_headers[i].name; - IntPtr val = conn.http_headers[i].value; - System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name); - Mongoose.send_data(conn_ptr, " " + - System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name) + ": " + - System.Runtime.InteropServices.Marshal.PtrToStringAnsi(val) + "\n"); - } - return 1; - } - return 0; - } - - static void Main() { - Mongoose web_server = new Mongoose(".", "9001", - new MongooseEventHandler(EventHandler)); - - Console.WriteLine("Mongoose started, press Ctrl-C to exit."); - for (;;) { - web_server.poll(1000); - } - } -} diff --git a/examples/csharp/mongoose.cs b/examples/csharp/mongoose.cs deleted file mode 100644 index efd26581..00000000 --- a/examples/csharp/mongoose.cs +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of mongoose web server project, -// https://github.com/cesanta/mongoose - -using System; -using System.Runtime.InteropServices; - -[StructLayout(LayoutKind.Sequential)] public struct MongooseHeader { - [MarshalAs(UnmanagedType.LPTStr)] public IntPtr name; - [MarshalAs(UnmanagedType.LPTStr)] public IntPtr value; -}; - -// mongoose.h :: struct mg_connection -[StructLayout(LayoutKind.Sequential)] public struct MongooseConnection { - [MarshalAs(UnmanagedType.LPTStr)] public string request_method; - [MarshalAs(UnmanagedType.LPTStr)] public string uri; - [MarshalAs(UnmanagedType.LPTStr)] public string http_version; - [MarshalAs(UnmanagedType.LPTStr)] public string query_string; - - [MarshalAs(UnmanagedType.ByValArray,SizeConst=48)] public char[] remote_ip; - [MarshalAs(UnmanagedType.LPTStr)] public string local_ip; - [MarshalAs(UnmanagedType.U2)] public short remote_port; - [MarshalAs(UnmanagedType.U2)] public short local_port; - - [MarshalAs(UnmanagedType.SysInt)] public int num_headers; - [MarshalAs(UnmanagedType.ByValArray,SizeConst=30)] - public MongooseHeader[] http_headers; - - [MarshalAs(UnmanagedType.LPTStr)] public IntPtr content; - [MarshalAs(UnmanagedType.SysInt)] public int content_len; - - [MarshalAs(UnmanagedType.SysInt)] public int is_websocket; - [MarshalAs(UnmanagedType.SysInt)] public int status_code; - [MarshalAs(UnmanagedType.SysInt)] public int wsbits; -}; - -public delegate int MongooseEventHandler(IntPtr c, int ev); - -public class Mongoose { - public const string dll_ = "mongoose"; - private IntPtr server_; - - [DllImport(dll_)] private static extern IntPtr - mg_create_server(IntPtr user_data, MongooseEventHandler eh); - [DllImport(dll_)] private static extern int - mg_poll_server(IntPtr server, int milli); - [DllImport(dll_)] private static extern IntPtr - mg_set_option(IntPtr server, string name, string value); - [DllImport(dll_)] public static extern int - mg_send_data(IntPtr conn, string data, int length); - - public Mongoose(string document_root, - string listening_port, - MongooseEventHandler event_handler) { - server_ = mg_create_server(IntPtr.Zero, event_handler); - mg_set_option(server_, "document_root", document_root); - mg_set_option(server_, "listening_port", listening_port); - } - - public static int send_data(IntPtr conn, string data) { - return mg_send_data(conn, data, data.Length); - } - - public void poll(int milli) { - mg_poll_server(server_, milli); - } - - // TODO: add destructor and call mg_destroy_server() -} diff --git a/examples/digest_authentication/Makefile b/examples/digest_authentication/Makefile deleted file mode 100644 index 86cd30db..00000000 --- a/examples/digest_authentication/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = digest_auth -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/digest_authentication/digest_auth.c b/examples/digest_authentication/digest_auth.c deleted file mode 100644 index 18835c72..00000000 --- a/examples/digest_authentication/digest_auth.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - - if (ev == MG_AUTH) { - int result = MG_FALSE; // Not authorized - FILE *fp; - - // To populate passwords file, do - // mongoose -A my_passwords.txt mydomain.com admin admin - if ((fp = fopen("my_passwords.txt", "r")) != NULL) { - result = mg_authorize_digest(conn, fp); - fclose(fp); - } - - return result; - } - - return MG_FALSE; -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - mg_set_option(server, "document_root", "."); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/file_upload/Makefile b/examples/file_upload/Makefile deleted file mode 100644 index bf1e51df..00000000 --- a/examples/file_upload/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = file_upload -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/examples/file_upload/file_upload.c b/examples/file_upload/file_upload.c deleted file mode 100644 index eedfc837..00000000 --- a/examples/file_upload/file_upload.c +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2004-2012 Sergey Lyubka -// This file is a part of mongoose project, http://github.com/valenok/mongoose - -#include -#include -#include "mongoose.h" - -static int send_index_page(struct mg_connection *conn) { - const char *data; - int data_len, n1, n2; - char var_name[100], file_name[100]; - - mg_printf_data(conn, "%s", - "Upload example." - "
" - "
" - "
" - "" - "
"); - - n1 = n2 = 0; - while ((n2 = mg_parse_multipart(conn->content + n1, conn->content_len - n1, - var_name, sizeof(var_name), file_name, - sizeof(file_name), &data, &data_len)) > 0) { - mg_printf_data(conn, "var: %s, file_name: %s, size: %d bytes
", - var_name, file_name, data_len); - n1 += n2; - } - - mg_printf_data(conn, "%s", ""); - - return MG_TRUE; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: return send_index_page(conn); - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/form_submit/Makefile b/examples/form_submit/Makefile deleted file mode 100644 index b233f285..00000000 --- a/examples/form_submit/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = form_submit -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/form_submit/form_submit.c b/examples/form_submit/form_submit.c deleted file mode 100644 index f6893114..00000000 --- a/examples/form_submit/form_submit.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include "mongoose.h" - -static const char *html_form = - "POST example." - "
" - "Input 1:
" - "Input 2:
" - "" - "
"; - -static void send_reply(struct mg_connection *conn) { - char var1[500], var2[500]; - - if (strcmp(conn->uri, "/handle_post_request") == 0) { - // User has submitted a form, show submitted data and a variable value - // Parse form data. var1 and var2 are guaranteed to be NUL-terminated - mg_get_var(conn, "input_1", var1, sizeof(var1)); - mg_get_var(conn, "input_2", var2, sizeof(var2)); - - // Send reply to the client, showing submitted form values. - // POST data is in conn->content, data length is in conn->content_len - mg_send_header(conn, "Content-Type", "text/plain"); - mg_printf_data(conn, - "Submitted data: [%.*s]\n" - "Submitted data length: %d bytes\n" - "input_1: [%s]\n" - "input_2: [%s]\n", - conn->content_len, conn->content, - conn->content_len, var1, var2); - } else { - // Show HTML form. - mg_send_data(conn, html_form, strlen(html_form)); - } -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_REQUEST) { - send_reply(conn); - return MG_TRUE; - } else if (ev == MG_AUTH) { - return MG_TRUE; - } else { - return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - - mg_set_option(server, "listening_port", "8080"); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/hello_world/Makefile b/examples/hello_world/Makefile deleted file mode 100644 index d1384e01..00000000 --- a/examples/hello_world/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = hello_world -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - wine $(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/examples/hello_world/hello_world.c b/examples/hello_world/hello_world.c deleted file mode 100644 index 95056895..00000000 --- a/examples/hello_world/hello_world.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates basic use of Mongoose embedded web server. -// $Date: 2014-09-09 22:20:23 UTC $ - -#include -#include -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: - mg_printf_data(conn, "Hello! Requested URI is [%s]", conn->uri); - return MG_TRUE; - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/http_client/Makefile b/examples/http_client/Makefile index 5769babf..2da47c2c 100644 --- a/examples/http_client/Makefile +++ b/examples/http_client/Makefile @@ -1,12 +1,14 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - PROG = http_client -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -DNS_ENABLE_SSL -lssl -lcrypto -pthread $(CFLAGS_EXTRA) -unix: $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp *.o *.lib + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/http_client/http_client.c b/examples/http_client/http_client.c index 41eac581..97b9b35b 100644 --- a/examples/http_client/http_client.c +++ b/examples/http_client/http_client.c @@ -1,82 +1,70 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates how to connect to the remote Web server, -// download data, process it and send back a reply. - -#include -#include +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * + * This program fetches HTTP URLs. + */ #include "mongoose.h" -static int s_received_signal = 0; -static struct mg_server *s_server = NULL; -static const char *s_remote_addr = "glosbe.com:80"; +static int s_exit_flag = 0; +static int s_show_headers = 0; +static const char *s_show_headers_opt = "--show-headers"; -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_received_signal = sig_num; -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - struct mg_connection *client, *orig; +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; switch (ev) { - case MG_AUTH: - return MG_TRUE; - - case MG_CONNECT: - // Send request to the remote host. - // TODO(lsm): handle connect error here. - mg_printf(conn, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", - "/gapi/translate?from=eng&dest=fra&format=json&phrase=cat", - s_remote_addr); - return MG_TRUE; - - case MG_REPLY: - // Send reply to the original connection - orig = (struct mg_connection *) conn->connection_param; - mg_send_status(orig, conn->status_code); - mg_send_header(orig, "Content-Type", "text/plain"); - mg_send_data(orig, conn->content, conn->content_len); - mg_send_data(orig, "", 0); // Last chunk: mark the end of reply - - // Disconnect connections - orig->connection_param = NULL; - conn->connection_param = NULL; - return MG_TRUE; - - case MG_REQUEST: - if ((client = mg_connect(s_server, s_remote_addr)) != NULL) { - // Interconnect requests - client->connection_param = conn; - conn->connection_param = client; - return MG_MORE; - } else { - mg_printf_data(conn, "%s", "cannot send API request"); - return MG_TRUE; + case NS_CONNECT: + if (* (int *) ev_data != 0) { + fprintf(stderr, "connect() failed: %s\n", strerror(* (int *) ev_data)); + s_exit_flag = 1; } - + break; + case NS_HTTP_REPLY: + nc->flags |= NSF_CLOSE_IMMEDIATELY; + if (s_show_headers) { + fwrite(hm->message.p, 1, hm->message.len, stdout); + } else { + fwrite(hm->body.p, 1, hm->body.len, stdout); + } + putchar('\n'); + s_exit_flag = 1; + break; default: - return MG_FALSE; + break; } } -int main(void) { - s_server = mg_create_server(NULL, ev_handler); +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + int i; - mg_set_option(s_server, "listening_port", "8080"); + mg_mgr_init(&mgr, NULL); - // Setup signal handlers - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - printf("Listening on port %s\n", mg_get_option(s_server, "listening_port")); - while (s_received_signal == 0) { - mg_poll_server(s_server, 1000); + /* Process command line arguments */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], s_show_headers_opt) == 0) { + s_show_headers = 1; + } else if (strcmp(argv[i], "--hexdump") == 0 && i + 1 < argc) { + mgr.hexdump_file = argv[++i]; + } else { + break; + } } - mg_destroy_server(&s_server); - printf("Existing on signal %d\n", s_received_signal); - return EXIT_SUCCESS; + if (i + 1 != argc) { + fprintf(stderr, "Usage: %s [%s] [--hexdump ] \n", + argv[0], s_show_headers_opt); + exit(EXIT_FAILURE); + } + + mg_connect_http(&mgr, ev_handler, argv[i], NULL, NULL); + + while (s_exit_flag == 0) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; } diff --git a/examples/json_rpc_server/Makefile b/examples/json_rpc_server/Makefile new file mode 100644 index 00000000..84ea6049 --- /dev/null +++ b/examples/json_rpc_server/Makefile @@ -0,0 +1,14 @@ +PROG = json_rpc_server +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -pthread $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/json_rpc_server/json_rpc_server.c b/examples/json_rpc_server/json_rpc_server.c new file mode 100644 index 00000000..ad39e291 --- /dev/null +++ b/examples/json_rpc_server/json_rpc_server.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * + * To test this server, do + * $ curl -d '{"id":1,method:"sum",params:[22,33]}' 127.0.0.1:8000 + */ + +#include "mongoose.h" + +static const char *s_http_port = "8000"; + +static int rpc_sum(char *buf, int len, struct mg_rpc_request *req) { + double sum = 0; + int i; + + if (req->params[0].type != JSON_TYPE_ARRAY) { + return mg_rpc_create_std_error(buf, len, req, + JSON_RPC_INVALID_PARAMS_ERROR); + } + + for (i = 0; i < req->params[0].num_desc; i++) { + if (req->params[i + 1].type != JSON_TYPE_NUMBER) { + return mg_rpc_create_std_error(buf, len, req, + JSON_RPC_INVALID_PARAMS_ERROR); + } + sum += strtod(req->params[i + 1].ptr, NULL); + } + return mg_rpc_create_reply(buf, len, req, "f", sum); +} + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; + static const char *methods[] = { "sum", NULL }; + static mg_rpc_handler_t handlers[] = { rpc_sum, NULL }; + char buf[100]; + + switch (ev) { + case NS_HTTP_REQUEST: + mg_rpc_dispatch(hm->body.p, hm->body.len, buf, sizeof(buf), + methods, handlers); + mg_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n" + "Content-Type: application/json\r\n\r\n%s", + (int) strlen(buf), buf); + nc->flags |= NSF_SEND_AND_CLOSE; + break; + default: + break; + } +} + +int main(void) { + struct mg_mgr mgr; + struct mg_connection *nc; + + mg_mgr_init(&mgr, NULL); + nc = mg_bind(&mgr, s_http_port, ev_handler); + mg_set_protocol_http_websocket(nc); + + printf("Starting JSON-RPC server on port %s\n", s_http_port); + for (;;) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/load_balancer/Dockerfile b/examples/load_balancer/Dockerfile new file mode 100644 index 00000000..7c88956b --- /dev/null +++ b/examples/load_balancer/Dockerfile @@ -0,0 +1,10 @@ +FROM cesanta/mongoose + +COPY load_balancer.c /mongoose/ +WORKDIR /mongoose +RUN mkdir /mongoose/certs; \ + sed -i 's:#include "../../mongoose.h":#include "mongoose.h":' load_balancer.c; \ + cc load_balancer.c mongoose.c -o load_balancer -W -Wall -pthread -DNS_ENABLE_SSL -lssl -lcrypto +EXPOSE 8000 +VOLUME ["/mongoose/certs"] +ENTRYPOINT ["/mongoose/load_balancer"] diff --git a/examples/load_balancer/Makefile b/examples/load_balancer/Makefile new file mode 100644 index 00000000..34ccc884 --- /dev/null +++ b/examples/load_balancer/Makefile @@ -0,0 +1,39 @@ +# To build with SSL under windows, do: +# wine make load_balancer.exe SSL=openssl # OpenSSL build +# wine make load_balancer.exe SSL=krypton # Krypton build + +PROG = load_balancer +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -pthread $(CFLAGS_EXTRA) + +ifeq ($(SSL), openssl) + OPENSSL_PATH = ./openssl-0.9.8 + CFLAGS_EXTRA += -DNS_ENABLE_SSL -I$(OPENSSL_PATH)/include + CFLAGS_EXTRA += /link /libpath:$(OPENSSL_PATH)/lib ssleay32.lib libeay32.lib +endif + +ifeq ($(SSL), krypton) + KRYPTON_PATH = ../../../krypton + CFLAGS_EXTRA += -DNS_ENABLE_SSL $(KRYPTON_PATH)/krypton.c -I$(KRYPTON_PATH) +endif + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I.. /MD /Fe$@ /DNS_ENABLE_THREADS advapi32.lib $(CFLAGS_EXTRA) + +test: $(PROG) + $(MAKE) -C ../api_server + sh unit_test.sh $$(pwd)/$(PROG) + +docker-build: + docker build -t cesanta/load_balancer . + +docker-push: + docker push cesanta/load_balancer + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/load_balancer/README.md b/examples/load_balancer/README.md new file mode 100644 index 00000000..ec5551a3 --- /dev/null +++ b/examples/load_balancer/README.md @@ -0,0 +1,44 @@ +# Mongoose-based HTTP load balancer + +## Configuration + +Load balancer is configured with command-line flags. + +### Global flags + +* `-p port` – TCP port to listen on. Default: 8000. +* `-l log_file` – path to the log file. Default: none. +* `-s ssl_cert` – path to SSL certificate. Default: none. + +### Backend configuration + +Main flag is `-b uri_prefix host_port` – it adds a new backend for a given +URI prefix. Example: `-b /stuff/ 127.0.0.1:8080` will route all requests that +start with '/stuff/' to a backend at port 8080 on localhost. There is a special +syntax for `uri_prefix` that allows you to change the URIs that get passed to +backends: + +* `-b /stuff/=/ 127.0.0.1:8080` – for '/stuff/thing' backend will see '/thing'. +* `-b /stuff/=/other/ 127.0.0.1:8080` – '/stuff/thing' => '/other/thing'. + +Also there are few per-backend flags that can be placed before `-b` and apply +only to the next backend: + +* `-r` – instead of proxying requests load balancer will reply with 302 +redirect. +* `-v vhost` – match not only URI prefix but 'Host:' header as well. + +### Example + +``` +load_balancer -s path/to/cert.pem \ + -v example.com -b /site/=/ 127.0.0.1:8080 \ + -b /static/ 127.0.0.1:8081 \ + -b /static/ 127.0.0.1:8082 +``` + +In this example requests to 'example.com/site/' will be forwarded to the +backend on port 8080 with '/site' prefix stripped off and requests to +'/static/' on any virtual host will be balanced in round-robin fashion between +backends on ports 8081 and 8082. + diff --git a/examples/load_balancer/load_balancer.c b/examples/load_balancer/load_balancer.c new file mode 100644 index 00000000..fb01dfa7 --- /dev/null +++ b/examples/load_balancer/load_balancer.c @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#include "../../mongoose.h" +#include + +#define MAX_IDLE_CONNS 5 +#define CONN_IDLE_TIMEOUT 30 + +struct http_backend; + +struct be_conn { + struct http_backend *be; + struct mg_connection *nc; + time_t idle_deadline; + + STAILQ_ENTRY(be_conn) conns; +}; + +STAILQ_HEAD(be_conn_list_head, be_conn); +struct http_backend { + const char *vhost; /* NULL if any host */ + const char *uri_prefix; /* URI prefix, e.g. "/api/v1/", "/static/" */ + const char *uri_prefix_replacement; /* if not NULL, will replace uri_prefix in + requests to backends */ + const char *host_port; /* Backend address */ + int redirect; /* if true redirect instead of proxy */ + int usage_counter; /* Number of times this backend was chosen */ + + struct be_conn_list_head conns; + int num_conns; +}; + +struct peer { + struct mg_connection *nc; + int64_t body_len; /* Size of the HTTP body to forward */ + int64_t body_sent; /* Number of bytes already forwarded */ + struct { + /* Headers have been sent, no more headers. */ + unsigned int headers_sent : 1; + unsigned int keep_alive : 1; + } flags; +}; + +struct conn_data { + struct be_conn *be_conn; /* Chosen backend */ + struct peer client; /* Client peer */ + struct peer backend; /* Backend peer */ + time_t last_activity; +}; + +static const char *s_error_500 = "HTTP/1.1 500 Failed\r\n"; +static const char *s_content_len_0 = "Content-Length: 0\r\n"; +static const char *s_connection_close = "Connection: close\r\n"; +static const char *s_http_port = "8000"; +static struct http_backend s_vhost_backends[100], s_default_backends[100]; +static int s_num_vhost_backends = 0, s_num_default_backends = 0; +static int s_sig_num = 0; +static int s_backend_keepalive = 0; +static FILE *s_log_file = NULL; +#ifdef NS_ENABLE_SSL +const char *s_ssl_cert = NULL; +#endif + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data); +static void write_log(const char *fmt, ...); + +static void signal_handler(int sig_num) { + signal(sig_num, signal_handler); + s_sig_num = sig_num; +} + +static void send_http_err(struct mg_connection *nc, const char *err_line) { + mg_printf(nc, "%s%s%s\r\n", err_line, s_content_len_0, s_connection_close); +} + +static void respond_with_error(struct conn_data *conn, const char *err_line) { + struct mg_connection *nc = conn->client.nc; + int headers_sent = conn->client.flags.headers_sent; +#ifdef DEBUG + write_log("conn=%p nc=%p respond_with_error %d\n", conn, nc, headers_sent); +#endif + if (nc == NULL) return; + if (!headers_sent) { + send_http_err(nc, err_line); + conn->client.flags.headers_sent = 1; + } + nc->flags |= NSF_SEND_AND_CLOSE; +} + +static int has_prefix(const struct mg_str *uri, const char *prefix) { + size_t prefix_len = strlen(prefix); + return uri->len >= prefix_len && memcmp(uri->p, prefix, prefix_len) == 0; +} + +static int matches_vhost(const struct mg_str *host, const char *vhost) { + size_t vhost_len; + if (vhost == NULL) { + return 1; + } + vhost_len = strlen(vhost); + return host->len == vhost_len && memcmp(host->p, vhost, vhost_len) == 0; +} + +static void write_log(const char *fmt, ...) { + va_list ap; + if (s_log_file != NULL) { + va_start(ap, fmt); + vfprintf(s_log_file, fmt, ap); + fflush(s_log_file); + va_end(ap); + } +} + +static struct http_backend *choose_backend_from_list( + struct http_message *hm, struct http_backend *backends, int num_backends) { + int i; + struct mg_str vhost = {"", 0}; + const struct mg_str *host = mg_get_http_header(hm, "host"); + if (host != NULL) vhost = *host; + + const char *vhost_end = vhost.p; + + while (vhost_end < vhost.p + vhost.len && *vhost_end != ':') { + vhost_end++; + } + vhost.len = vhost_end - vhost.p; + + struct http_backend *chosen = NULL; + for (i = 0; i < num_backends; i++) { + struct http_backend *be = &backends[i]; + if (has_prefix(&hm->uri, be->uri_prefix) && + matches_vhost(&vhost, be->vhost) && + (chosen == NULL || + /* Prefer most specific URI prefixes */ + strlen(be->uri_prefix) > strlen(chosen->uri_prefix) || + /* Among prefixes of the same length chose the least used. */ + (strlen(be->uri_prefix) == strlen(chosen->uri_prefix) && + be->usage_counter < chosen->usage_counter))) { + chosen = be; + } + } + + return chosen; +} + +static struct http_backend *choose_backend(struct http_message *hm) { + struct http_backend *chosen = + choose_backend_from_list(hm, s_vhost_backends, s_num_vhost_backends); + + /* Nothing was chosen for this vhost, look for vhost == NULL backends. */ + if (chosen == NULL) { + chosen = choose_backend_from_list(hm, s_default_backends, + s_num_default_backends); + } + + if (chosen != NULL) chosen->usage_counter++; + + return chosen; +} + +static void forward_body(struct peer *src, struct peer *dst) { + struct mbuf *src_io = &src->nc->recv_mbuf; + if (src->body_sent < src->body_len) { + size_t to_send = src->body_len - src->body_sent; + if (src_io->len < to_send) { + to_send = src_io->len; + } + mg_send(dst->nc, src_io->buf, to_send); + src->body_sent += to_send; + mbuf_remove(src_io, to_send); + } +#ifdef DEBUG + write_log("forward_body %p (ka=%d) -> %p sent %d of %d\n", src->nc, + src->flags.keep_alive, dst->nc, src->body_sent, src->body_len); +#endif +} + +static void forward(struct conn_data *conn, struct http_message *hm, + struct peer *src_peer, struct peer *dst_peer) { + struct mg_connection *src = src_peer->nc; + struct mg_connection *dst = dst_peer->nc; + struct mbuf *io = &src->recv_mbuf; + int i; + int is_request = (src_peer == &conn->client); + src_peer->body_len = hm->body.len; + struct http_backend *be = conn->be_conn->be; + + if (is_request) { + /* Write rewritten request line. */ + size_t trim_len = strlen(be->uri_prefix); + mg_printf(dst, "%.*s%s%.*s\r\n", (int) (hm->uri.p - io->buf), io->buf, + be->uri_prefix_replacement, + (int) (hm->proto.p + hm->proto.len - (hm->uri.p + trim_len)), + hm->uri.p + trim_len); + } else { + /* Reply line goes without modification */ + mg_printf(dst, "%.*s %d %.*s\r\n", (int) hm->proto.len, hm->proto.p, + (int) hm->resp_code, (int) hm->resp_status_msg.len, + hm->resp_status_msg.p); + } + + /* Headers. */ + for (i = 0; i < NS_MAX_HTTP_HEADERS && hm->header_names[i].len > 0; i++) { + struct mg_str hn = hm->header_names[i]; + struct mg_str hv = hm->header_values[i]; +#ifdef NS_ENABLE_SSL + /* + * If we terminate SSL and backend redirects to local HTTP port, + * strip protocol to let client use HTTPS. + * TODO(lsm): web page content may also contain local HTTP references, + * they need to be rewritten too. + */ + if (mg_vcasecmp(&hn, "Location") == 0 && s_ssl_cert != NULL) { + size_t hlen = strlen(be->host_port); + const char *hp = be->host_port, *p = memchr(hp, ':', hlen); + + if (p == NULL) { + p = hp + hlen; + } + + if (mg_ncasecmp(hv.p, "http://", 7) == 0 && + mg_ncasecmp(hv.p + 7, hp, (p - hp)) == 0) { + mg_printf(dst, "Location: %.*s\r\n", (int) (hv.len - (7 + (p - hp))), + hv.p + 7 + (p - hp)); + continue; + } + } +#endif + + /* We always rewrite the connection header depending on the settings. */ + if (mg_vcasecmp(&hn, "Connection") == 0) continue; + + mg_printf(dst, "%.*s: %.*s\r\n", (int) hn.len, hn.p, (int) hv.len, hv.p); + } + + /* Emit the connection header. */ + const char *connection_mode = "close"; + if (dst_peer == &conn->backend) { + if (s_backend_keepalive) connection_mode = "keep-alive"; + } else { + if (conn->client.flags.keep_alive) connection_mode = "keep-alive"; + } + mg_printf(dst, "Connection: %s\r\n", connection_mode); + + mg_printf(dst, "%s", "\r\n"); + + mbuf_remove(io, hm->body.p - hm->message.p); /* We've forwarded headers */ + dst_peer->flags.headers_sent = 1; + + forward_body(src_peer, dst_peer); +} + +struct be_conn *get_conn(struct http_backend *be) { + if (STAILQ_EMPTY(&be->conns)) return NULL; + struct be_conn *result = STAILQ_FIRST(&be->conns); + STAILQ_REMOVE_HEAD(&be->conns, conns); + be->num_conns--; + return result; +} + +/* + * choose_backend parses incoming HTTP request and routes it to the appropriate + * backend. It assumes that clients don't do HTTP pipelining, handling only + * one request request for each connection. To give a hint to backend about + * this it inserts "Connection: close" header into each forwarded request. + */ +static int connect_backend(struct conn_data *conn, struct http_message *hm) { + struct mg_connection *nc = conn->client.nc; + struct http_backend *be = choose_backend(hm); + + write_log("%.*s %.*s backend=%s\n", (int) hm->method.len, hm->method.p, + (int) hm->uri.len, hm->uri.p, be->host_port); + + if (be == NULL) return 0; + if (be->redirect != 0) { + mg_printf(nc, "HTTP/1.1 302 Found\r\nLocation: %s\r\n\r\n", be->host_port); + return 1; + } + struct be_conn *bec = get_conn(be); + if (bec != NULL) { + bec->nc->handler = ev_handler; +#ifdef DEBUG + write_log("conn=%p to %p (%s) reusing bec=%p\n", conn, be, be->host_port, + bec); +#endif + } else { + bec = malloc(sizeof(*conn->be_conn)); + memset(bec, 0, sizeof(*bec)); + bec->nc = mg_connect(nc->mgr, be->host_port, ev_handler); +#ifdef DEBUG + write_log("conn=%p new conn to %p (%s) bec=%p\n", conn, be, be->host_port, + bec); +#endif + if (bec->nc == NULL) { + free(bec); + write_log("Connection to [%s] failed\n", be->host_port); + return 0; + } + } + bec->be = be; + conn->be_conn = bec; + conn->backend.nc = bec->nc; + conn->backend.nc->user_data = conn; + mg_set_protocol_http_websocket(conn->backend.nc); + return 1; +} + +static int is_keep_alive(struct http_message *hm) { + const struct mg_str *connection_header = mg_get_http_header(hm, "Connection"); + if (connection_header == NULL) { + /* HTTP/1.1 connections are keep-alive by default. */ + if (mg_vcasecmp(&hm->proto, "HTTP/1.1") != 0) return 0; + } else if (mg_vcasecmp(connection_header, "keep-alive") != 0) { + return 0; + } + // We must also have Content-Length. + return mg_get_http_header(hm, "Content-Length") != NULL; +} + +static void idle_backend_handler(struct mg_connection *nc, int ev, + void *ev_data) { + (void) ev_data; /* Unused. */ + struct be_conn *bec = nc->user_data; + const time_t now = time(NULL); +#ifdef DEBUG + write_log("%d idle bec=%p nc=%p ev=%d deadline=%d\n", now, bec, nc, ev, + bec->idle_deadline); +#endif + switch (ev) { + case NS_POLL: { + if (bec->idle_deadline > 0 && now > bec->idle_deadline) { +#ifdef DEBUG + write_log("bec=%p nc=%p closing due to idleness\n", bec, bec->nc); +#endif + bec->nc->flags |= NSF_CLOSE_IMMEDIATELY; + } + break; + } + + case NS_CLOSE: { +#ifdef DEBUG + write_log("bec=%p closed\n", bec); +#endif + if (bec->idle_deadline > 0) { + STAILQ_REMOVE(&bec->be->conns, bec, be_conn, conns); + } + free(bec); + break; + } + } +} + +void release_backend(struct conn_data *conn) { + /* Disassociate the backend, put back on the pool. */ + struct be_conn *bec = conn->be_conn; + conn->be_conn = NULL; + if (bec->nc == NULL) { + free(bec); + memset(&conn->backend, 0, sizeof(conn->backend)); + return; + } + struct http_backend *be = bec->be; + bec->nc->user_data = bec; + bec->nc->handler = idle_backend_handler; + if (conn->backend.flags.keep_alive) { + bec->idle_deadline = time(NULL) + CONN_IDLE_TIMEOUT; + STAILQ_INSERT_TAIL(&be->conns, bec, conns); +#ifdef DEBUG + write_log("bec=%p becoming idle\n", bec); +#endif + be->num_conns++; + while (be->num_conns > MAX_IDLE_CONNS) { + bec = STAILQ_FIRST(&be->conns); + STAILQ_REMOVE_HEAD(&be->conns, conns); + be->num_conns--; + bec->idle_deadline = 0; + bec->nc->flags = NSF_CLOSE_IMMEDIATELY; +#ifdef DEBUG + write_log("bec=%p evicted\n", bec); +#endif + } + } else { + bec->idle_deadline = 0; + bec->nc->flags |= NSF_CLOSE_IMMEDIATELY; + } + memset(&conn->backend, 0, sizeof(conn->backend)); +} + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct conn_data *conn = (struct conn_data *) nc->user_data; + const time_t now = time(NULL); +#ifdef DEBUG + write_log("%d conn=%p nc=%p ev=%d ev_data=%p bec=%p bec_nc=%p\n", now, conn, + nc, ev, ev_data, conn != NULL ? conn->be_conn : NULL, + conn != NULL && conn->be_conn != NULL ? conn->be_conn->nc : NULL); +#endif + + if (conn == NULL) { + if (ev == NS_ACCEPT) { + conn = calloc(1, sizeof(*conn)); + if (conn == NULL) { + send_http_err(nc, s_error_500); + } else { + memset(conn, 0, sizeof(*conn)); + nc->user_data = conn; + conn->client.nc = nc; + conn->client.body_len = -1; + conn->backend.body_len = -1; + conn->last_activity = now; + } + return; + } else { + nc->flags |= NSF_CLOSE_IMMEDIATELY; + return; + } + } + + if (ev != NS_POLL) conn->last_activity = now; + + switch (ev) { + case NS_HTTP_REQUEST: { /* From client */ + assert(conn != NULL); + assert(conn->be_conn == NULL); + struct http_message *hm = (struct http_message *) ev_data; + conn->client.flags.keep_alive = is_keep_alive(hm); + + if (!connect_backend(conn, hm)) { + respond_with_error(conn, s_error_500); + break; + } + + if (conn->backend.nc == NULL) { + /* This is a redirect, we're done. */ + conn->client.nc->flags |= NSF_SEND_AND_CLOSE; + break; + } + + forward(conn, hm, &conn->client, &conn->backend); + break; + } + + case NS_CONNECT: { /* To backend */ + assert(conn != NULL); + assert(conn->be_conn != NULL); + int status = *(int *) ev_data; + if (status != 0) { + write_log("Error connecting to %s: %d (%s)\n", + conn->be_conn->be->host_port, status, strerror(status)); + /* TODO(lsm): mark backend as defunct, try it later on */ + respond_with_error(conn, s_error_500); + conn->be_conn->nc = NULL; + release_backend(conn); + break; + } + break; + } + + case NS_HTTP_REPLY: { /* From backend */ + assert(conn != NULL); + struct http_message *hm = (struct http_message *) ev_data; + conn->backend.flags.keep_alive = s_backend_keepalive && is_keep_alive(hm); + forward(conn, hm, &conn->backend, &conn->client); + release_backend(conn); + if (!conn->client.flags.keep_alive) { + conn->client.nc->flags |= NSF_SEND_AND_CLOSE; + } else { +#ifdef DEBUG + write_log("conn=%p remains open\n", conn); +#endif + } + break; + } + + case NS_POLL: { + assert(conn != NULL); + if (now - conn->last_activity > CONN_IDLE_TIMEOUT && + conn->backend.nc == NULL /* not waiting for backend */) { +#ifdef DEBUG + write_log("conn=%p has been idle for too long\n", conn); + conn->client.nc->flags |= NSF_SEND_AND_CLOSE; +#endif + } + break; + } + + case NS_CLOSE: { + assert(conn != NULL); + if (nc == conn->client.nc) { +#ifdef DEBUG + write_log("conn=%p nc=%p client closed, body_sent=%d\n", conn, nc, + conn->backend.body_sent); +#endif + conn->client.nc = NULL; + if (conn->backend.nc != NULL) { + conn->backend.nc->flags |= NSF_CLOSE_IMMEDIATELY; + } + } else if (nc == conn->backend.nc) { +#ifdef DEBUG + write_log("conn=%p nc=%p backend closed\n", conn, nc); +#endif + conn->backend.nc = NULL; + if (conn->client.nc != NULL && + (conn->backend.body_len < 0 || + conn->backend.body_sent < conn->backend.body_len)) { + write_log("Backend %s disconnected.\n", conn->be_conn->be->host_port); + respond_with_error(conn, s_error_500); + } + } + if (conn->client.nc == NULL && conn->backend.nc == NULL) { + free(conn); + } + break; + } + } +} + +static void print_usage_and_exit(const char *prog_name) { + fprintf(stderr, + "Usage: %s [-D debug_dump_file] [-p http_port] [-l log] [-k]" +#if NS_ENABLE_SSL + "[-s ssl_cert] " +#endif + "<[-r] [-v vhost] -b uri_prefix[=replacement] host_port> ... \n", + prog_name); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + int i, redirect = 0; + const char *vhost = NULL; + + mg_mgr_init(&mgr, NULL); + + /* Parse command line arguments */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-D") == 0) { + mgr.hexdump_file = argv[i + 1]; + i++; + } else if (strcmp(argv[i], "-k") == 0) { + s_backend_keepalive = 1; + } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) { + if (strcmp(argv[i + 1], "-") == 0) { + s_log_file = stdout; + } else { + s_log_file = fopen(argv[i + 1], "a"); + if (s_log_file == NULL) { + perror("fopen"); + exit(EXIT_FAILURE); + } + } + i++; + } else if (strcmp(argv[i], "-p") == 0) { + s_http_port = argv[i + 1]; + i++; + } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) { + redirect = 1; + } else if (strcmp(argv[i], "-v") == 0 && i + 1 < argc) { + if (strcmp(argv[i + 1], "") == 0) { + vhost = NULL; + } else { + vhost = argv[i + 1]; + } + i++; + } else if (strcmp(argv[i], "-b") == 0 && i + 2 < argc) { + struct http_backend *be = + vhost != NULL ? &s_vhost_backends[s_num_vhost_backends++] + : &s_default_backends[s_num_default_backends++]; + STAILQ_INIT(&be->conns); + char *r = NULL; + be->vhost = vhost; + be->uri_prefix = argv[i + 1]; + be->host_port = argv[i + 2]; + be->redirect = redirect; + be->uri_prefix_replacement = be->uri_prefix; + if ((r = strchr(be->uri_prefix, '=')) != NULL) { + *r = '\0'; + be->uri_prefix_replacement = r + 1; + } + printf( + "Adding backend for %s%s : %s " + "[redirect=%d,prefix_replacement=%s]\n", + be->vhost == NULL ? "" : be->vhost, be->uri_prefix, be->host_port, + be->redirect, be->uri_prefix_replacement); + vhost = NULL; + redirect = 0; + i += 2; +#ifdef NS_ENABLE_SSL + } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) { + s_ssl_cert = argv[++i]; +#endif + } else { + print_usage_and_exit(argv[0]); + } + } + + /* Open listening socket */ + if ((nc = mg_bind(&mgr, s_http_port, ev_handler)) == NULL) { + fprintf(stderr, "mg_bind(%s) failed\n", s_http_port); + exit(EXIT_FAILURE); + } + +#if NS_ENABLE_SSL + if (s_ssl_cert != NULL) { + const char *err_str = mg_set_ssl(nc, s_ssl_cert, NULL); + if (err_str != NULL) { + fprintf(stderr, "Error loading SSL cert: %s\n", err_str); + exit(1); + } + } +#endif + mg_set_protocol_http_websocket(nc); + + if (s_num_vhost_backends + s_num_default_backends == 0) { + print_usage_and_exit(argv[0]); + } + + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + /* Run event loop until signal is received */ + printf("Starting LB on port %s\n", s_http_port); + while (s_sig_num == 0) { + mg_mgr_poll(&mgr, 1000); + } + + /* Cleanup */ + mg_mgr_free(&mgr); + + printf("Exiting on signal %d\n", s_sig_num); + + return EXIT_SUCCESS; +} diff --git a/examples/load_balancer/unit_test.sh b/examples/load_balancer/unit_test.sh new file mode 100644 index 00000000..019fafda --- /dev/null +++ b/examples/load_balancer/unit_test.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +PROG=$1 +PORT=8002 + +cleanup() { + kill -9 $PID >/dev/null 2>&1 +} + +#set -x +trap cleanup EXIT + +cleanup +$PROG -p $PORT -b /api/ 127.0.0.1:8000 & +PID=$! + +# Perform api_server unit test through the load balancer by passing +# load balancer port to the unit test script +(cd ../api_server && make && sh unit_test.sh ./api_server $PORT) + +exit $? diff --git a/examples/mjpg_streamer/Makefile b/examples/mjpg_streamer/Makefile deleted file mode 100644 index 35946c0a..00000000 --- a/examples/mjpg_streamer/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = mjpg_streamer -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/mjpg_streamer/mjpg_streamer.c b/examples/mjpg_streamer/mjpg_streamer.c deleted file mode 100644 index 4bac6c14..00000000 --- a/examples/mjpg_streamer/mjpg_streamer.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include "mongoose.h" - -static void send_file(struct mg_connection *conn, const char *path) { - char buf[1024]; - struct stat st; - int n; - FILE *fp; - - if (stat(path, &st) == 0 && (fp = fopen(path, "rb")) != NULL) { - mg_printf(conn, "--w00t\r\nContent-Type: image/jpeg\r\n" - "Content-Length: %lu\r\n\r\n", (unsigned long) st.st_size); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { - mg_write(conn, buf, n); - } - fclose(fp); - mg_write(conn, "\r\n", 2); - } -} - -struct conn_state { - int file_index; - time_t last_poll; -}; - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - const char **file_names = (const char **) conn->server_param; - struct conn_state *state; - time_t now = time(NULL); - - switch (ev) { - - case MG_AUTH: - return MG_TRUE; - - case MG_REQUEST: - if (strcmp(conn->uri, "/stream") != 0) { - mg_send_header(conn, "Content-Type", "text/html"); - mg_printf_data(conn, "%s", - "Go to /stream for MJPG stream"); - return MG_TRUE; - } - - mg_printf(conn, "%s", - "HTTP/1.0 200 OK\r\n" "Cache-Control: no-cache\r\n" - "Pragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\n" - "Connection: close\r\nContent-Type: multipart/x-mixed-replace; " - "boundary=--w00t\r\n\r\n"); - - send_file(conn, file_names[0]); - - state = (struct conn_state *) malloc(sizeof(*state)); - conn->connection_param = state; - state->file_index = 1; // First file is already sent - state->last_poll = time(NULL); - return MG_MORE; - - case MG_POLL: - state = (struct conn_state *) conn->connection_param; - - if (state != NULL && now > state->last_poll) { - if (file_names[state->file_index] != NULL) { - send_file(conn, file_names[state->file_index]); - state->file_index++; - if (file_names[state->file_index] == NULL) { - return MG_TRUE; // No more images, close connection - } - } - state->last_poll = now; - } - return MG_FALSE; - - case MG_CLOSE: - free(conn->connection_param); - conn->connection_param = NULL; - return MG_FALSE; - - default: - return MG_FALSE; - } -} - -int main(int argc, char *argv[]) { - struct mg_server *server; - - if (argc < 3) { - printf("Usage: %s image1.jpg image2.jpg ...\n", argv[0]); - return 1; - } - - server = mg_create_server(&argv[1], ev_handler); - mg_set_option(server, "listening_port", "8080"); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/mqtt_broker/Makefile b/examples/mqtt_broker/Makefile new file mode 100644 index 00000000..4e5590c1 --- /dev/null +++ b/examples/mqtt_broker/Makefile @@ -0,0 +1,14 @@ +PROG = mqtt_broker +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -pthread -DNS_ENABLE_SSL -DNS_ENABLE_MQTT_BROKER -lssl -lcrypto $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /DNS_ENABLE_SSL /DNS_ENABLE_MQTT_BROKER /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/mqtt_broker/mqtt_broker.c b/examples/mqtt_broker/mqtt_broker.c new file mode 100644 index 00000000..2bf82251 --- /dev/null +++ b/examples/mqtt_broker/mqtt_broker.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +#include "../../mongoose.h" + +int main(void) { + struct mg_mgr mgr; + const char *address = "0.0.0.0:1883"; + struct mg_connection *nc; + struct mg_mqtt_broker brk; + + mg_mgr_init(&mgr, NULL); + mg_mqtt_broker_init(&brk, NULL); + + if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) { + fprintf(stderr, "mg_bind(%s) failed\n", address); + exit(EXIT_FAILURE); + } + nc->user_data = &brk; + + /* + * TODO: Add a HTTP status page that shows current sessions + * and subscriptions + */ + + for(;;) { + mg_mgr_poll(&mgr, 1000); + } +} diff --git a/examples/mqtt_client/Makefile b/examples/mqtt_client/Makefile new file mode 100644 index 00000000..e36a83d5 --- /dev/null +++ b/examples/mqtt_client/Makefile @@ -0,0 +1,14 @@ +PROG = mqtt_client +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -pthread -DNS_ENABLE_SSL -lssl -lcrypto $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /DNS_ENABLE_SSL /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/mqtt_client/mqtt_client.c b/examples/mqtt_client/mqtt_client.c new file mode 100644 index 00000000..005e6c17 --- /dev/null +++ b/examples/mqtt_client/mqtt_client.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + * This software is dual-licensed: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. For the terms of this + * license, see . + * + * You are free to use this software under the terms of the GNU General + * Public License, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * Alternatively, you can license this software under a commercial + * license, as set out in . + */ + +#include "mongoose.h" + +struct mg_mqtt_topic_expression topic_expressions[] = { + {"/stuff", 0} +}; + +static void ev_handler(struct mg_connection *nc, int ev, void *p) { + struct mg_mqtt_message *msg = (struct mg_mqtt_message *)p; + (void) nc; + +#if 0 + if (ev != NS_POLL) + printf("USER HANDLER GOT %d\n", ev); +#endif + + switch (ev) { + case NS_CONNECT: + mg_set_protocol_mqtt(nc); + mg_send_mqtt_handshake(nc, "dummy"); + break; + case NS_MQTT_CONNACK: + if (msg->connack_ret_code != NS_MQTT_CONNACK_ACCEPTED) { + printf("Got mqtt connection error: %d\n", msg->connack_ret_code); + exit(1); + } + printf("Subscribing to '/stuff'\n"); + mg_mqtt_subscribe(nc, topic_expressions, sizeof(topic_expressions)/sizeof(*topic_expressions), 42); + break; + case NS_MQTT_PUBACK: + printf("Message publishing acknowledged (msg_id: %d)\n", msg->message_id); + break; + case NS_MQTT_SUBACK: + printf("Subscription acknowledged, forwarding to '/test'\n"); + break; + case NS_MQTT_PUBLISH: + { +#if 0 + char hex[1024] = {0}; + mg_hexdump(nc->recv_mbuf.buf, msg->payload.len, hex, sizeof(hex)); + printf("Got incoming message %s:\n%s", msg->topic, hex); +#else + printf("Got incoming message %s: %.*s\n", msg->topic, (int)msg->payload.len, msg->payload.p); +#endif + + printf("Forwarding to /test\n"); + mg_mqtt_publish(nc, "/test", 65, NS_MQTT_QOS(0), msg->payload.p, msg->payload.len); + } + break; + case NS_CLOSE: + printf("Connection closed\n"); + exit(1); + } +} + +int main(void) { + struct mg_mgr mgr; + const char *address = "localhost:1883"; + + mg_mgr_init(&mgr, NULL); + + if (mg_connect(&mgr, address, ev_handler) == NULL) { + fprintf(stderr, "mg_connect(%s) failed\n", address); + exit(EXIT_FAILURE); + } + + for(;;) { + mg_mgr_poll(&mgr, 1000); + } +} diff --git a/examples/multi_threaded_server/Makefile b/examples/multi_threaded_server/Makefile deleted file mode 100644 index 2b08db12..00000000 --- a/examples/multi_threaded_server/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = multi_threaded_server -CFLAGS = -W -Wall -I../.. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/multi_threaded_server/multi_threaded_server.c b/examples/multi_threaded_server/multi_threaded_server.c deleted file mode 100644 index 30af3f10..00000000 --- a/examples/multi_threaded_server/multi_threaded_server.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "mongoose.h" - -// Start a browser and hit refresh couple of times. The replies will -// come from both server instances. -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_REQUEST) { - mg_send_header(conn, "Content-Type", "text/plain"); - mg_printf_data(conn, "This is a reply from server instance # %s", - (char *) conn->server_param); - return MG_TRUE; - } else if (ev == MG_AUTH) { - return MG_TRUE; - } else { - return MG_FALSE; - } -} - -static void *serve(void *server) { - for (;;) mg_poll_server((struct mg_server *) server, 1000); - return NULL; -} - -int main(void) { - struct mg_server *server1, *server2; - - server1 = mg_create_server((void *) "1", ev_handler); - server2 = mg_create_server((void *) "2", ev_handler); - - // Make both server1 and server2 listen on the same sockets - mg_set_option(server1, "listening_port", "8080"); - mg_copy_listeners(server1, server2); - - // server1 goes to separate thread, server 2 runs in main thread. - // IMPORTANT: NEVER LET DIFFERENT THREADS HANDLE THE SAME SERVER. - mg_start_thread(serve, server1); - mg_start_thread(serve, server2); - getchar(); - - return 0; -} diff --git a/examples/multithreaded_restful_server/Makefile b/examples/multithreaded_restful_server/Makefile new file mode 100644 index 00000000..6885b8c8 --- /dev/null +++ b/examples/multithreaded_restful_server/Makefile @@ -0,0 +1,18 @@ +PROG = multithreaded_restful_server +SOURCES = $(PROG).c ../../mongoose.c +APP_FLAGS = -DNS_ENABLE_THREADS $(CFLAGS_EXTRA) + +ifeq ($(OS), Windows_NT) +APP_FLAGS += advapi32.lib +endif + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ -W -Wall -I../.. -pthread $(APP_FLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ $(APP_FLAGS) + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/multithreaded_restful_server/multithreaded_restful_server.c b/examples/multithreaded_restful_server/multithreaded_restful_server.c new file mode 100644 index 00000000..3cf248d7 --- /dev/null +++ b/examples/multithreaded_restful_server/multithreaded_restful_server.c @@ -0,0 +1,52 @@ +// Copyright (c) 2015 Cesanta Software Limited +// All rights reserved + +// This example shows how to handle long, blocking requests by +// handing off computation to different threads. Here, each +// request spawns a new thread. In a production scenario, a thread +// pools can be used for efficiency, if required. +// Long computation is simulated by sleeping for a random interval. + +#include "mongoose.h" + +static const char *s_http_port = "8000"; + +static void ev_handler(struct mg_connection *c, int ev, void *p) { + if (ev == NS_HTTP_REQUEST) { + struct http_message *hm = (struct http_message *) p; + char reply[100]; + + /* Simulate long calculation */ + sleep(3); + + /* Send the reply */ + snprintf(reply, sizeof(reply), "{ \"uri\": \"%.*s\" }\n", + (int) hm->uri.len, hm->uri.p); + mg_printf(c, "HTTP/1.1 200 OK\r\n" + "Content-Type: application/json\r\n" + "Content-Length: %d\r\n" + "\r\n" + "%s", + (int) strlen(reply), reply); + } +} + +int main(void) { + struct mg_mgr mgr; + struct mg_connection *nc; + + mg_mgr_init(&mgr, NULL); + nc = mg_bind(&mgr, s_http_port, ev_handler); + mg_set_protocol_http_websocket(nc); + + /* For each new connection, execute ev_handler in a separate thread */ + mg_enable_multithreading(nc); + + printf("Starting multi-threaded server on port %s\n", s_http_port); + for (;;) { + mg_mgr_poll(&mgr, 3000); + } + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/netcat/Makefile b/examples/netcat/Makefile new file mode 100644 index 00000000..62c8d161 --- /dev/null +++ b/examples/netcat/Makefile @@ -0,0 +1,14 @@ +PROG = nc +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -pthread -DNS_ENABLE_SSL -DNS_ENABLE_THREADS -lssl -lcrypto $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /DNS_ENABLE_SSL /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/netcat/nc.c b/examples/netcat/nc.c new file mode 100644 index 00000000..eceb6583 --- /dev/null +++ b/examples/netcat/nc.c @@ -0,0 +1,140 @@ +// Copyright (c) 2014 Cesanta Software Limited +// All rights reserved +// +// This software is dual-licensed: you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. For the terms of this +// license, see . +// +// You are free to use this software under the terms of the GNU General +// Public License, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// Alternatively, you can license this software under a commercial +// license, as set out in . +// +// $Date: 2014-09-28 05:04:41 UTC $ + +// This file implements "netcat" utility with SSL and traffic hexdump. + +#include "mongoose.h" + +static sig_atomic_t s_received_signal = 0; + +static void signal_handler(int sig_num) { + signal(sig_num, signal_handler); + s_received_signal = sig_num; +} + +static void show_usage_and_exit(const char *prog_name) { + fprintf(stderr, "%s\n", "Copyright (c) 2014 CESANTA SOFTWARE"); + fprintf(stderr, "%s\n", "Usage:"); + fprintf(stderr, " %s\n [-d debug_file] [-l] [tcp|ssl]://[ip:]port[:cert][:ca_cert]", + prog_name); + fprintf(stderr, "%s\n", "Examples:"); + fprintf(stderr, " %s\n -d hexdump.txt ssl://google.com:443", prog_name); + fprintf(stderr, " %s\n -l ssl://443:ssl_cert.pem", prog_name); + fprintf(stderr, " %s\n -l tcp://8080", prog_name); + exit(EXIT_FAILURE); +} + +static void on_stdin_read(struct mg_connection *nc, int ev, void *p) { + int ch = * (int *) p; + + (void) ev; + + if (ch < 0) { + // EOF is received from stdin. Schedule the connection to close + nc->flags |= NSF_SEND_AND_CLOSE; + if (nc->send_mbuf.len <= 0) { + nc->flags |= NSF_CLOSE_IMMEDIATELY; + } + } else { + // A character is received from stdin. Send it to the connection. + unsigned char c = (unsigned char) ch; + mg_send(nc, &c, 1); + } +} + +static void *stdio_thread_func(void *param) { + struct mg_mgr *mgr = (struct mg_mgr *) param; + int ch; + + // Read stdin until EOF character by character, sending them to the mgr + while ((ch = getchar()) != EOF) { + mg_broadcast(mgr, on_stdin_read, &ch, sizeof(ch)); + } + s_received_signal = 1; + + return NULL; +} + +static void ev_handler(struct mg_connection *nc, int ev, void *p) { + (void) p; + + switch (ev) { + case NS_ACCEPT: + case NS_CONNECT: + mg_start_thread(stdio_thread_func, nc->mgr); + break; + + case NS_CLOSE: + s_received_signal = 1; + break; + + case NS_RECV: + fwrite(nc->recv_mbuf.buf, 1, nc->recv_mbuf.len, stdout); + mbuf_remove(&nc->recv_mbuf, nc->recv_mbuf.len); + break; + + default: + break; + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + int i, is_listening = 0; + const char *address = NULL; + + mg_mgr_init(&mgr, NULL); + + // Parse command line options + for (i = 1; i < argc && argv[i][0] == '-'; i++) { + if (strcmp(argv[i], "-l") == 0) { + is_listening = 1; + } else if (strcmp(argv[i], "-d") == 0 && i + 1 < argc) { + mgr.hexdump_file = argv[++i]; + } else { + show_usage_and_exit(argv[0]); + } + } + + if (i + 1 == argc) { + address = argv[i]; + } else { + show_usage_and_exit(argv[0]); + } + + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGPIPE, SIG_IGN); + + if (is_listening) { + if (mg_bind(&mgr, address, ev_handler) == NULL) { + fprintf(stderr, "mg_bind(%s) failed\n", address); + exit(EXIT_FAILURE); + } + } else if (mg_connect(&mgr, address, ev_handler) == NULL) { + fprintf(stderr, "mg_connect(%s) failed\n", address); + exit(EXIT_FAILURE); + } + + while (s_received_signal == 0) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return EXIT_SUCCESS; +} diff --git a/examples/proxy_server/Makefile b/examples/proxy_server/Makefile deleted file mode 100644 index 7a5d2f7d..00000000 --- a/examples/proxy_server/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = proxy_server -FLAGS = -I../.. -DNS_ENABLE_SSL -CFLAGS = -W -Wall -g -O0 -pthread -lssl -DMONGOOSE_ENABLE_THREADS $(FLAGS) $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -unix: $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/proxy_server/proxy_server.c b/examples/proxy_server/proxy_server.c deleted file mode 100644 index cef0f24c..00000000 --- a/examples/proxy_server/proxy_server.c +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2014 Cesanta Software Limited -// All rights reserved -// -// To build and run this example: -// git clone https://github.com/cesanta/net_skeleton.git -// git clone https://github.com/cesanta/mongoose.git -// cd mongoose/examples -// make proxy -// ./proxy -// -// Configure your browser to use localhost:2014 as a proxy for all protocols -// Then, navigate to https://cesanta.com - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#define sleep(x) Sleep((x) * 1000) -#else -#include -#endif - -#include "mongoose.h" - -static int s_received_signal = 0; -static struct mg_server *s_server = NULL; - -#define SSE_CONNECTION ((void *) 1) - -static void elog(int do_exit, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputc('\n', stderr); - if (do_exit) exit(EXIT_FAILURE); -} - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_received_signal = sig_num; -} - -static int sse_push(struct mg_connection *conn, enum mg_event ev) { - if (ev == MG_POLL && conn->connection_param == SSE_CONNECTION) { - mg_printf(conn, "data: %s\r\n\r\n", (const char *) conn->callback_param); - } - return MG_TRUE; -} - -static void *sse_pusher_thread_func(void *param) { - while (s_received_signal == 0) { - mg_wakeup_server_ex(s_server, sse_push, "%lu %s", - (unsigned long) time(NULL), (const char *) param); - sleep(1); - } - return NULL; -} - -// Return: 1 if regular file, 2 if directory, 0 if not found -static int exists(const char *path) { - struct stat st; - return stat(path, &st) != 0 ? 0 : S_ISDIR(st.st_mode) == 0 ? 1 : 2; -} - -// Return: 1 if regular file, 2 if directory, 0 if not found -static int is_local_file(const char *uri, char *path, size_t path_len) { - snprintf(path, path_len, "%s/%s", - mg_get_option(s_server, "document_root"), uri); - return exists(path); -} - -static int try_to_serve_locally(struct mg_connection *conn) { - char path[500], buf[2000]; - int n, res; - FILE *fp = NULL; - - if ((res = is_local_file(conn->uri, path, sizeof(path))) == 2) { - strncat(path, "/index.html", sizeof(path) - strlen(path) - 1); - res = exists(path); - printf("PATH: [%s]\n", path); - } - if (res == 0) return MG_FALSE; - - if ((fp = fopen(path, "rb")) != NULL) { - printf("Serving [%s] locally \n", path); - mg_send_header(conn, "Connection", "close"); - mg_send_header(conn, "Content-Type", mg_get_mime_type(path, "text/plain")); - while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { - mg_send_data(conn, buf, n); - } - mg_send_data(conn, "", 0); - fclose(fp); - } - return fp == NULL ? MG_FALSE : MG_TRUE; -} - -static int is_resource_present_locally(const char *uri) { - char path[500]; - return is_local_file(uri, path, sizeof(path)) || strcmp(uri, "/api/sse") == 0; -} - -static int proxy_event_handler(struct mg_connection *conn, enum mg_event ev) { - static const char target_url[] = "http://cesanta.com"; - static int target_url_size = sizeof(target_url) - 1; - const char *host; - - switch (ev) { - case MG_REQUEST: - host = mg_get_header(conn, "Host"); - printf("[%s] [%s] [%s]\n", conn->request_method, conn->uri, - host == NULL ? "" : host); - if (strstr(conn->uri, "/qqq") != NULL) s_received_signal = SIGTERM; - - // Proxied HTTPS requests use "CONNECT foo.com:443" - // Proxied HTTP requests use "GET http://..... " - // Serve requests for target_url from the local FS. - if (memcmp(conn->uri, target_url, target_url_size) == 0 && - is_resource_present_locally(conn->uri + target_url_size)) { - conn->uri += target_url_size; // Leave only path in the URI - } - - if (strcmp(conn->uri, "/api/sse") == 0) { - conn->connection_param = SSE_CONNECTION; - mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n" - "Content-Type: text/event-stream\r\n" - "Cache-Control: no-cache\r\n\r\n"); - return MG_MORE; - } - - if (host != NULL && strstr(host, "cesanta") != NULL) { - return try_to_serve_locally(conn); - } - - // Enable man-in-the-middle SSL mode for oracle.com - if (!strcmp(conn->request_method, "CONNECT") && - !strcmp(host, "oracle.com")) { - mg_terminate_ssl(conn, "ssl_cert.pem"); // MUST return MG_MORE after - return MG_MORE; - } - - return MG_FALSE; - case MG_AUTH: - return MG_TRUE; - default: - return MG_FALSE; - } -} - -static void setopt(struct mg_server *s, const char *opt, const char *val) { - const char *err_msg = mg_set_option(s, opt, val); - if (err_msg != NULL) { - elog(1, "Error setting [%s]: [%s]", opt, err_msg); - } -} - -int main(int argc, char *argv[]) { - const char *port = "2014", *dump = NULL, *root = "proxy_web_root"; - int i; - - // Parse command line options - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-port") == 0 && i + 1 < argc) { - port = argv[++i]; - } else if (strcmp(argv[i], "-root") == 0 && i + 1 < argc) { - root = argv[++i]; - } else if (strcmp(argv[i], "-dump") == 0 && i + 1 < argc) { - dump = argv[++i]; - } else { - elog(1, "Usage: %s [-cert FILE] [-ca_cert FILE] [-port PORT]", argv[0]); - } - } - - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - // Create and configure proxy server - s_server = mg_create_server(NULL, &proxy_event_handler); - setopt(s_server, "enable_proxy", "yes"); - setopt(s_server, "document_root", root); - setopt(s_server, "listening_port", port); - setopt(s_server, "hexdump_file", dump); - - // Start two SSE pushing threads - mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_1"); - mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_2"); - - // Start serving in the main thread - printf("Starting on port %s\n", mg_get_option(s_server, "listening_port")); - while (s_received_signal == 0) { - mg_poll_server(s_server, 1000); - } - printf("Existing on signal %d\n", s_received_signal); - mg_destroy_server(&s_server); - - return EXIT_SUCCESS; -} diff --git a/examples/proxy_server/proxy_web_root/app1/index.html b/examples/proxy_server/proxy_web_root/app1/index.html deleted file mode 100644 index 5b5c8167..00000000 --- a/examples/proxy_server/proxy_web_root/app1/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - App1 Index - - - - -

App1 index page. Served locally from the the proxy server filesystem

- -

image that references non-existent local resource. Forwarded to - the 'real' proxy target:

- - -

Google logo via HTTPS (external resource, served by remote host):

- - -

Same image via HTTP:

- - - - diff --git a/examples/proxy_server/proxy_web_root/app2/index.html b/examples/proxy_server/proxy_web_root/app2/index.html deleted file mode 100644 index 28d4bead..00000000 --- a/examples/proxy_server/proxy_web_root/app2/index.html +++ /dev/null @@ -1,37 +0,0 @@ - - - App2 Index - - - - -

App2 index page. Served locally from the - the proxy's filesystem.

-

- Following div shows proxy forwarding of websocket connection, served by - ws://echo.websocket.org: -

- -
- - diff --git a/examples/proxy_server/proxy_web_root/index.html b/examples/proxy_server/proxy_web_root/index.html deleted file mode 100644 index d8343bf3..00000000 --- a/examples/proxy_server/proxy_web_root/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - proxy index - - - -

proxy index page.

-
    -
  • App1 - App1 root
  • -
  • App2 - App2 root
  • -
- -

SSE pushes, done by separate threads at random times:

-
- - - diff --git a/examples/proxy_server/ssl_cert.pem b/examples/proxy_server/ssl_cert.pem deleted file mode 100644 index f7e15a0e..00000000 --- a/examples/proxy_server/ssl_cert.pem +++ /dev/null @@ -1,50 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAwONaLOP7EdegqjRuQKSDXzvHmFMZfBufjhELhNjo5KsL4ieH -hMSGCcSV6y32hzhqR5lvTViaQez+xhc58NZRu+OUgEhodRBW/vAOjpz/xdMz5HaC -EhP3E9W1pkitVseS8B5rrgJo1BfCGai1fPav1nutPq2Kj7vMy24+g460Lonf6ln1 -di4aTIRtAqXtUU6RFpPJP35PkCXbTK65O8HJSxxt/XtfoezHCU5+UIwmZGYx46UB -Wzg3IfK6bGPSiHU3pdiTol0uMPt/GUK+x4NyZJ4/ImsNAicRwMBdja4ywHKXJehH -gXBthsVIHbL21x+4ibsg9eVM/XioTV6tW3IrdwIDAQABAoIBACFfdLutmkQFBcRN -HAJNNHmmsyr0vcUOVnXTFyYeDXV67qxrYHQlOHe6LqIpKq1Mon7O2kYMnWvooFAP -trOnsS6L+qaTYJdYg2TKjgo4ubw1hZXytyB/mdExuaMSkgMgtpia+tB5lD+V+LxN -x1DesZ+veFMO3Zluyckswt4qM5yVa04YFrt31H0E1rJfIen61lidXIKYmHHWuRxK -SadjFfbcqJ6P9ZF22BOkleg5Fm5NaxJmyQynOWaAkSZa5w1XySFfRjRfsbDr64G6 -+LSG8YtRuvfxnvUNhynVPHcpE40eiPo6v8Ho6yZKXpV5klCKciodXAORsswSoGJa -N3nnu/ECgYEA6Yb2rM3QUEPIALdL8f/OzZ1GBSdiQB2WSAxzl9pR/dLF2H+0pitS -to0830mk92ppVmRVD3JGxYDRZQ56tlFXyGaCzJBMRIcsotAhBoNbjV0i9n5bLJYf -BmjU9yvWcgsTt0tr3B0FrtYyp2tCvwHqlxvFpFdUCj2oRw2uGpkhmNkCgYEA03M6 -WxFhsix3y6eVCVvShfbLBSOqp8l0qiTEty+dgVQcWN4CO/5eyaZXKxlCG9KMmKxy -Yx+YgxZrDhfaZ0cxhHGPRKEAxM3IKwT2C8/wCaSiLWXZZpTifnSD99vtOt4wEfrG -+AghNd5kamFiM9tU0AyvhJc2vdJFuXrfeC7ntM8CgYBGDA+t4cZcbRhu7ow/OKYF -kulP3nJgHP/Y+LMrl3cEldZ2jEfZmCElVNQvfd2XwTl7injhOzvzPiKRF3jDez7D -g8w0JAxceddvttJRK9GoY4l7OoeKpjUELSnEQkf+yUfOsTbXPXVY7jMfeNL6jE6b -qN7t3qv8rmXtejMBE3G6cQKBgGR5W2BMiRSlxqKx1cKlrApV87BUe1HRCyuR3xuA -d6Item7Lx1oEi7vb242yKdSYnpApWQ06xTh83Y/Ly87JaIEbiM0+h+P8OEIg0F1a -iB+86AcUX1I8KseVy+Np0HbpfwP8GrFfA5DaRPK7pXMopEtby8cAJ1XZZaI1/ZvZ -BebHAoGAcQU9WvCkT+nIp9FpXfBybYUsvgkaizMIqp66/l3GYgYAq8p1VLGvN4v5 -ec0dW58SJrCpqsM3NP78DtEzQf9OOsk+FsjBFzDU2RkeUreyt2/nQBj/2mN/+hEy -hYN0Zii2yTb63jGxKY6gH1R/r9dL8kXaJmcZrfSa3AgywnteJWg= ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCX05m0b053QzANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTA4MTIwNzEwMjUyMloXDTE4MTIwNTEwMjUyMlowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMDjWizj+xHXoKo0bkCkg187x5hTGXwbn44RC4TY6OSrC+Inh4TEhgnElest9oc4 -akeZb01YmkHs/sYXOfDWUbvjlIBIaHUQVv7wDo6c/8XTM+R2ghIT9xPVtaZIrVbH -kvAea64CaNQXwhmotXz2r9Z7rT6tio+7zMtuPoOOtC6J3+pZ9XYuGkyEbQKl7VFO -kRaTyT9+T5Al20yuuTvByUscbf17X6HsxwlOflCMJmRmMeOlAVs4NyHyumxj0oh1 -N6XYk6JdLjD7fxlCvseDcmSePyJrDQInEcDAXY2uMsBylyXoR4FwbYbFSB2y9tcf -uIm7IPXlTP14qE1erVtyK3cCAwEAATANBgkqhkiG9w0BAQQFAAOCAQEAW4yZdqpB -oIdiuXRosr86Sg9FiMg/cn+2OwQ0QIaA8ZBwKsc+wIIHEgXCS8J6316BGQeUvMD+ -plNe0r4GWzzmlDMdobeQ5arPRB89qd9skE6pAMdLg3FyyfEjz3A0VpskolW5VBMr -P5R7uJ1FLgH12RyAjZCWYcCRqEMOffqvyMCH6oAjyDmQOA5IssRKX/HsHntSH/HW -W7slTcP45ty1b44Nq22/ubYk0CJRQgqKOIQ3cLgPomN1jNFQbAbfVTaK1DpEysrQ -5V8a8gNW+3sVZmV6d1Mj3pN2Le62wUKuV2g6BNU7iiwcoY8HI68aRxz2hVMS+t5f -SEGI4JSxV56lYg== ------END CERTIFICATE----- ------BEGIN DH PARAMETERS----- -MEYCQQD+ef8hZ4XbdoyIpJyCTF2UrUEfX6mYDvxuS5O1UNYcslUqlj6JkA11e/yS -6DK8Z86W6mSj5CEk4IjbyEOECXH7AgEC ------END DH PARAMETERS----- diff --git a/examples/publish_subscribe/Makefile b/examples/publish_subscribe/Makefile new file mode 100644 index 00000000..8330d2b9 --- /dev/null +++ b/examples/publish_subscribe/Makefile @@ -0,0 +1,14 @@ +PROG = publish_subscribe +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -DNS_ENABLE_THREADS -pthread $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/publish_subscribe/publish_subscribe.c b/examples/publish_subscribe/publish_subscribe.c new file mode 100644 index 00000000..0ce5b6d5 --- /dev/null +++ b/examples/publish_subscribe/publish_subscribe.c @@ -0,0 +1,112 @@ +// Copyright (c) 2014 Cesanta Software Limited +// All rights reserved +// +// This software is dual-licensed: you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. For the terms of this +// license, see . +// +// You are free to use this software under the terms of the GNU General +// Public License, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// Alternatively, you can license this software under a commercial +// license, as set out in . +// +// $Date: 2014-09-28 05:04:41 UTC $ + +#include "mongoose.h" + +static void *stdin_thread(void *param) { + int ch, sock = * (int *) param; + while ((ch = getchar()) != EOF) { + unsigned char c = (unsigned char) ch; + send(sock, &c, 1, 0); // Forward all types characters to the socketpair + } + return NULL; +} + +static void server_handler(struct mg_connection *nc, int ev, void *p) { + (void) p; + if (ev == NS_RECV) { + // Push received message to all ncections + struct mbuf *io = &nc->recv_mbuf; + struct mg_connection *c; + + for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) { + mg_send(c, io->buf, io->len); + } + mbuf_remove(io, io->len); + } +} + +static void client_handler(struct mg_connection *conn, int ev, void *p) { + struct mbuf *io = &conn->recv_mbuf; + (void) p; + + if (ev == NS_CONNECT) { + if (conn->flags & NSF_CLOSE_IMMEDIATELY) { + printf("%s\n", "Error connecting to server!"); + exit(EXIT_FAILURE); + } + printf("%s\n", "Connected to server. Type a message and press enter."); + } else if (ev == NS_RECV) { + if (conn->flags & NSF_USER_1) { + // Received data from the stdin, forward it to the server + struct mg_connection *c = (struct mg_connection *) conn->user_data; + mg_send(c, io->buf, io->len); + mbuf_remove(io, io->len); + } else { + // Received data from server connection, print it + fwrite(io->buf, io->len, 1, stdout); + mbuf_remove(io, io->len); + } + } else if (ev == NS_CLOSE) { + // Connection has closed, most probably cause server has stopped + exit(EXIT_SUCCESS); + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } else if (strcmp(argv[2], "client") == 0) { + int fds[2]; + struct mg_connection *ioconn, *server_conn; + + mg_mgr_init(&mgr, NULL); + + // Connect to the pubsub server + server_conn = mg_connect(&mgr, argv[1], client_handler); + if (server_conn == NULL) { + fprintf(stderr, "Cannot connect to port %s\n", argv[1]); + exit(EXIT_FAILURE); + } + + // Create a socketpair and give one end to the thread that reads stdin + mg_socketpair(fds, SOCK_STREAM); + mg_start_thread(stdin_thread, &fds[1]); + + // The other end of a pair goes inside the server + ioconn = mg_add_sock(&mgr, fds[0], client_handler); + ioconn->flags |= NSF_USER_1; // Mark this so we know this is a stdin + ioconn->user_data = server_conn; + + } else { + // Server code path + mg_mgr_init(&mgr, NULL); + mg_bind(&mgr, argv[1], server_handler); + printf("Starting pubsub server on port %s\n", argv[1]); + } + + for (;;) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return EXIT_SUCCESS; +} diff --git a/examples/raspberry_pi_mjpeg_led/Makefile b/examples/raspberry_pi_mjpeg_led/Makefile new file mode 100644 index 00000000..cb56be58 --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/Makefile @@ -0,0 +1,18 @@ +NS=../../mongoose.c +FLAGS = ../../mongoose.c -I../.. +CFLAGS=-W -Wall -DNS_ENABLE_THREADS -pthread $(CFLAGS_EXTRA) +PROGS = device_side cloud_side + +all: $(PROGS) + +device_side: Makefile device_side.c $(NS) + $(CC) device_side.c $(FLAGS) -o $@ $(CFLAGS) + +cloud_side: Makefile cloud_side.c $(NS) + $(CC) cloud_side.c $(FLAGS) -o $@ $(CFLAGS) + +device_side.exe: Makefile device_side.c $(NS) + cl device_side.c $(FLAGS) /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROGS) diff --git a/examples/raspberry_pi_mjpeg_led/README.adoc b/examples/raspberry_pi_mjpeg_led/README.adoc new file mode 100644 index 00000000..4aeb32ab --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/README.adoc @@ -0,0 +1,72 @@ += Raspberry Pi camera/LED demo + +== Overview + +The link:/[demo] consists of web app providing access to a webcam and a LED attached to a RaspberryPi. +The device is assumed to have a limited bandwidth towards the server hosting the web app. + +== Objective + +The demo shows how to use websockets to communicate bidirectionally with an embedded device using standard protocols. + +It also shows that it's possible to use Smart.c to develop also the cloud endpoint and expose WebSocket and RESTful APIs +easy to integreate with modern web stacks. + +== How it works + +image::docs/arch.png[] + +There are two components, once with runs on the device (`device_side`) and one that runs on a stronger machine +and with more bandwidth (`cloud_side`). + +The device app connects to the cloud app via websocket and sends a new jpeg frame as fast as the underlying `raspistill` camera +grabbing application can handle. The device automatically attempts reconnecting. + +The cloud side serves the webapp static pages and serves an MPJEG image on `/mpjg`. +The MPJEG image handler blocks all the clients until a JPEG frame arrives via websocket +and then every client will recieve a copy of the frame. + +The web app can turn on and off the LED via a RESTful api accessible via the `/api` handler. + +== Installation + +=== Server side + +---- +git clone https://github.com/cesanta/mongoose +cd mongoose/examples/web_demo +make cloud_side && ./cloud_side 0.0.0.0:8080 +---- + +=== Raspberry Pi + +The instructions provided here are tailored for the Raspbian distribution. + +==== Dependencies + +jpegoptim:: +apt-get install jpegoptim + +camera:: +run raspi-config and enable camera + +==== LED + +In order to access the led on your link:http://www.qdh.org.uk/wordpress/?page_id=15[HotPi] +board you need to export the gpio pins: + +---- +for i in 22 23 24; do + echo $i >/sys/class/gpio/export + echo out >/sys/class/gpio/gpio$i/direction + chgrp pi /sys/class/gpio/gpio$i/value +done +---- + +==== Build and run + +---- +git clone https://github.com/cesanta/mongoose +cd mongoose/examples/web_demo +make device_side && ./device_side yourserver:8080 +---- diff --git a/examples/raspberry_pi_mjpeg_led/cloud_side.c b/examples/raspberry_pi_mjpeg_led/cloud_side.c new file mode 100644 index 00000000..15341305 --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/cloud_side.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * This is the cloud endpoint of the Raspberry Pi camera/LED example + * of the Mongoose networking library. + * It is a simple web server, serving both static files, a REST API handler, + * and a WebSocket handler. + */ +#include "mongoose.h" + +static struct mg_serve_http_opts web_root_opts; + +/* + * Forwards the jpeg frame data to all open mjpeg connections. + * + * Incoming messages follow a very simple binary frame format: + * 4 bytes: timestamp (in network byte order) + * n bytes: jpeg payload + * + * The timestamp is used to compute a lag. + * It's done in a quite stupid way as it requires the device clock + * to be synchronized with the cloud endpoint. + */ +static void push_frame_to_clients(struct mg_mgr *mgr, + const struct websocket_message *wm) { + struct mg_connection *nc; + /* + * mjpeg connections are tagged with the NSF_USER_2 flag so we can find them + * my scanning the connection list provided by the mongoose manager. + */ + for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { + if (!(nc->flags & NSF_USER_2)) continue; // Ignore un-marked requests + + mg_printf(nc, "--w00t\r\nContent-Type: image/jpeg\r\n" + "Content-Length: %lu\r\n\r\n", (unsigned long) wm->size); + mg_send(nc, wm->data, wm->size); + mg_send(nc, "\r\n", 2); + printf("Image pushed to %p\n", nc); + } +} + +/* + * Forwards API payload to the device, by scanning through + * all the connections to find those that are tagged as WebSocket. + */ +static void send_command_to_the_device(struct mg_mgr *mgr, + const struct mg_str *cmd) { + struct mg_connection *nc; + for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { + if (!(nc->flags & NSF_IS_WEBSOCKET)) continue; // Ignore non-websocket requests + + mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, cmd->p, cmd->len); + printf("Sent API command [%.*s] to %p\n", (int) cmd->len, cmd->p, nc); + } +} + +/* + * Main event handler. Receives data events and dispatches to + * the appropriate handler function. + * + * 1. RESTful API requests are handled by send_command_to_the_device. + * 2. requests to /mpeg are established and left open waiting for data to arrive + * from WebSocket. + * 3. WebSocket frames are handled by push_frame_to_clients. + * 4. All other connections are passed to the mg_serve_http handler + * which serves static files. + */ +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct websocket_message *wm = (struct websocket_message *) ev_data; + struct http_message *hm = (struct http_message *) ev_data; + + switch (ev) { + case NS_HTTP_REQUEST: + if (mg_vcmp(&hm->uri, "/mjpg") == 0) { + nc->flags |= NSF_USER_2; /* Set a mark on image requests */ + mg_printf(nc, "%s", + "HTTP/1.0 200 OK\r\n" + "Cache-Control: no-cache\r\n" + "Pragma: no-cache\r\n" + "Expires: Thu, 01 Dec 1994 16:00:00 GMT\r\n" + "Connection: close\r\n" + "Content-Type: multipart/x-mixed-replace; " + "boundary=--w00t\r\n\r\n"); + } else if (mg_vcmp(&hm->uri, "/api") == 0 && hm->body.len > 0) { + /* + * RESTful API call. HTTP message body should be a JSON message. + * We should parse it and take appropriate action. + * In our case, simply forward that call to the device. + */ + printf("API CALL: [%.*s] [%.*s]\n", (int) hm->method.len, hm->method.p, + (int) hm->body.len, hm->body.p); + send_command_to_the_device(nc->mgr, &hm->body); + mg_printf(nc, "HTTP/1.0 200 OK\nContent-Length: 0\n\n"); + } else { + /* Delegate to the static web server handler for all other paths. */ + mg_serve_http(nc, hm, web_root_opts); + } + break; + case NS_WEBSOCKET_FRAME: + printf("Got websocket frame, size %lu\n", (unsigned long) wm->size); + push_frame_to_clients(nc->mgr, wm); + break; + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + printf("Listening on: [%s]\n", argv[1]); + mg_mgr_init(&mgr, NULL); + + /* + * mg_bind() creates a listening connection on a given ip:port and + * with an attached event handler. + * The event handler will only trigger TCP events until the http + * protocol handler is installed. + */ + if ((nc = mg_bind(&mgr, argv[1], ev_handler)) == NULL) { + fprintf(stderr, "Error binding to %s\n", argv[1]); + exit(EXIT_FAILURE); + } + mg_set_protocol_http_websocket(nc); + web_root_opts.document_root = "./web_root"; + + /* + * We explicitly hand over control to the Mongoose manager + * in this event loop and we can easily multiplex other activities. + */ + for(;;) { + mg_mgr_poll(&mgr, 1000); + } + + return EXIT_SUCCESS; +} diff --git a/examples/raspberry_pi_mjpeg_led/device_side.c b/examples/raspberry_pi_mjpeg_led/device_side.c new file mode 100644 index 00000000..90989f9c --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/device_side.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +/* + * This is the device endpoint of the Raspberry Pi camera/LED example + * of the Mongoose networking library. + * It is a simple websocket client, sending jpeg frames obtained from the + * RPi camera and receiving JSON commands through the same WebSocket channel + */ + +#include +#include "mongoose.h" + +static int s_poll_interval_ms = 100; +static int s_still_period = 100; +static int s_vertical_flip = 0; +static int s_width = 320; +static int s_height = 180; +static const char *s_mjpg_file = "/var/run/shm/cam.jpg"; + +static struct mg_connection *client; + +/* + * Check if there is a new image available and + * send it to the cloud endpoint if the send buffer is not too full. + * The image is moved in a new file by the jpeg optimizer function; + * this ensures that we will detect a new frame when raspistill writes + * it's output file. + */ +static void send_mjpg_frame(struct mg_connection *nc, const char *file_path) { + static int skipped_frames = 0; + struct stat st; + FILE *fp; + + /* Check file modification time. */ + if (stat(file_path, &st) == 0) { + /* Skip the frame if there is too much unsent data. */ + if (nc->send_mbuf.len > 256) skipped_frames++; + + /* Read new mjpg frame into a buffer */ + fp = fopen(file_path, "rb"); + char buf[st.st_size]; + fread(buf, 1, sizeof(buf), fp); + fclose(fp); + + /* + * Delete the file so we can detect when raspistill creates a new one. + * mtime granularity is only 1s. + */ + unlink(file_path); + + /* Send those buffer through the websocket connection */ + mg_send_websocket_frame(nc, WEBSOCKET_OP_BINARY, buf, sizeof(buf)); + printf("Sent mjpg frame, %lu bytes after skippping %d frames\n", (unsigned long) sizeof(buf), skipped_frames); + skipped_frames = 0; + } +} + +/* + * Turn on or off the LED. + * The LED in this example is an RGB led, so all the colors have to be set. + */ +static void set_led(int v) { + char cmd[512]; + snprintf(cmd, sizeof(cmd), "for i in 22 23 24; do" + " echo %d >/sys/class/gpio/gpio$i/value; done", v); + system(cmd); +} + +/* + * Parse control JSON and perform command: + * for now only LED on/off is supported. + */ +static void perform_control_command(const char* data, size_t len) { + struct json_token toks[200], *onoff; + parse_json(data, len, toks, sizeof(toks)); + onoff = find_json_token(toks, "onoff"); + set_led(strncmp("[\"on\"]", onoff->ptr, onoff->len) == 0); +} + +/* Main event handler. Sends websocket frames and receives control commands */ +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct websocket_message *wm = (struct websocket_message *) ev_data; + + switch (ev) { + case NS_CONNECT: + printf("Reconnect: %s\n", * (int *) ev_data == 0 ? "ok" : "failed"); + if (* (int *) ev_data == 0) { + /* + * Tune the tcp send buffer size, so that we can skip frames + * when the connection is congested. This helps maintaining a + * reasonable latency. + */ + int sndbuf_size = 512; + if(setsockopt(nc->sock, SOL_SOCKET, SO_SNDBUF, + (void *) &sndbuf_size, sizeof(int)) == -1) { + perror("failed to tune TCP send buffer size\n"); + } + + mg_send_websocket_handshake(nc, "/stream", NULL); + } + break; + case NS_CLOSE: + printf("Connection %p closed\n", nc); + client = NULL; + break; + case NS_POLL: + send_mjpg_frame(nc, s_mjpg_file); + break; + case NS_WEBSOCKET_FRAME: + printf("Got control command: [%.*s]\n", (int) wm->size, wm->data); + perform_control_command((const char*)wm->data, wm->size); + break; + } +} + +/* + * This thread regenerates s_mjpg_file every s_poll_interval_ms milliseconds. + * It is Raspberry PI specific, change this function on other systems. + */ +static void *generate_mjpg_data_thread_func(void *param) { + char cmd[400]; + (void) param; + + snprintf(cmd, sizeof(cmd), "raspistill -w %d -h %d -n -q 100 -tl %d " + "-t 999999999 -v %s -o %s >/dev/null 2>&1", s_width, s_height, + s_still_period, s_vertical_flip ? "-vf" : "", s_mjpg_file); + + for(;;) { + int ret = system(cmd); + if (WIFSIGNALED(ret)) exit(1); + sleep(1); + } + return NULL; +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + char *addr = argv[1]; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + /* Start separate thread that generates MJPG data */ + mg_start_thread(generate_mjpg_data_thread_func, NULL); + + printf("Streaming [%s] to [%s]\n", s_mjpg_file, addr); + + mg_mgr_init(&mgr, NULL); + + for(;;) { + mg_mgr_poll(&mgr, s_poll_interval_ms); + + /* Reconnect if disconnected */ + if (!client) { + sleep(1); /* limit reconnections frequency */ + printf("Reconnecting to %s...\n", addr); + client = mg_connect(&mgr, addr, ev_handler); + if (client) mg_set_protocol_http_websocket(client); + } + } + + return EXIT_SUCCESS; +} diff --git a/examples/raspberry_pi_mjpeg_led/docs/arch.png b/examples/raspberry_pi_mjpeg_led/docs/arch.png new file mode 100644 index 0000000000000000000000000000000000000000..938f71a86a3746b015823a9facb6d83ae6e9ff5e GIT binary patch literal 40959 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 Y+UGwDbXc1y69q`rR5X+;|1b;w7hjc(3jhEB literal 0 HcmV?d00001 diff --git a/examples/raspberry_pi_mjpeg_led/web_root/doc.html b/examples/raspberry_pi_mjpeg_led/web_root/doc.html new file mode 100644 index 00000000..00915466 --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/web_root/doc.html @@ -0,0 +1,533 @@ + + + + + + + +Raspberry Pi camera/LED demo + + + + + +
+
+

Overview

+
+
+

The demo consists of web app providing access to a webcam and a LED attached to a RaspberryPi. +The device is assumed to have a limited bandwidth towards the server hosting the web app.

+
+
+
+
+

Objective

+
+
+

The demo shows how to use websockets to communicate bidirectionally with an embedded device using standard protocols.

+
+
+

It also shows that it’s possible to use Smart.c to develop also the cloud endpoint and expose WebSocket and RESTful APIs +easy to integreate with modern web stacks.

+
+
+
+
+

How it works

+
+
+
+arch +
+
+
+

There are two components, once with runs on the device (device_side) and one that runs on a stronger machine +and with more bandwidth (cloud_side).

+
+
+

The device app connects to the cloud app via websocket and sends a new jpeg frame as fast as the underlying raspistill camera +grabbing application can handle. The device automatically attempts reconnecting.

+
+
+

The cloud side serves the webapp static pages and serves an MPJEG image on /mpjg. +The MPJEG image handler blocks all the clients until a JPEG frame arrives via websocket +and then every client will recieve a copy of the frame.

+
+
+

The web app can turn on and off the LED via a RESTful api accessible via the /api handler.

+
+
+
+
+

Installation

+
+
+

Server side

+
+
+
git clone https://github.com/cesanta/mongoose
+cd mongoose/examples/web_demo
+make cloud_side && ./cloud_side 0.0.0.0:8080
+
+
+
+
+

Raspberry Pi

+
+

The instructions provided here are tailored for the Raspbian distribution.

+
+
+

Dependencies

+
+
+
jpegoptim
+
+

apt-get install jpegoptim

+
+
camera
+
+

run raspi-config and enable camera

+
+
+
+
+
+

LED

+
+

In order to access the led on your HotPi +board you need to export the gpio pins:

+
+
+
+
for i in 22 23 24; do
+  echo $i >/sys/class/gpio/export
+  echo out >/sys/class/gpio/gpio$i/direction
+  chgrp pi /sys/class/gpio/gpio$i/value
+done
+
+
+
+
+

Build and run

+
+
+
git clone https://github.com/cesanta/mongoose
+cd mongoose/examples/web_demo
+make device_side && ./device_side yourserver:8080
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/examples/raspberry_pi_mjpeg_led/web_root/docs/arch.png b/examples/raspberry_pi_mjpeg_led/web_root/docs/arch.png new file mode 120000 index 00000000..47db27dc --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/web_root/docs/arch.png @@ -0,0 +1 @@ +../../docs/arch.png \ No newline at end of file diff --git a/examples/raspberry_pi_mjpeg_led/web_root/framework7.min.css b/examples/raspberry_pi_mjpeg_led/web_root/framework7.min.css new file mode 100755 index 00000000..ec9c9934 --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/web_root/framework7.min.css @@ -0,0 +1,15 @@ +/* + * Framework7 0.9.6 + * Full Featured HTML Framework For Building iOS 7 Apps + * + * http://www.idangero.us/framework7 + * + * Copyright 2014, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: September 13, 2014 +*/ +html,body{position:relative;height:100%;width:100%;overflow-x:hidden}body{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;margin:0;padding:0;color:#000;font-size:14px;line-height:1.4;width:100%;-webkit-text-size-adjust:100%;background:#fff;overflow:hidden}@media all and (width:1024px) and (height:691px) and (orientation:landscape){html,body{height:671px}}@media all and (width:1024px) and (height:692px) and (orientation:landscape){html,body{height:672px}}*{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none}a,input,textarea,select{outline:0}a{text-decoration:none;color:#007aff}p{margin:1em 0}.row{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-lines:multiple;-moz-box-lines:multiple;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.row>[class*=col-]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row .col-100{width:100%;width:-webkit-calc((100% - 15px*0) / 1);width:calc((100% - 15px*0) / 1)}.row.no-gutter .col-100{width:100%}.row .col-95{width:95%;width:-webkit-calc((100% - 15px*0.05263157894736836) / 1.0526315789473684);width:calc((100% - 15px*0.05263157894736836) / 1.0526315789473684)}.row.no-gutter .col-95{width:95%}.row .col-90{width:90%;width:-webkit-calc((100% - 15px*0.11111111111111116) / 1.1111111111111112);width:calc((100% - 15px*0.11111111111111116) / 1.1111111111111112)}.row.no-gutter .col-90{width:90%}.row .col-85{width:85%;width:-webkit-calc((100% - 15px*0.17647058823529416) / 1.1764705882352942);width:calc((100% - 15px*0.17647058823529416) / 1.1764705882352942)}.row.no-gutter .col-85{width:85%}.row .col-80{width:80%;width:-webkit-calc((100% - 15px*0.25) / 1.25);width:calc((100% - 15px*0.25) / 1.25)}.row.no-gutter .col-80{width:80%}.row .col-75{width:75%;width:-webkit-calc((100% - 15px*0.33333333333333326) / 1.3333333333333333);width:calc((100% - 15px*0.33333333333333326) / 1.3333333333333333)}.row.no-gutter .col-75{width:75%}.row .col-66{width:66.66666666666666%;width:-webkit-calc((100% - 15px*0.5000000000000002) / 1.5000000000000002);width:calc((100% - 15px*0.5000000000000002) / 1.5000000000000002)}.row.no-gutter .col-66{width:66.66666666666666%}.row .col-60{width:60%;width:-webkit-calc((100% - 15px*0.6666666666666667) / 1.6666666666666667);width:calc((100% - 15px*0.6666666666666667) / 1.6666666666666667)}.row.no-gutter .col-60{width:60%}.row .col-50{width:50%;width:-webkit-calc((100% - 15px*1) / 2);width:calc((100% - 15px*1) / 2)}.row.no-gutter .col-50{width:50%}.row .col-40{width:40%;width:-webkit-calc((100% - 15px*1.5) / 2.5);width:calc((100% - 15px*1.5) / 2.5)}.row.no-gutter .col-40{width:40%}.row .col-33{width:33.333333333333336%;width:-webkit-calc((100% - 15px*2) / 3);width:calc((100% - 15px*2) / 3)}.row.no-gutter .col-33{width:33.333333333333336%}.row .col-25{width:25%;width:-webkit-calc((100% - 15px*3) / 4);width:calc((100% - 15px*3) / 4)}.row.no-gutter .col-25{width:25%}.row .col-20{width:20%;width:-webkit-calc((100% - 15px*4) / 5);width:calc((100% - 15px*4) / 5)}.row.no-gutter .col-20{width:20%}.row .col-15{width:15%;width:-webkit-calc((100% - 15px*5.666666666666667) / 6.666666666666667);width:calc((100% - 15px*5.666666666666667) / 6.666666666666667)}.row.no-gutter .col-15{width:15%}.row .col-10{width:10%;width:-webkit-calc((100% - 15px*9) / 10);width:calc((100% - 15px*9) / 10)}.row.no-gutter .col-10{width:10%}.row .col-5{width:5%;width:-webkit-calc((100% - 15px*19) / 20);width:calc((100% - 15px*19) / 20)}.row.no-gutter .col-5{width:5%}@media all and (min-width:768px){.row .tablet-100{width:100%;width:-webkit-calc((100% - 15px*0) / 1);width:calc((100% - 15px*0) / 1)}.row.no-gutter .tablet-100{width:100%}.row .tablet-95{width:95%;width:-webkit-calc((100% - 15px*0.05263157894736836) / 1.0526315789473684);width:calc((100% - 15px*0.05263157894736836) / 1.0526315789473684)}.row.no-gutter .tablet-95{width:95%}.row .tablet-90{width:90%;width:-webkit-calc((100% - 15px*0.11111111111111116) / 1.1111111111111112);width:calc((100% - 15px*0.11111111111111116) / 1.1111111111111112)}.row.no-gutter .tablet-90{width:90%}.row .tablet-85{width:85%;width:-webkit-calc((100% - 15px*0.17647058823529416) / 1.1764705882352942);width:calc((100% - 15px*0.17647058823529416) / 1.1764705882352942)}.row.no-gutter .tablet-85{width:85%}.row .tablet-80{width:80%;width:-webkit-calc((100% - 15px*0.25) / 1.25);width:calc((100% - 15px*0.25) / 1.25)}.row.no-gutter .tablet-80{width:80%}.row .tablet-75{width:75%;width:-webkit-calc((100% - 15px*0.33333333333333326) / 1.3333333333333333);width:calc((100% - 15px*0.33333333333333326) / 1.3333333333333333)}.row.no-gutter .tablet-75{width:75%}.row .tablet-66{width:66.66666666666666%;width:-webkit-calc((100% - 15px*0.5000000000000002) / 1.5000000000000002);width:calc((100% - 15px*0.5000000000000002) / 1.5000000000000002)}.row.no-gutter .tablet-66{width:66.66666666666666%}.row .tablet-60{width:60%;width:-webkit-calc((100% - 15px*0.6666666666666667) / 1.6666666666666667);width:calc((100% - 15px*0.6666666666666667) / 1.6666666666666667)}.row.no-gutter .tablet-60{width:60%}.row .tablet-50{width:50%;width:-webkit-calc((100% - 15px*1) / 2);width:calc((100% - 15px*1) / 2)}.row.no-gutter .tablet-50{width:50%}.row .tablet-40{width:40%;width:-webkit-calc((100% - 15px*1.5) / 2.5);width:calc((100% - 15px*1.5) / 2.5)}.row.no-gutter .tablet-40{width:40%}.row .tablet-33{width:33.333333333333336%;width:-webkit-calc((100% - 15px*2) / 3);width:calc((100% - 15px*2) / 3)}.row.no-gutter .tablet-33{width:33.333333333333336%}.row .tablet-25{width:25%;width:-webkit-calc((100% - 15px*3) / 4);width:calc((100% - 15px*3) / 4)}.row.no-gutter .tablet-25{width:25%}.row .tablet-20{width:20%;width:-webkit-calc((100% - 15px*4) / 5);width:calc((100% - 15px*4) / 5)}.row.no-gutter .tablet-20{width:20%}.row .tablet-15{width:15%;width:-webkit-calc((100% - 15px*5.666666666666667) / 6.666666666666667);width:calc((100% - 15px*5.666666666666667) / 6.666666666666667)}.row.no-gutter .tablet-15{width:15%}.row .tablet-10{width:10%;width:-webkit-calc((100% - 15px*9) / 10);width:calc((100% - 15px*9) / 10)}.row.no-gutter .tablet-10{width:10%}.row .tablet-5{width:5%;width:-webkit-calc((100% - 15px*19) / 20);width:calc((100% - 15px*19) / 20)}.row.no-gutter .tablet-5{width:5%}}.views,.view{position:relative;width:100%;height:100%;z-index:5000}.views{overflow:auto;-webkit-overflow-scrolling:touch}.view{overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pages{position:relative;width:100%;height:100%;overflow:hidden;background:#000}.page{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;background:#efeff4;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1;-webkit-box-shadow:none;box-shadow:none}.page.cached{display:none}.page-on-left{opacity:.9;-webkit-box-shadow:0 0 12px rgba(0,0,0,.5);box-shadow:0 0 12px rgba(0,0,0,.5);-webkit-transform:translate3d(-20%,0,0);-ms-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0)}.page-on-center{opacity:1;-webkit-box-shadow:0 0 12px rgba(0,0,0,.5);box-shadow:0 0 12px rgba(0,0,0,.5);-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.page-on-right{-webkit-box-shadow:none;box-shadow:none;opacity:1;-webkit-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.page-content{overflow:auto;-webkit-overflow-scrolling:touch;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:100%}.page-transitioning{-webkit-transition-duration:400ms;transition-duration:400ms}.page-from-right-to-center{-webkit-animation:pageFromRightToCenter 400ms forwards;animation:pageFromRightToCenter 400ms forwards}.page-from-center-to-right{-webkit-animation:pageFromCenterToRight 400ms forwards;animation:pageFromCenterToRight 400ms forwards}@-webkit-keyframes pageFromRightToCenter{from{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:translate3d(100%,0,0)}to{-webkit-box-shadow:0 0 12px rgba(0,0,0,.5);box-shadow:0 0 12px rgba(0,0,0,.5);-webkit-transform:translate3d(0,0,0)}}@-webkit-keyframes pageFromCenterToRight{from{-webkit-box-shadow:0 0 12px rgba(0,0,0,.5);box-shadow:0 0 12px rgba(0,0,0,.5);-webkit-transform:translate3d(0,0,0)}to{-webkit-box-shadow:none;box-shadow:none;-webkit-transform:translate3d(100%,0,0)}}@keyframes pageFromRightToCenter{from{-webkit-box-shadow:none;box-shadow:none;transform:translate3d(100%,0,0)}to{-webkit-box-shadow:0 0 12px rgba(0,0,0,.5);box-shadow:0 0 12px rgba(0,0,0,.5);transform:translate3d(0,0,0)}}@keyframes pageFromCenterToRight{from{-webkit-box-shadow:0 0 12px rgba(0,0,0,.5);box-shadow:0 0 12px rgba(0,0,0,.5);transform:translate3d(0,0,0)}to{-webkit-box-shadow:none;box-shadow:none;transform:translate3d(100%,0,0)}}.page-from-center-to-left{-webkit-animation:pageFromCenterToLeft 400ms forwards;animation:pageFromCenterToLeft 400ms forwards}.page-from-left-to-center{-webkit-animation:pageFromLeftToCenter 400ms forwards;animation:pageFromLeftToCenter 400ms forwards}@-webkit-keyframes pageFromCenterToLeft{from{opacity:1;-webkit-transform:translate3d(0,0,0)}to{opacity:.9;-webkit-transform:translate3d(-20%,0,0)}}@-webkit-keyframes pageFromLeftToCenter{from{opacity:.9;-webkit-transform:translate3d(-20%,0,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0)}}@keyframes pageFromCenterToLeft{from{opacity:1;transform:translate3d(0,0,0)}to{opacity:.9;transform:translate3d(-20%,0,0)}}@keyframes pageFromLeftToCenter{from{opacity:.9;transform:translate3d(-20%,0,0)}to{opacity:1;transform:translate3d(0,0,0)}}html.android .page{box-shadow:none!important}html.android .page-from-right-to-center{-webkit-animation:pageFromRightToCenterDegrade 400ms forwards;animation:pageFromRightToCenterDegrade 400ms forwards}html.android .page-from-center-to-right{-webkit-animation:pageFromCenterToRightDegrade 400ms forwards;animation:pageFromCenterToRightDegrade 400ms forwards}@-webkit-keyframes pageFromRightToCenterDegrade{from{-webkit-transform:translate3d(100%,0,0)}to{-webkit-transform:translate3d(0,0,0)}}@-webkit-keyframes pageFromCenterToRightDegrade{from{-webkit-transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(100%,0,0)}}@keyframes pageFromRightToCenterDegrade{from{transform:translate3d(100%,0,0)}to{transform:translate3d(0,0,0)}}@keyframes pageFromCenterToRightDegrade{from{transform:translate3d(0,0,0)}to{transform:translate3d(100%,0,0)}}.navbar-inner,.toolbar-inner{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 8px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.navbar,.toolbar{height:44px;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;font-size:17px;position:relative;margin:0;z-index:500;-webkit-backface-visibility:hidden;backface-visibility:hidden}.navbar b,.toolbar b{font-weight:500}.navbar a.link,.toolbar a.link{line-height:44px;height:44px;text-decoration:none;position:relative;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;-webkit-transition-duration:300ms;transition-duration:300ms}html:not(.watch-active-state) .navbar a.link:active,html:not(.watch-active-state) .toolbar a.link:active,.navbar a.link.active-state,.toolbar a.link.active-state{opacity:.3;-webkit-transition-duration:0ms;transition-duration:0ms}.navbar a.link i+span,.toolbar a.link i+span,.navbar a.link i+i,.toolbar a.link i+i,.navbar a.link span+i,.toolbar a.link span+i,.navbar a.link span+span,.toolbar a.link span+span{margin-left:7px}.navbar a.icon-only,.toolbar a.icon-only{min-width:44px;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;margin:0}.navbar i.icon,.toolbar i.icon{display:block}.navbar{left:0;top:0;background:#f7f7f8;border-bottom:1px solid #c4c4c4}html.retina.ios-gt-7 .navbar{border-bottom-width:.5px}.navbar .center{font-size:17px;font-weight:500;text-align:center;margin:0;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:44px;-webkit-flex-shrink:10;-ms-flex:0 10 auto;flex-shrink:10;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.navbar .left,.navbar .right{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.navbar .left a+a,.navbar .right a+a{margin-left:15px}.navbar .left{margin-right:10px}.navbar .right{margin-left:10px}.navbar .right:first-child{position:absolute;right:8px;height:100%}.toolbar{left:0;bottom:0;background:#f7f7f8;border-top:1px solid #c4c4c4}html.retina.ios-gt-7 .toolbar{border-top-width:.5px}.toolbar a{-webkit-flex-shrink:1;-ms-flex:0 1 auto;flex-shrink:1;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.tabbar{color:#929292;z-index:5001}.tabbar a{color:#929292}.tabbar a.active{color:#007aff}.tabbar a.tab-link,.tabbar a.link{height:100%;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;overflow:visible;-webkit-box-flex:1;-ms-flex:1;-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.tabbar i.icon{height:30px}.tabbar-labels{height:50px}.tabbar-labels a.tab-link,.tabbar-labels a.link{padding-top:4px;padding-bottom:4px;height:100%;-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.tabbar-labels span.tabbar-label{line-height:1;display:block;letter-spacing:.01em;font-size:10px;position:relative;text-overflow:ellipsis;white-space:nowrap}@media all and (min-width:768px){.tabbar .toolbar-inner{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.tabbar a.tab-link,.tabbar a.link{width:auto;min-width:105px}.tabbar-labels{height:56px}.tabbar-labels span.tabbar-label{font-size:14px}}.navbar-from-right-to-center .left,.navbar-from-right-to-center .right,.navbar-from-right-to-center .center{-webkit-animation:navbarElementFadeIn 400ms forwards;animation:navbarElementFadeIn 400ms forwards}.navbar-from-right-to-center .sliding{opacity:1}.navbar-from-center-to-right .left,.navbar-from-center-to-right .right,.navbar-from-center-to-right .center{-webkit-animation:navbarElementFadeOut 400ms forwards;animation:navbarElementFadeOut 400ms forwards}.navbar-from-center-to-right .sliding{opacity:0}@-webkit-keyframes navbarElementFadeIn{from{opacity:0}to{opacity:1}}@keyframes navbarElementFadeIn{from{opacity:0}to{opacity:1}}.navbar-from-center-to-left .left,.navbar-from-center-to-left .right,.navbar-from-center-to-left .center{-webkit-animation:navbarElementFadeOut 400ms forwards;animation:navbarElementFadeOut 400ms forwards}.navbar-from-center-to-left .sliding{opacity:0}.navbar-from-left-to-center .left,.navbar-from-left-to-center .right,.navbar-from-left-to-center .center{-webkit-animation:navbarElementFadeIn 400ms forwards;animation:navbarElementFadeIn 400ms forwards}.navbar-from-left-to-center .sliding{opacity:1}.navbar-on-left .left,.navbar-on-left .right,.navbar-on-left .center{opacity:0}.navbar-on-left .sliding{opacity:0}.navbar-on-right .left,.navbar-on-right .right,.navbar-on-right .center{opacity:0}.navbar-on-right .sliding{opacity:0}@-webkit-keyframes navbarElementFadeOut{from{opacity:1}to{opacity:0}}@keyframes navbarElementFadeOut{from{opacity:1}to{opacity:0}}.navbar-from-right-to-center .left.sliding .back.link .icon,.navbar-from-center-to-right .left.sliding .back.link .icon,.navbar-from-center-to-left .left.sliding .back.link .icon,.navbar-from-left-to-center .left.sliding .back.link .icon{-webkit-transition-duration:400ms;transition-duration:400ms}.navbar-from-right-to-center .sliding,.navbar-from-center-to-right .sliding,.navbar-from-center-to-left .sliding,.navbar-from-left-to-center .sliding{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-animation:none;animation:none}.page>.navbar,.view>.navbar,.views>.navbar,.page>.toolbar,.view>.toolbar,.views>.toolbar{position:absolute}.navbar-through .page-content,.navbar-fixed .page-content{padding-top:44px}.toolbar-through .page-content,.toolbar-fixed .page-content,.tabbar-through .page-content,.tabbar-fixed .page-content{padding-bottom:44px}.tabbar-labels-fixed .page-content,.tabbar-labels-through .page-content{padding-bottom:50px}@media all and (min-width:768px){.tabbar-labels-fixed .page-content,.tabbar-labels-through .page-content{padding-bottom:56px}}.hidden-navbar .navbar{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(0,-100%,0);-ms-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}.hiding-navbar .navbar{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.page.no-navbar .page-content{padding-top:0}.hidden-toolbar .toolbar{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.hiding-toolbar .toolbar{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.page.no-toolbar .page-content{padding-bottom:0}.searchbar{height:44px;background:#c9c9ce;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #b4b4b4;padding:0 8px;overflow:hidden;position:relative;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}html.retina.ios-gt-7 .searchbar{border-bottom-width:.5px}.searchbar .searchbar-input{width:100%;height:28px;position:relative;-webkit-flex-shrink:1;-ms-flex:0 1 auto;flex-shrink:1}.searchbar input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;height:100%;display:block;border:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border-radius:5px;font-family:inherit;color:#000;font-size:14px;font-weight:400;padding:0 28px;background:#fff url("data:image/svg+xml;charset=utf-8,") no-repeat 8px center;-webkit-background-size:13px 13px;background-size:13px 13px}.searchbar input[type=search]::-webkit-input-placeholder{color:#939398;opacity:1}.searchbar input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}.searchbar .searchbar-clear{position:absolute;width:28px;height:28px;right:0;top:0;opacity:0;pointer-events:none;background:url("data:image/svg+xml;charset=utf-8,") no-repeat center;-webkit-background-size:14px 14px;background-size:14px 14px;-webkit-transition-duration:300ms;transition-duration:300ms;cursor:pointer}.searchbar .searchbar-cancel{-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);font-size:17px;cursor:pointer;opacity:0;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;margin-left:0;pointer-events:none}.searchbar.searchbar-active .searchbar-cancel{margin-left:8px;opacity:1;pointer-events:auto}html:not(.watch-active-state) .searchbar.searchbar-active .searchbar-cancel:active,.searchbar.searchbar-active .searchbar-cancel.active-state{opacity:.3;-webkit-transition-duration:0ms;transition-duration:0ms}.searchbar.searchbar-not-empty .searchbar-clear{pointer-events:auto;opacity:1}.searchbar-overlay{position:absolute;left:0;top:0;width:100%;height:100%;z-index:100;opacity:0;pointer-events:none;background:rgba(0,0,0,.4);-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.searchbar-overlay.searchbar-overlay-active{opacity:1;pointer-events:auto}.searchbar-not-found{display:none}.hidden-by-searchbar,.list-block .hidden-by-searchbar,.list-block li.hidden-by-searchbar{display:none}.page>.searchbar{position:absolute;width:100%;left:0;top:0;z-index:200}.page>.searchbar~.page-content{padding-top:44px}.navbar-fixed .page>.searchbar,.navbar-through .page>.searchbar,.navbar-fixed>.searchbar,.navbar-through>.searchbar{top:44px}.navbar-fixed .page>.searchbar~.page-content,.navbar-through .page>.searchbar~.page-content,.navbar-fixed>.searchbar~.page-content,.navbar-through>.searchbar~.page-content{padding-top:88px}.messagebar{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0ms;transition-duration:0ms}.messagebar textarea{-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #c8c8cd;background:#fff;border-radius:5px;box-shadow:none;display:block;padding:3px 8px;margin:0;width:100%;height:28px;color:#000;font-size:17px;line-height:20px;font-family:inherit;resize:none;-webkit-flex-shrink:1;-ms-flex:0 1 auto;flex-shrink:1}.messagebar .link{-ms-flex-item-align:flex-end;-webkit-align-self:flex-end;align-self:flex-end}.messagebar .link.icon-only:first-child{margin-left:-6px}.messagebar .link:not(.icon-only)+textarea{margin-left:8px}.messagebar textarea+.link{margin-left:8px}.messagebar .link{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0}.messagebar~.page-content{padding-bottom:44px}.page.no-toolbar .messagebar~.page-content{padding-bottom:44px}.hidden-toolbar .messagebar{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0ms;transition-duration:0ms}i.icon{display:inline-block;vertical-align:middle;background-size:100% auto;background-position:center;background-repeat:no-repeat;font-style:normal;position:relative}i.icon.icon-back{width:12px;height:20px;background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon.icon-bars{width:21px;height:13px;background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon.icon-camera{width:25px;height:20px;background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon.icon-f7{width:29px;height:29px;background-image:url(../img/i-f7.png)}i.icon.icon-form-name{width:29px;height:29px;background-image:url(../img/i-form-name.png)}i.icon.icon-form-password{width:29px;height:29px;background-image:url(../img/i-form-password.png)}i.icon.icon-form-email{width:29px;height:29px;background-image:url(../img/i-form-email.png)}i.icon.icon-form-calendar{width:29px;height:29px;background-image:url(../img/i-form-calendar.png)}i.icon.icon-form-tel{width:29px;height:29px;background-image:url(../img/i-form-tel.png)}i.icon.icon-form-gender{width:29px;height:29px;background-image:url(../img/i-form-gender.png)}i.icon.icon-form-toggle{width:29px;height:29px;background-image:url(../img/i-form-toggle.png)}i.icon.icon-form-comment{width:29px;height:29px;background-image:url(../img/i-form-comment.png)}i.icon.icon-form-settings{width:29px;height:29px;background-image:url(../img/i-form-settings.png)}i.icon.icon-form-url{width:29px;height:29px;background-image:url(../img/i-form-url.png)}i.icon.icon-next,i.icon.icon-prev{width:15px;height:15px}i.icon.icon-next{background:url("data:image/svg+xml;charset=utf-8,")}i.icon.icon-prev{background:url("data:image/svg+xml;charset=utf-8,")}i.icon.icon-plus{width:25px;height:25px;font-size:31px;line-height:20px;text-align:center;font-weight:100}.badge{font-size:13px;display:inline-block;color:#fff;background:#8e8e93;border-radius:20px;padding:1px 7px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.icon .badge{position:absolute;left:100%;margin-left:-10px;top:-2px;font-size:10px;padding:1px 5px}.content-block{margin:35px 0;padding:0 15px;color:#6d6d72}.content-block-title{position:relative;overflow:hidden;margin:0;white-space:nowrap;text-overflow:ellipsis;font-size:14px;text-transform:uppercase;line-height:1;color:#6d6d72;margin:35px 15px 10px}.content-block-title+.list-block,.content-block-title+.content-block{margin-top:10px}.content-block-inner{background:#fff;padding:10px 15px;margin-left:-15px;width:100%;border-bottom:1px solid #c8c7cc;border-top:1px solid #c8c7cc;color:#000}html.retina.ios-gt-7 .content-block-inner{border-top-width:.5px;border-bottom-width:.5px}.content-block.inset{margin-left:15px;margin-right:15px;border-radius:7px}.content-block.inset .content-block-inner{border:none;border-radius:7px}@media all and (min-width:768px){.content-block.tablet-inset{margin-left:15px;margin-right:15px;border-radius:7px}.content-block.tablet-inset .content-block-inner{border:none;border-radius:7px}}.list-block{margin:35px 0;font-size:17px}.list-block ul{background:#fff;list-style:none;padding:0;margin:0;border-top:1px solid #c8c7cc;border-bottom:1px solid #c8c7cc;position:relative}.list-block ul ul{border-top:none;border-bottom:none;padding-left:45px}.list-block .align-top,.list-block .align-top .item-content,.list-block .align-top .item-inner{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.list-block.inset{margin-left:15px;margin-right:15px;border-radius:7px}.list-block.inset .content-block-title{margin-left:0;margin-right:0}.list-block.inset ul{border-radius:7px;border-top:none;border-bottom:none}.list-block.inset li:first-child>a{border-radius:7px 7px 0 0}.list-block.inset li:last-child>a{border-radius:0 0 7px 7px}.list-block.inset li:first-child:last-child>a{border-radius:7px}@media all and (min-width:768px){.list-block.tablet-inset{margin-left:15px;margin-right:15px;border-radius:7px}.list-block.tablet-inset .content-block-title{margin-left:0;margin-right:0}.list-block.tablet-inset ul{border-radius:7px;border-top:none;border-bottom:none}.list-block.tablet-inset li:first-child>a{border-radius:7px 7px 0 0}.list-block.tablet-inset li:last-child>a{border-radius:0 0 7px 7px}.list-block.tablet-inset li:first-child:last-child>a{border-radius:7px}.list-block.tablet-inset .content-block-title{margin-left:0;margin-right:0}.list-block.tablet-inset ul{border-radius:7px;border-top:none;border-bottom:none}.list-block.tablet-inset li:first-child>a{border-radius:7px 7px 0 0}.list-block.tablet-inset li:last-child>a{border-radius:0 0 7px 7px}.list-block.tablet-inset li:first-child:last-child>a{border-radius:7px}}.list-block li{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative}.list-block .item-media{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;-webkit-box-lines:single;-moz-box-lines:single;-webkit-flex-wrap:nowrap;-ms-flex-wrap:none;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;padding-top:7px;padding-bottom:8px}.list-block .item-media i+i{margin-left:5px}.list-block .item-media i+img{margin-left:5px}.list-block .item-media+.item-inner{margin-left:15px}.list-block .item-inner{padding-right:15px;border-bottom:1px solid #c8c7cc;width:100%;padding-top:8px;padding-bottom:7px;min-height:44px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-flex:1;-ms-flex:1;-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.list-block .item-title{-webkit-flex-shrink:1;-ms-flex:0 1 auto;flex-shrink:1;white-space:nowrap;position:relative;overflow:hidden;text-overflow:ellipsis;max-width:100%}.list-block .item-title.label{width:35%;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0}.list-block .item-input{width:100%;margin-top:-8px;margin-bottom:-7px;-webkit-box-flex:1;-ms-flex:1;-webkit-flex-shrink:1;-ms-flex:0 1 auto;flex-shrink:1}.list-block .item-after{white-space:nowrap;color:#8e8e93;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;margin-left:5px;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;max-height:28px}.list-block .smart-select .item-after{max-width:70%;overflow:hidden;text-overflow:ellipsis;position:relative}.list-block .item-link{-webkit-transition-duration:300ms;transition-duration:300ms;display:block;color:inherit}.list-block .item-link .item-inner{padding-right:35px;background:no-repeat -webkit-calc(100% - 15px) center;background:no-repeat calc(100% - 15px) center;background-image:url("data:image/svg+xml;charset=utf-8,");background-size:10px 20px}html:not(.watch-active-state) .list-block .item-link:active,.list-block .item-link.active-state{-webkit-transition-duration:0ms;transition-duration:0ms;background-color:#d9d9d9}html:not(.watch-active-state) .list-block .item-link:active .item-inner,.list-block .item-link.active-state .item-inner{border-bottom-color:transparent}.list-block .item-link.list-button{padding:0 15px;text-align:center;color:#007aff;display:block;border-bottom:1px solid #c8c7cc;line-height:43px}.list-block .item-content{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding-left:15px;min-height:44px;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}.list-block .list-block-label{margin:10px 0 35px;padding:0 15px;font-size:14px;color:#8f8f94}.list-block .swipeout{overflow:hidden;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.list-block .swipeout.deleting{-webkit-transition-duration:300ms;transition-duration:300ms}.list-block .swipeout.deleting .swipeout-content{-webkit-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.list-block .swipeout.transitioning .swipeout-content,.list-block .swipeout.transitioning .swipeout-actions-right a,.list-block .swipeout.transitioning .swipeout-actions-left a,.list-block .swipeout.transitioning .swipeout-overswipe{-webkit-transition:300ms;transition:300ms}.list-block .swipeout-content{position:relative;z-index:10}.list-block .swipeout-overswipe{-webkit-transition:200ms left;transition:200ms left}.list-block .swipeout-actions-left,.list-block .swipeout-actions-right{position:absolute;top:0;height:100%;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transform:translate3d(0%,0,0);-ms-transform:translate3d(0%,0,0);transform:translate3d(0%,0,0)}.list-block .swipeout-actions-left a,.list-block .swipeout-actions-right a{padding:0 30px;color:#fff;background:#c7c7cc;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;position:relative;left:0}.list-block .swipeout-actions-left a:after,.list-block .swipeout-actions-right a:after{content:'';position:absolute;top:0;width:600%;height:100%;background:inherit;z-index:-1}.list-block .swipeout-actions-left a.swipeout-delete,.list-block .swipeout-actions-right a.swipeout-delete{background:#ff3b30}.list-block .swipeout-actions-right{right:0;-webkit-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.list-block .swipeout-actions-right a:after{left:100%;margin-left:-1px}.list-block .swipeout-actions-left{left:0;-webkit-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.list-block .swipeout-actions-left a:after{right:100%;margin-right:-1px}.list-block .item-subtitle{font-size:15px;position:relative;overflow:hidden;white-space:nowrap;max-width:100%;text-overflow:ellipsis}.list-block .item-text{font-size:15px;color:#8e8e93;line-height:21px;position:relative;overflow:hidden;height:42px;text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.list-block.media-list .item-title,.list-block li.media-item .item-title{font-weight:500}.list-block.media-list .item-inner,.list-block li.media-item .item-inner{display:block;padding-top:10px;padding-bottom:9px;-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.list-block.media-list .item-link .item-inner,.list-block li.media-item .item-link .item-inner{background:0 0;padding-right:15px}.list-block.media-list .item-link .item-title-row,.list-block li.media-item .item-link .item-title-row{padding-right:20px;background:no-repeat right center;background-image:url("data:image/svg+xml;charset=utf-8,");background-size:10px 20px}.list-block.media-list .item-media,.list-block li.media-item .item-media{padding-top:9px;padding-bottom:10px}.list-block.media-list .item-media img,.list-block li.media-item .item-media img{display:block}.list-block.media-list .item-title-row,.list-block li.media-item .item-title-row{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.list-block .list-group:nth-child(n+2) ul{border-top:none}.list-block .item-divider,.list-block .list-group-title{background:#f7f7f7;border-top:1px solid #c8c7cc;margin-top:-1px;padding:4px 15px;white-space:nowrap;position:relative;max-width:100%;text-overflow:ellipsis;overflow:hidden;color:#8e8e93}.list-block .list-group-title{position:relative;position:-webkit-sticky;position:-moz-sticky;position:sticky;top:0;z-index:10;margin-top:0;border-top:none}.list-block .sortable-handler{position:absolute;right:0;top:0;height:-webkit-calc(100% - 1px);height:calc(100% - 1px);z-index:10;background-repeat:no-repeat;background-size:18px 12px;background-position:center;width:35px;background-image:url("data:image/svg+xml;charset=utf-8,");opacity:0;visibility:hidden;cursor:pointer;-webkit-transition-duration:300ms;transition-duration:300ms}.list-block.sortable .item-inner{-webkit-transition-duration:300ms;transition-duration:300ms}.list-block.sortable-opened .sortable-handler{visibility:visible;opacity:1}.list-block.sortable-opened .item-inner,.list-block.sortable-opened .item-link .item-inner{padding-right:35px}.list-block.sortable-opened .item-link .item-inner,.list-block.sortable-opened .item-link .item-title-row{background-image:none}.list-block.sortable-sorting li{-webkit-transition-duration:300ms;transition-duration:300ms}.list-block li.sorting{z-index:50;background:rgba(255,255,255,.8);box-shadow:0 2px 8px rgba(0,0,0,.6);-webkit-transition-duration:0ms;transition-duration:0ms}.list-block li.sorting .item-inner{border-bottom:none}.list-block li:last-child .list-button{border-bottom:none}.list-block li:last-child .item-inner,.list-block li:last-child li:last-child .item-inner{border-bottom:none}.list-block li li:last-child .item-inner,.list-block li:last-child li .item-inner{border-bottom:1px solid #c8c7cc}html.retina.ios-gt-7 .list-block ul{border-top-width:.5px;border-bottom-width:.5px}html.retina.ios-gt-7 .list-block li:not(:last-child) .item-inner{border-bottom-width:.5px}html.retina.ios-gt-7 .item-divider{border-top-width:.5px;margin-top:-.5px}html.retina.ios-gt-7 .item-link.list-button{border-bottom-width:.5px}.contacts-content{background:#fff}.contacts-block{margin:0}.contacts-block .list-group-title{padding:0 15px;background:#f7f7f7;color:#000;font-weight:500;line-height:22px;height:22px}.contacts-block .list-group:first-child ul{border-top:none}.contacts-block .list-group:last-child ul{border-bottom:none}.list-block input[type=text],.list-block input[type=password],.list-block input[type=email],.list-block input[type=tel],.list-block input[type=url],.list-block input[type=date],.list-block input[type=datetime-local],.list-block input[type=number],.list-block select,.list-block textarea{-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:none;background:0 0;border-radius:0;-webkit-box-shadow:none;box-shadow:none;display:block;padding:0 0 0 5px;margin:0;width:100%;height:43px;color:#000;font-size:17px;font-family:inherit}.list-block input[type=date],.list-block input[type=datetime-local]{line-height:44px}.list-block select{-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none}.list-block .lable{vertical-align:top}.list-block textarea{height:100px;resize:none;line-height:1.4;padding-top:8px;padding-bottom:7px}.label-switch{display:inline-block;vertical-align:middle;width:52px;border-radius:16px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:32px;position:relative;cursor:pointer;-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.label-switch .checkbox{width:52px;border-radius:16px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:32px;background:#e5e5e5;z-index:0;margin:0;padding:0;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;cursor:pointer;position:relative;-webkit-transition-duration:300ms;transition-duration:300ms}.label-switch .checkbox:before{content:' ';position:absolute;left:2px;top:2px;width:48px;border-radius:16px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:28px;background:#fff;z-index:1;-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}.label-switch .checkbox:after{content:' ';height:28px;width:28px;border-radius:28px;background:#fff;position:absolute;z-index:2;top:2px;left:2px;-webkit-box-shadow:0 2px 5px rgba(0,0,0,.4);box-shadow:0 2px 5px rgba(0,0,0,.4);-webkit-transform:translateX(0px);-ms-transform:translateX(0px);transform:translateX(0px);-webkit-transition-duration:300ms;transition-duration:300ms}.label-switch input[type=checkbox]{display:none}.label-switch input[type=checkbox]:checked+.checkbox{background:#4cd964}.label-switch input[type=checkbox]:checked+.checkbox:before{-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}.label-switch input[type=checkbox]:checked+.checkbox:after{-webkit-transform:translateX(22px);-ms-transform:translateX(22px);transform:translateX(22px)}html.android .label-switch input[type=checkbox]+.checkbox{-webkit-transition-duration:0;transition-duration:0}html.android .label-switch input[type=checkbox]+.checkbox:after,html.android .label-switch input[type=checkbox]+.checkbox:before{-webkit-transition-duration:0;transition-duration:0}.button{border:1px solid #007aff;color:#007aff;text-decoration:none;text-align:center;display:block;border-radius:5px;line-height:27px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;padding:0 10px;margin:0;height:29px;white-space:nowrap;position:relative;overflow:hidden;text-overflow:ellipsis;font-size:14px;font-family:inherit;cursor:pointer}input[type=submit].button,input[type=button].button{width:100%}html:not(.watch-active-state) .button:active,.button.active-state{background:rgba(0,122,255,.15)}.button.button-round{border-radius:27px}.button.active{background:#007aff;color:#fff}.button.button-big{font-size:17px;height:44px;line-height:42px}.button.button-fill{color:#fff;background:#007aff;border:none}html:not(.watch-active-state) .button.button-fill:active,.button.button-fill.active-state{opacity:.8}.buttons-row{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-lines:single;-moz-box-lines:single;-webkit-flex-wrap:nowrap;-ms-flex-wrap:none;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.buttons-row .button{border-radius:0;border-left-width:0;width:100%;-webkit-box-flex:1;-ms-flex:1}.buttons-row .button:first-child{border-radius:5px 0 0 5px;border-left-width:1px;border-left-style:solid}.buttons-row .button:last-child{border-radius:0 5px 5px 0}.buttons-row .button.button-round:first-child{border-radius:27px 0 0 27px}.buttons-row .button.button-round:last-child{border-radius:0 27px 27px 0}.range-slider{width:100%;position:relative;overflow:hidden;padding-left:3px;padding-right:3px;margin-left:-1px;-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.range-slider input[type=range]{position:relative;height:28px;width:100%;margin:4px 0 5px;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(0,#b7b8b7),color-stop(100%,#b7b8b7));background:linear-gradient(to right,#b7b8b7 0,#b7b8b7 100%);background-position:center;background-size:100% 2px;background-repeat:no-repeat;outline:0}.range-slider input[type=range]:after{height:2px;background:#fff;content:' ';width:5px;top:50%;margin-top:-1px;left:-5px;z-index:1;position:absolute}.range-slider input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;height:28px;width:28px;position:relative;background:0 0}.range-slider input[type=range]::-webkit-slider-thumb:after{height:28px;width:28px;border-radius:28px;background:#fff;z-index:10;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.4);box-shadow:0 2px 4px rgba(0,0,0,.4);position:absolute;left:0;top:0;content:' '}.range-slider input[type=range]::-webkit-slider-thumb:before{position:absolute;top:50%;right:100%;width:2000px;height:2px;margin-top:-1px;z-index:1;background:#007aff;content:' '}label.label-checkbox{cursor:pointer}label.label-checkbox i.icon-form-checkbox{width:22px;height:22px;position:relative;border-radius:22px;border:1px solid #c7c7cc;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}label.label-checkbox i.icon-form-checkbox:after{content:' ';position:absolute;left:50%;margin-left:-6px;top:50%;margin-top:-4px;width:12px;height:9px}label.label-checkbox input[type=checkbox],label.label-checkbox input[type=radio]{display:none}label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{border:none;background-color:#007aff}label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox:after,label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox:after{background:no-repeat center;background-image:url("data:image/svg+xml;charset=utf-8,");-webkit-background-size:12px 9px;background-size:12px 9px}label.label-radio{cursor:pointer}label.label-radio input[type=checkbox],label.label-radio input[type=radio]{display:none}label.label-radio input[type=checkbox]~.item-inner,label.label-radio input[type=radio]~.item-inner{padding-right:35px}label.label-radio input[type=checkbox]:checked~.item-inner,label.label-radio input[type=radio]:checked~.item-inner{background:no-repeat center;background-image:url("data:image/svg+xml;charset=utf-8, ");background-position:90% center;background-position:-webkit-calc(100% - 15px) center;background-position:calc(100% - 15px) center;-webkit-background-size:13px 10px;background-size:13px 10px}label.label-checkbox,label.label-radio{-webkit-transition-duration:300ms;transition-duration:300ms}html:not(.watch-active-state) label.label-checkbox:active,html:not(.watch-active-state) label.label-radio:active,label.label-checkbox.active-state,label.label-radio.active-state{-webkit-transition-duration:0ms;transition-duration:0ms;background-color:#d9d9d9}html:not(.watch-active-state) label.label-checkbox:active .item-inner,html:not(.watch-active-state) label.label-radio:active .item-inner,label.label-checkbox.active-state .item-inner,label.label-radio.active-state .item-inner{border-bottom-color:transparent}.smart-select select{display:none}.list-block .accordion-item-toggle{cursor:pointer;-webkit-transition-duration:300ms;transition-duration:300ms}.list-block .accordion-item-toggle .item-inner{padding-right:35px;background:no-repeat -webkit-calc(100% - 15px) center;background:no-repeat calc(100% - 15px) center;background-image:url("data:image/svg+xml;charset=utf-8,");background-size:10px 20px}html:not(.watch-active-state) .list-block .accordion-item-toggle:active,.list-block .accordion-item-toggle.active-state{-webkit-transition-duration:0ms;transition-duration:0ms;background-color:#d9d9d9}html:not(.watch-active-state) .list-block .accordion-item-toggle:active>.item-inner,.list-block .accordion-item-toggle.active-state>.item-inner{border-bottom-color:transparent}.list-block .accordion-item-toggle .item-inner,.list-block .accordion-item>.item-link .item-inner{-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-property:background-color,border-color;transition-property:background-color,border-color}.list-block .accordion-item-expanded .accordion-toggle .item-inner,.list-block .accordion-item-expanded>.item-link .item-inner{background-image:url("data:image/svg+xml;charset=utf-8,");background-size:20px 20px;border-bottom-color:transparent}.list-block .accordion-item .content-block,.list-block .accordion-item .list-block{margin-top:0;margin-bottom:0}.list-block .accordion-item ul{padding-left:0}.accordion-item-content{position:relative;overflow:hidden;height:0;font-size:14px;-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.accordion-item-expanded .accordion-item-content{height:auto}.modal-overlay,.preloader-indicator-overlay,.popup-overlay{position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.4);z-index:10600;visibility:hidden;opacity:0;-webkit-transition-duration:400ms;transition-duration:400ms}.modal-overlay.modal-overlay-visible,.preloader-indicator-overlay.modal-overlay-visible,.popup-overlay.modal-overlay-visible{visibility:visible;opacity:1}html.ios .modal-overlay.modal-overlay-visible,html.ios .preloader-indicator-overlay.modal-overlay-visible,html.ios .popup-overlay.modal-overlay-visible{overflow:auto;-webkit-overflow-scrolling:touch}.popup-overlay{z-index:10200}.modal{width:270px;position:absolute;z-index:11000;left:50%;margin-left:-135px;margin-top:0;top:50%;text-align:center;border-radius:7px;opacity:0;-webkit-transform:translate3d(0,0,0) scale(1.185);-ms-transform:translate3d(0,0,0) scale(1.185);transform:translate3d(0,0,0) scale(1.185);-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-ms-transition-property:-ms-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;color:#000}.modal.modal-in{opacity:1;-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(0,0,0) scale(1);-ms-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1)}.modal.modal-out{opacity:0;z-index:10999;-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transform:translate3d(0,0,0) scale(0.815);-ms-transform:translate3d(0,0,0) scale(0.815);transform:translate3d(0,0,0) scale(0.815)}.modal-inner{padding:15px;border-bottom:1px solid #b5b5b5;border-radius:7px 7px 0 0;background:#e8e8e8}.modal-title{font-weight:500;font-size:18px;text-align:center}.modal-title+.modal-text{margin-top:5px}.modal-buttons{height:44px;overflow:hidden;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.modal-button{width:100%;padding:0 5px;height:44px;font-size:17px;line-height:44px;text-align:center;color:#007aff;background:#e8e8e8;display:block;position:relative;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;cursor:pointer;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-right:1px solid #b5b5b5;-webkit-box-flex:1;-ms-flex:1}.modal-button:first-child{border-radius:0 0 0 7px}.modal-button:last-child{border-right:none;border-radius:0 0 7px}.modal-button:first-child:last-child{border-radius:0 0 7px 7px}.modal-button.modal-button-bold{font-weight:500}html:not(.watch-active-state) .modal-button:active,.modal-button.active-state{background:#d4d4d4}.modal-no-buttons .modal-inner{border-radius:7px;border-bottom:none}.modal-no-buttons .modal-buttons{display:none}.actions-modal{position:absolute;left:0;bottom:0;z-index:11000;width:100%;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.actions-modal.modal-in{-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.actions-modal.modal-out{z-index:10999;-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.actions-modal-group{margin:8px}.actions-modal-button,.actions-modal-label{width:100%;text-align:center;font-weight:400;margin:0;background:rgba(243,243,243,.95);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;border-bottom:1px solid #d2d2d6}.actions-modal-button a,.actions-modal-label a{text-decoration:none;color:inherit}.actions-modal-button b,.actions-modal-label b{font-weight:500}.actions-modal-button.actions-modal-button-bold,.actions-modal-label.actions-modal-button-bold{font-weight:500}.actions-modal-button.actions-modal-button-red,.actions-modal-label.actions-modal-button-red{color:#ff3b30}.actions-modal-button:first-child,.actions-modal-label:first-child{border-radius:4px 4px 0 0}.actions-modal-button:last-child,.actions-modal-label:last-child{border:none;border-radius:0 0 4px 4px}.actions-modal-button:first-child:last-child,.actions-modal-label:first-child:last-child{border-radius:4px}.actions-modal-button{cursor:pointer;line-height:43px;font-size:20px;color:#007aff}html:not(.watch-active-state) .actions-modal-button:active,.actions-modal-button.active-state{background:#dcdcdc}.actions-modal-label{font-size:13px;line-height:1.3;min-height:44px;padding:8px 10px;color:#8a8a8a;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center}input.modal-text-input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:30px;background:#fff;margin:0;margin-top:15px;padding:0 5px;border:1px solid #a0a0a0;border-radius:5px;width:100%;font-size:14px;font-family:inherit;display:block;-webkit-box-shadow:0 0 0 rgba(0,0,0,0);box-shadow:0 0 0 rgba(0,0,0,0);-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none}input.modal-text-input+input.modal-text-input{margin-top:5px}input.modal-text-input.modal-text-input-double{border-radius:5px 5px 0 0}input.modal-text-input.modal-text-input-double+input.modal-text-input{margin-top:0;border-top:0;border-radius:0 0 5px 5px}.popover{width:320px;background:rgba(255,255,255,.95);z-index:11000;margin:0;top:0;opacity:0;left:0;border-radius:7px;position:absolute;display:none;-webkit-transform:none;-ms-transform:none;transform:none;-webkit-transition-property:opacity;-moz-transition-property:opacity;-ms-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.popover.modal-in{-webkit-transition-duration:300ms;transition-duration:300ms;opacity:1}.popover .list-block{margin:0}.popover .list-block ul{background:0 0}.popover .list-block:first-child ul{border-top:none;border-radius:7px 7px 0 0}.popover .list-block:first-child li:first-child a{border-radius:7px 7px 0 0}.popover .list-block:last-child ul{border-bottom:none;border-radius:0 0 7px 7px}.popover .list-block:last-child li:last-child a{border-radius:0 0 7px 7px}.popover .list-block:first-child:last-child li:first-child:last-child a,.popover .list-block:first-child:last-child ul:first-child:last-child{border-radius:7px}.popover .list-block+.list-block{margin-top:35px}.popover-angle{width:26px;height:26px;position:absolute;left:-26px;top:0;z-index:100;overflow:hidden}.popover-angle:after{content:' ';background:rgba(255,255,255,.95);width:26px;height:26px;position:absolute;left:0;top:0;border-radius:3px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.popover-angle.on-left{left:-26px}.popover-angle.on-left:after{left:19px;top:0}.popover-angle.on-right{left:100%}.popover-angle.on-right:after{left:-19px;top:0}.popover-angle.on-top{left:0;top:-26px}.popover-angle.on-top:after{left:0;top:19px}.popover-angle.on-bottom{left:0;top:100%}.popover-angle.on-bottom:after{left:0;top:-19px}.popover-inner{overflow:auto;-webkit-overflow-scrolling:touch}.actions-popover .list-block+.list-block{margin-top:20px}.actions-popover .list-block ul{background:#fff}.actions-popover-label{padding:8px 10px;color:#8a8a8a;font-size:13px;line-height:1.3;text-align:center;border-bottom:1px solid #d2d2d6}.actions-popover-label:last-child{border-bottom:none}.popup,.login-screen{position:absolute;left:0;top:0;width:100%;height:100%;z-index:10400;background:#fff;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:none;overflow:auto;-webkit-overflow-scrolling:touch;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-ms-transition-property:-ms-transform;-o-transition-property:-o-transform;transition-property:transform;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.popup.modal-in,.login-screen.modal-in,.popup.modal-out,.login-screen.modal-out{-webkit-transition-duration:400ms;transition-duration:400ms}.popup.modal-in,.login-screen.modal-in{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.popup.modal-out,.login-screen.modal-out{-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.login-screen.modal-in,.login-screen.modal-out{display:block}@media all and (min-width:630px) and (min-height:630px){.popup:not(.tablet-fullscreen){width:630px;height:630px;left:50%;top:50%;margin-left:-315px;margin-top:-315px;-webkit-transform:translate3d(0,1024px,0);-ms-transform:translate3d(0,1024px,0);transform:translate3d(0,1024px,0)}.popup:not(.tablet-fullscreen).modal-in{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.popup:not(.tablet-fullscreen).modal-out{-webkit-transform:translate3d(0,1024px,0);-ms-transform:translate3d(0,1024px,0);transform:translate3d(0,1024px,0)}}@media all and (max-width:629px),(max-height:629px){html.with-statusbar-overlay .popup{height:-webkit-calc(100% - 20px);height:calc(100% - 20px);top:20px}html.with-statusbar-overlay .popup-overlay{z-index:9800}}html.with-statusbar-overlay .login-screen,html.with-statusbar-overlay .popup.tablet-fullscreen{height:-webkit-calc(100% - 20px);height:calc(100% - 20px);top:20px}.modal .preloader{width:34px;height:34px}.preloader-indicator-overlay{visibility:visible;opacity:0;background:0 0}.preloader-indicator-modal{position:absolute;left:50%;top:50%;padding:8px;margin-left:-25px;margin-top:-25px;background:rgba(0,0,0,.8);z-index:11000;border-radius:5px}.preloader-indicator-modal .preloader{display:block;width:34px;height:34px}html.retina.ios-gt-7 .modal-inner{border-bottom-width:.5px}html.retina.ios-gt-7 .modal-button{border-right-width:.5px}html.retina.ios-gt-7 .actions-modal-button,html.retina.ios-gt-7 .actions-modal-label{border-bottom-width:.5px}html.retina.ios-gt-7 .actions-popover-label{border-bottom-width:.5px}html.retina.ios-gt-7 input.modal-text-input{border-width:.5px}.panel-overlay{position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0);opacity:0;z-index:5999;display:none}.panel{z-index:1000;display:none;background:#111;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;overflow:auto;-webkit-overflow-scrolling:touch;position:absolute;width:260px;top:0;height:100%;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:400ms;transition-duration:400ms}.panel.panel-left.panel-cover{z-index:6000;left:-260px}.panel.panel-left.panel-reveal{left:0}.panel.panel-right.panel-cover{z-index:6000;right:-260px}.panel.panel-right.panel-reveal{right:0}body.with-panel-left-cover .views,body.with-panel-right-cover .views{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}body.with-panel-left-cover .panel-overlay,body.with-panel-right-cover .panel-overlay{display:block}body.with-panel-left-reveal .views,body.with-panel-right-reveal .views{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}body.with-panel-left-reveal .panel-overlay,body.with-panel-right-reveal .panel-overlay{display:block}body.with-panel-left-reveal .views{-webkit-transform:translate3d(260px,0,0);-ms-transform:translate3d(260px,0,0);transform:translate3d(260px,0,0)}body.with-panel-left-reveal .panel-overlay{margin-left:260px}body.with-panel-left-cover .panel-left{-webkit-transform:translate3d(260px,0,0);-ms-transform:translate3d(260px,0,0);transform:translate3d(260px,0,0)}body.with-panel-right-reveal .views{-webkit-transform:translate3d(-260px,0,0);-ms-transform:translate3d(-260px,0,0);transform:translate3d(-260px,0,0)}body.with-panel-right-reveal .panel-overlay{margin-left:-260px}body.with-panel-right-cover .panel-right{-webkit-transform:translate3d(-260px,0,0);-ms-transform:translate3d(-260px,0,0);transform:translate3d(-260px,0,0)}body.panel-closing .views{-webkit-transition-duration:400ms;transition-duration:400ms;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}.tabs .tab{display:none}.tabs .tab.active{display:block}.tabs-animated-wrap{position:relative;width:100%;overflow:hidden;height:100%}.tabs-animated-wrap>.tabs{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;height:100%;-webkit-transition-duration:300ms;transition-duration:300ms}.tabs-animated-wrap>.tabs>.tab{width:100%;display:block;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0}.messages-content{background:#fff}.messages{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.messages-date{text-align:center;font-weight:500;font-size:11px;line-height:1;margin:10px 15px;color:#8e8e93}.messages-date span{font-weight:400}.message{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px 10px 0;max-width:70%;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.message:first-child{margin-top:10px}.message .message-text{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:16px;padding:6px 16px 9px;min-width:48px;min-height:35px;font-size:17px;line-height:1.2;word-break:break-word}.message.message-pic .message-text{padding:0;background:0 0}.message.message-pic img{display:block;height:auto;max-width:100%;border-radius:16px}.message-name{font-size:12px;line-height:1;color:#8e8e93;margin-bottom:2px;margin-top:7px;display:none}.message-avatar{width:29px;height:29px;border-radius:100%;margin-top:-29px;position:relative;top:1px;background-size:cover;opacity:0;-webkit-transition-duration:400ms;transition-duration:400ms}.message-sent{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end;-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.message-sent .message-name{margin-right:16px}.message-sent.message-with-avatar .message-text{margin-right:29px}.message-sent.message-with-avatar .message-name{margin-right:45px}.message-sent .message-text{padding-right:22px;background-color:#00d449;color:#fff;margin-left:auto;-webkit-mask-box-image:url("data:image/svg+xml;charset=utf-8,") 50% 56% 49% 43%}.message-sent.message-last .message-text{border-radius:16px 16px 0;-webkit-mask-box-image:url("data:image/svg+xml;charset=utf-8,") 50% 56% 49% 43%}.message-sent.message-last.message-pic img{border-radius:16px 16px 0}.message-received{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start;-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.message-received .message-text{padding-left:22px;background-color:#e5e5ea;color:#000;-webkit-mask-box-image:url("data:image/svg+xml;charset=utf-8,") 50% 43% 49% 56%}.message-received .message-name{margin-left:16px}.message-received.message-with-avatar .message-text{margin-left:29px}.message-received.message-with-avatar .message-name{margin-left:45px}.message-received.message-last .message-text{border-radius:16px 16px 16px 0;-webkit-mask-box-image:url("data:image/svg+xml;charset=utf-8,") 50% 43% 49% 56%}.message-received.message-last.message-pic img{border-radius:16px 16px 16px 0}.message-first .message-name{display:block}.message-last{margin-bottom:8px}.message-last .message-avatar{opacity:1}.message-appear{-webkit-animation:messageAppearFromBottom 400ms;animation:messageAppearFromBottom 400ms}.new-messages-first .message-appear{-webkit-animation:messageAppearFromTop 400ms;animation:messageAppearFromTop 400ms}html.retina.ios-6 .message,html.retina.ios-6 .message.message-pic img{-webkit-mask-box-image:none;border-radius:16px}@-webkit-keyframes messageAppearFromBottom{from{-webkit-transform:translate3d(0,100%,0)}to{-webkit-transform:translate3d(0,0,0)}}@keyframes messageAppearFromBottom{from{transform:translate3d(0,100%,0)}to{transform:translate3d(0,0,0)}}@-webkit-keyframes messageAppearFromTop{from{-webkit-transform:translate3d(0,-100%,0)}to{-webkit-transform:translate3d(0,0,0)}}@keyframes messageAppearFromTop{from{transform:translate3d(0,-100%,0)}to{transform:translate3d(0,0,0)}}html.with-statusbar-overlay body{padding-top:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html.with-statusbar-overlay body .statusbar-overlay{display:block}html.with-statusbar-overlay body .panel{padding-top:20px}.statusbar-overlay{background:#f7f7f8;z-index:10000;position:absolute;left:0;top:0;height:20px;width:100%;display:none;-webkit-transition-duration:400ms;transition-duration:400ms}.preloader{display:inline-block;width:20px;height:20px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:preloader-spin 1s step-end infinite;animation:preloader-spin 1s step-end infinite}.preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,");background-position:50%;background-size:100%;background-repeat:no-repeat}.preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,")}@-webkit-keyframes preloader-spin{0%{-webkit-transform:rotate(0deg)}8.33333333%{-webkit-transform:rotate(30deg)}16.66666667%{-webkit-transform:rotate(60deg)}25%{-webkit-transform:rotate(90deg)}33.33333333%{-webkit-transform:rotate(120deg)}41.66666667%{-webkit-transform:rotate(150deg)}50%{-webkit-transform:rotate(180deg)}58.33333333%{-webkit-transform:rotate(210deg)}66.66666667%{-webkit-transform:rotate(240deg)}75%{-webkit-transform:rotate(270deg)}83.33333333%{-webkit-transform:rotate(300deg)}91.66666667%{-webkit-transform:rotate(330deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes preloader-spin{0%{transform:rotate(0deg)}8.33333333%{transform:rotate(30deg)}16.66666667%{transform:rotate(60deg)}25%{transform:rotate(90deg)}33.33333333%{transform:rotate(120deg)}41.66666667%{transform:rotate(150deg)}50%{transform:rotate(180deg)}58.33333333%{transform:rotate(210deg)}66.66666667%{transform:rotate(240deg)}75%{transform:rotate(270deg)}83.33333333%{transform:rotate(300deg)}91.66666667%{transform:rotate(330deg)}100%{transform:rotate(360deg)}}.pull-to-refresh-layer{position:absolute;position:relative;margin-top:-44px;left:0;top:0;width:100%;height:44px}.pull-to-refresh-layer .preloader{position:absolute;left:50%;top:50%;margin-left:-10px;margin-top:-10px;visibility:hidden}.pull-to-refresh-layer .pull-to-refresh-arrow{width:13px;height:20px;position:absolute;left:50%;top:50%;margin-left:-6px;margin-top:-10px;background:no-repeat center;background-image:url("data:image/svg+xml;charset=utf-8,");background-size:13px 20px;z-index:10;-webkit-transform:rotate(0deg) translate3d(0,0,0);-ms-transform:rotate(0deg) translate3d(0,0,0);transform:rotate(0deg) translate3d(0,0,0);-webkit-transition-duration:300ms;transition-duration:300ms}.pull-to-refresh-content.transitioning,.pull-to-refresh-content.refreshing{-webkit-transition-duration:400ms;transition-duration:400ms}.pull-to-refresh-content:not(.refreshing) .preloader{-webkit-animation:none;animation:none}.pull-to-refresh-content.refreshing{-webkit-transform:translate3d(0,44px,0);-ms-transform:translate3d(0,44px,0);transform:translate3d(0,44px,0)}.pull-to-refresh-content.refreshing .pull-to-refresh-arrow{visibility:hidden;-webkit-transition-duration:0ms;transition-duration:0ms}.pull-to-refresh-content.refreshing .preloader{visibility:visible}.pull-to-refresh-content.pull-up .pull-to-refresh-arrow{-webkit-transform:rotate(180deg) translate3d(0,0,0);-ms-transform:rotate(180deg) translate3d(0,0,0);transform:rotate(180deg) translate3d(0,0,0)}.slider-container{position:relative;overflow:hidden;width:100%;height:100%}.slider-wrapper{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;width:100%;height:100%;position:relative;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slider-container-vertical>.slider-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.slider-slide{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%}.slider-pagination{position:absolute;z-index:10;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0;bottom:10px;width:100%;text-align:center;-webkit-transition-duration:300ms;transition-duration:300ms;opacity:1;-webkit-transition-property:opacity;-moz-transition-property:opacity;transition-property:opacity}.slider-pagination.slider-pagination-hidden{opacity:0;pointer-events:none}.slider-container-vertical>.slider-pagination{right:10px;left:auto;top:50%;bottom:auto;width:auto;height:auto;-webkit-transform:translate3d(0,-50%,0);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.slider-container-vertical>.slider-pagination .slider-pagination-bullet{display:block;margin:5px 0}.slider-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2;margin:0 5px}.slider-pagination-active{opacity:1;background:#007aff}.photo-browser{position:absolute;left:0;top:0;width:100%;height:100%;z-index:10500}body>.photo-browser{opacity:0;display:none;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}body>.photo-browser.photo-browser-in{display:block;-webkit-animation:photoBrowserIn 400ms forwards;animation:photoBrowserIn 400ms forwards}body>.photo-browser.photo-browser-out{display:block;-webkit-animation:photoBrowserOut 400ms forwards;animation:photoBrowserOut 400ms forwards}html.with-statusbar-overlay body>.photo-browser{height:-webkit-calc(100% - 20px);height:calc(100% - 20px);top:20px}.popup>.photo-browser .navbar,body>.photo-browser .navbar,.popup>.photo-browser .toolbar,body>.photo-browser .toolbar{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.photo-browser .page[data-page=photo-browser-slides]{background:0 0}.photo-browser-popup{background:0 0}.photo-browser .navbar,.view[data-page=photo-browser-slides] .navbar,.photo-browser .toolbar,.view[data-page=photo-browser-slides] .toolbar{background:rgba(247,247,247,.95);-webkit-transition-duration:400ms;transition-duration:400ms}.view[data-page=photo-browser-slides] .page[data-page=photo-browser-slides] .navbar,.view[data-page=photo-browser-slides] .page[data-page=photo-browser-slides] .toolbar{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.photo-browser-exposed .navbar,.photo-browser-exposed .toolbar{opacity:0;visibility:hidden;pointer-events:none}.photo-browser-exposed .photo-browser-slider-container{background:#000}.photo-browser-of{margin:0 5px}.photo-browser-captions{pointer-events:none;position:absolute;left:0;width:100%;bottom:0;z-index:10;opacity:1;-webkit-transition-duration:400ms;transition-duration:400ms}.photo-browser-captions.photo-browser-captions-exposed{opacity:0}.toolbar~.photo-browser-captions{bottom:44px;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.photo-browser-exposed .toolbar~.photo-browser-captions{-webkit-transform:translate3d(0,44px,0);-ms-transform:translate3d(0,44px,0);transform:translate3d(0,44px,0)}.toolbar~.photo-browser-captions.photo-browser-captions-exposed{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.photo-browser-caption{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition-duration:300ms;transition-duration:300ms;position:absolute;bottom:0;left:0;opacity:0;padding:4px 5px;width:100%;text-align:center;color:#fff;background:rgba(0,0,0,.8)}.photo-browser-caption:empty{display:none}.photo-browser-caption.photo-browser-caption-active{opacity:1}.photo-browser-captions-light .photo-browser-caption{background:rgba(255,255,255,.8);color:#000}.photo-browser-exposed .photo-browser-caption{color:#fff;background:rgba(0,0,0,.8)}.photo-browser-slider-container{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;background:#fff;-webkit-transition-duration:400ms;transition-duration:400ms}.photo-browser-slider-wrapper{position:absolute;left:0;top:0;width:100%;height:100%;padding:0;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.photo-browser-link-inactive{opacity:.3}.photo-browser-slide{width:100%;height:100%;position:relative;overflow:hidden;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.photo-browser-slide.transitioning{-webkit-transition-duration:400ms;transition-duration:400ms}.photo-browser-slide span{width:100%;text-align:center;display:none}.photo-browser-slide img{width:auto;height:auto;max-width:100%;max-height:100%;display:none}.photo-browser-slide.slider-slide-active span,.photo-browser-slide.slider-slide-next span,.photo-browser-slide.slider-slide-prev span{display:block}.photo-browser-slide.slider-slide-active img,.photo-browser-slide.slider-slide-next img,.photo-browser-slide.slider-slide-prev img{display:inline}.photo-browser-slide iframe{width:100%;height:100%}.photo-browser-dark .navbar,.photo-browser-dark .toolbar{background:rgba(30,30,30,.8);border:none;color:#fff}.photo-browser-dark .navbar a,.photo-browser-dark .toolbar a{color:#fff}.photo-browser-dark .photo-browser-slider-container{background:#000}@-webkit-keyframes photoBrowserIn{0%{-webkit-transform:translate3d(0,0,0) scale(0.5);opacity:0}100%{-webkit-transform:translate3d(0,0,0) scale(1);opacity:1}}@keyframes photoBrowserIn{0%{transform:translate3d(0,0,0) scale(0.5);opacity:0}100%{transform:translate3d(0,0,0) scale(1);opacity:1}}@-webkit-keyframes photoBrowserOut{0%{-webkit-transform:translate3d(0,0,0) scale(1);opacity:1}100%{-webkit-transform:translate3d(0,0,0) scale(0.5);opacity:0}}@keyframes photoBrowserOut{0%{transform:translate3d(0,0,0) scale(1);opacity:1}100%{transform:translate3d(0,0,0) scale(0.5);opacity:0}}.notifications{position:absolute;left:0;top:0;width:100%;z-index:20000;color:#fff;font-size:14px;margin:0;border:none;display:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;max-height:100%;overflow:auto;-webkit-overflow-scrolling:touch;-webkit-transition-duration:450ms;transition-duration:450ms;background:rgba(0,0,0,.85);-webkit-perspective:1200px;perspective:1200px}.notifications.list-block>ul{border:none;background:0 0;margin:0}.with-statusbar-overlay .notifications{padding-top:20px;-webkit-transform:translate3d(0,-20px,0);-ms-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}.notifications .item-content{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.notifications .item-text,.notifications .item-subtitle,.notifications .item-title{font-size:14px}.notifications .item-title{font-weight:500}.notifications .item-text{height:auto;color:#d2d2d2;line-height:inherit}.notifications .item-text,.notifications .item-subtitle{font-weight:300}.notifications .item-inner{border-bottom-color:rgba(255,255,255,.2)}.notifications .item-media i.icon{width:20px;height:20px;-webkit-background-size:cover;background-size:cover;background-position:center;background-repeat:no-repeat}.notifications li.notification-item .item-media{padding-top:13px}.notifications .close-notification{width:19px;height:19px;background:url("data:image/svg+xml;charset=utf-8,") no-repeat center top;-webkit-background-size:100% auto;background-size:100% auto;position:relative}.notifications .close-notification span{position:absolute;width:44px;height:44px;left:50%;top:50%;margin-left:-22px;margin-top:-22px}.notifications .notification-item{max-width:568px;margin:0 auto;-webkit-transition-duration:450ms;transition-duration:450ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.notifications .notification-hidden{opacity:0;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.login-screen-content{background:#fff}.login-screen-content .login-screen-title,.login-screen-content .list-block,.login-screen-content .content-block,.login-screen-content .list-block-label{max-width:480px;margin:25px auto}.login-screen-content .list-block ul{border:none;background:0 0}.login-screen-content .list-block-label{text-align:center}.login-screen-title{text-align:center;font-size:30px}.disabled,[disabled]{opacity:.55;pointer-events:none}.disabled .disabled,.disabled [disabled],[disabled] .disabled,[disabled] [disabled]{opacity:1}.color-gray{color:#8e8e93}.list-block .item-link.list-button.color-gray,.tabbar a.active.color-gray,a.color-gray{color:#8e8e93}.label-switch input[type=checkbox]:checked+.checkbox.color-gray,.label-switch.color-gray input[type=checkbox]:checked+.checkbox{background-color:#8e8e93}.color-gray.button:not(.button-fill),.color-gray.buttons-row .button,.theme-gray .button:not(.button-fill){border-color:#8e8e93}html:not(.watch-active-state) .color-gray.button:not(.button-fill):active,html:not(.watch-active-state) .color-gray.buttons-row .button:active,html:not(.watch-active-state) .theme-gray .button:not(.button-fill):active,.color-gray.button:not(.button-fill).active-state,.color-gray.buttons-row .button.active-state,.theme-gray .button:not(.button-fill).active-state{background-color:rgba(142,142,147,.15)}.color-gray.button:not(.button-fill).active,.color-gray.buttons-row .button.active,.theme-gray .button:not(.button-fill).active{background-color:#8e8e93;color:#fff}.theme-gray .button.button-fill,.button.button-fill.color-gray{background:#8e8e93;color:#fff}.color-gray i.icon,.theme-gray i.icon,i.icon.color-gray,i.icon.theme-gray{color:#8e8e93}i.icon-next.color-gray,i.icon-next.theme-gray,.theme-gray i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-gray,i.icon-prev.theme-gray,.theme-gray i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-gray,i.icon-back.theme-gray,.theme-gray i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-gray,i.icon-bars.theme-gray,.theme-gray i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-gray a,.theme-gray .item-link.list-button{color:#8e8e93}.theme-gray .tabbar a,.tabbar.theme-gray a{color:inherit}.theme-gray .tabbar a.active,.tabbar.theme-gray a.active{color:#8e8e93}.theme-gray .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-gray input[type=range]::-webkit-slider-thumb:before{background-color:#8e8e93}.theme-gray label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-gray label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#8e8e93}.theme-gray label.label-radio input[type=checkbox]:checked~.item-inner,.theme-gray label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-gray .slider-pagination-active{background-color:#8e8e93}.bg-gray,.button.button-fill.bg-gray,a.bg-gray,.list-block .swipeout-actions-left a.bg-gray,.list-block .swipeout-actions-right a.bg-gray{background-color:#8e8e93}.border-gray{border-color:#8e8e93}.color-white{color:#fff}.list-block .item-link.list-button.color-white,.tabbar a.active.color-white,a.color-white{color:#fff}.label-switch input[type=checkbox]:checked+.checkbox.color-white,.label-switch.color-white input[type=checkbox]:checked+.checkbox{background-color:#fff}.color-white.button:not(.button-fill),.color-white.buttons-row .button,.theme-white .button:not(.button-fill){border-color:#fff}html:not(.watch-active-state) .color-white.button:not(.button-fill):active,html:not(.watch-active-state) .color-white.buttons-row .button:active,html:not(.watch-active-state) .theme-white .button:not(.button-fill):active,.color-white.button:not(.button-fill).active-state,.color-white.buttons-row .button.active-state,.theme-white .button:not(.button-fill).active-state{background-color:rgba(255,255,255,.15)}.color-white.button:not(.button-fill).active,.color-white.buttons-row .button.active,.theme-white .button:not(.button-fill).active{background-color:#fff;color:#fff}.theme-white .button.button-fill,.button.button-fill.color-white{background:#fff;color:#fff}.color-white i.icon,.theme-white i.icon,i.icon.color-white,i.icon.theme-white{color:#fff}i.icon-next.color-white,i.icon-next.theme-white,.theme-white i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-white,i.icon-prev.theme-white,.theme-white i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-white,i.icon-back.theme-white,.theme-white i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-white,i.icon-bars.theme-white,.theme-white i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-white a,.theme-white .item-link.list-button{color:#fff}.theme-white .tabbar a,.tabbar.theme-white a{color:inherit}.theme-white .tabbar a.active,.tabbar.theme-white a.active{color:#fff}.theme-white .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-white input[type=range]::-webkit-slider-thumb:before{background-color:#fff}.theme-white label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-white label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#fff}.theme-white label.label-radio input[type=checkbox]:checked~.item-inner,.theme-white label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-white .slider-pagination-active{background-color:#fff}.bg-white,.button.button-fill.bg-white,a.bg-white,.list-block .swipeout-actions-left a.bg-white,.list-block .swipeout-actions-right a.bg-white{background-color:#fff}.border-white{border-color:#fff}.color-black{color:#000}.list-block .item-link.list-button.color-black,.tabbar a.active.color-black,a.color-black{color:#000}.label-switch input[type=checkbox]:checked+.checkbox.color-black,.label-switch.color-black input[type=checkbox]:checked+.checkbox{background-color:#000}.color-black.button:not(.button-fill),.color-black.buttons-row .button,.theme-black .button:not(.button-fill){border-color:#000}html:not(.watch-active-state) .color-black.button:not(.button-fill):active,html:not(.watch-active-state) .color-black.buttons-row .button:active,html:not(.watch-active-state) .theme-black .button:not(.button-fill):active,.color-black.button:not(.button-fill).active-state,.color-black.buttons-row .button.active-state,.theme-black .button:not(.button-fill).active-state{background-color:rgba(0,0,0,.15)}.color-black.button:not(.button-fill).active,.color-black.buttons-row .button.active,.theme-black .button:not(.button-fill).active{background-color:#000;color:#fff}.theme-black .button.button-fill,.button.button-fill.color-black{background:#000;color:#fff}.color-black i.icon,.theme-black i.icon,i.icon.color-black,i.icon.theme-black{color:#000}i.icon-next.color-black,i.icon-next.theme-black,.theme-black i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-black,i.icon-prev.theme-black,.theme-black i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-black,i.icon-back.theme-black,.theme-black i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-black,i.icon-bars.theme-black,.theme-black i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-black a,.theme-black .item-link.list-button{color:#000}.theme-black .tabbar a,.tabbar.theme-black a{color:inherit}.theme-black .tabbar a.active,.tabbar.theme-black a.active{color:#000}.theme-black .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-black input[type=range]::-webkit-slider-thumb:before{background-color:#000}.theme-black label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-black label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#000}.theme-black label.label-radio input[type=checkbox]:checked~.item-inner,.theme-black label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-black .slider-pagination-active{background-color:#000}.bg-black,.button.button-fill.bg-black,a.bg-black,.list-block .swipeout-actions-left a.bg-black,.list-block .swipeout-actions-right a.bg-black{background-color:#000}.border-black{border-color:#000}.color-lightblue{color:#5ac8fa}.list-block .item-link.list-button.color-lightblue,.tabbar a.active.color-lightblue,a.color-lightblue{color:#5ac8fa}.label-switch input[type=checkbox]:checked+.checkbox.color-lightblue,.label-switch.color-lightblue input[type=checkbox]:checked+.checkbox{background-color:#5ac8fa}.color-lightblue.button:not(.button-fill),.color-lightblue.buttons-row .button,.theme-lightblue .button:not(.button-fill){border-color:#5ac8fa}html:not(.watch-active-state) .color-lightblue.button:not(.button-fill):active,html:not(.watch-active-state) .color-lightblue.buttons-row .button:active,html:not(.watch-active-state) .theme-lightblue .button:not(.button-fill):active,.color-lightblue.button:not(.button-fill).active-state,.color-lightblue.buttons-row .button.active-state,.theme-lightblue .button:not(.button-fill).active-state{background-color:rgba(90,200,250,.15)}.color-lightblue.button:not(.button-fill).active,.color-lightblue.buttons-row .button.active,.theme-lightblue .button:not(.button-fill).active{background-color:#5ac8fa;color:#fff}.theme-lightblue .button.button-fill,.button.button-fill.color-lightblue{background:#5ac8fa;color:#fff}.color-lightblue i.icon,.theme-lightblue i.icon,i.icon.color-lightblue,i.icon.theme-lightblue{color:#5ac8fa}i.icon-next.color-lightblue,i.icon-next.theme-lightblue,.theme-lightblue i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-lightblue,i.icon-prev.theme-lightblue,.theme-lightblue i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-lightblue,i.icon-back.theme-lightblue,.theme-lightblue i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-lightblue,i.icon-bars.theme-lightblue,.theme-lightblue i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-lightblue a,.theme-lightblue .item-link.list-button{color:#5ac8fa}.theme-lightblue .tabbar a,.tabbar.theme-lightblue a{color:inherit}.theme-lightblue .tabbar a.active,.tabbar.theme-lightblue a.active{color:#5ac8fa}.theme-lightblue .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-lightblue input[type=range]::-webkit-slider-thumb:before{background-color:#5ac8fa}.theme-lightblue label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-lightblue label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#5ac8fa}.theme-lightblue label.label-radio input[type=checkbox]:checked~.item-inner,.theme-lightblue label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-lightblue .slider-pagination-active{background-color:#5ac8fa}.bg-lightblue,.button.button-fill.bg-lightblue,a.bg-lightblue,.list-block .swipeout-actions-left a.bg-lightblue,.list-block .swipeout-actions-right a.bg-lightblue{background-color:#5ac8fa}.border-lightblue{border-color:#5ac8fa}.color-yellow{color:#fc0}.list-block .item-link.list-button.color-yellow,.tabbar a.active.color-yellow,a.color-yellow{color:#fc0}.label-switch input[type=checkbox]:checked+.checkbox.color-yellow,.label-switch.color-yellow input[type=checkbox]:checked+.checkbox{background-color:#fc0}.color-yellow.button:not(.button-fill),.color-yellow.buttons-row .button,.theme-yellow .button:not(.button-fill){border-color:#fc0}html:not(.watch-active-state) .color-yellow.button:not(.button-fill):active,html:not(.watch-active-state) .color-yellow.buttons-row .button:active,html:not(.watch-active-state) .theme-yellow .button:not(.button-fill):active,.color-yellow.button:not(.button-fill).active-state,.color-yellow.buttons-row .button.active-state,.theme-yellow .button:not(.button-fill).active-state{background-color:rgba(255,204,0,.15)}.color-yellow.button:not(.button-fill).active,.color-yellow.buttons-row .button.active,.theme-yellow .button:not(.button-fill).active{background-color:#fc0;color:#fff}.theme-yellow .button.button-fill,.button.button-fill.color-yellow{background:#fc0;color:#fff}.color-yellow i.icon,.theme-yellow i.icon,i.icon.color-yellow,i.icon.theme-yellow{color:#fc0}i.icon-next.color-yellow,i.icon-next.theme-yellow,.theme-yellow i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-yellow,i.icon-prev.theme-yellow,.theme-yellow i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-yellow,i.icon-back.theme-yellow,.theme-yellow i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-yellow,i.icon-bars.theme-yellow,.theme-yellow i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-yellow a,.theme-yellow .item-link.list-button{color:#fc0}.theme-yellow .tabbar a,.tabbar.theme-yellow a{color:inherit}.theme-yellow .tabbar a.active,.tabbar.theme-yellow a.active{color:#fc0}.theme-yellow .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-yellow input[type=range]::-webkit-slider-thumb:before{background-color:#fc0}.theme-yellow label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-yellow label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#fc0}.theme-yellow label.label-radio input[type=checkbox]:checked~.item-inner,.theme-yellow label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-yellow .slider-pagination-active{background-color:#fc0}.bg-yellow,.button.button-fill.bg-yellow,a.bg-yellow,.list-block .swipeout-actions-left a.bg-yellow,.list-block .swipeout-actions-right a.bg-yellow{background-color:#fc0}.border-yellow{border-color:#fc0}.color-orange{color:#ff9500}.list-block .item-link.list-button.color-orange,.tabbar a.active.color-orange,a.color-orange{color:#ff9500}.label-switch input[type=checkbox]:checked+.checkbox.color-orange,.label-switch.color-orange input[type=checkbox]:checked+.checkbox{background-color:#ff9500}.color-orange.button:not(.button-fill),.color-orange.buttons-row .button,.theme-orange .button:not(.button-fill){border-color:#ff9500}html:not(.watch-active-state) .color-orange.button:not(.button-fill):active,html:not(.watch-active-state) .color-orange.buttons-row .button:active,html:not(.watch-active-state) .theme-orange .button:not(.button-fill):active,.color-orange.button:not(.button-fill).active-state,.color-orange.buttons-row .button.active-state,.theme-orange .button:not(.button-fill).active-state{background-color:rgba(255,149,0,.15)}.color-orange.button:not(.button-fill).active,.color-orange.buttons-row .button.active,.theme-orange .button:not(.button-fill).active{background-color:#ff9500;color:#fff}.theme-orange .button.button-fill,.button.button-fill.color-orange{background:#ff9500;color:#fff}.color-orange i.icon,.theme-orange i.icon,i.icon.color-orange,i.icon.theme-orange{color:#ff9500}i.icon-next.color-orange,i.icon-next.theme-orange,.theme-orange i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-orange,i.icon-prev.theme-orange,.theme-orange i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-orange,i.icon-back.theme-orange,.theme-orange i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-orange,i.icon-bars.theme-orange,.theme-orange i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-orange a,.theme-orange .item-link.list-button{color:#ff9500}.theme-orange .tabbar a,.tabbar.theme-orange a{color:inherit}.theme-orange .tabbar a.active,.tabbar.theme-orange a.active{color:#ff9500}.theme-orange .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-orange input[type=range]::-webkit-slider-thumb:before{background-color:#ff9500}.theme-orange label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-orange label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#ff9500}.theme-orange label.label-radio input[type=checkbox]:checked~.item-inner,.theme-orange label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-orange .slider-pagination-active{background-color:#ff9500}.bg-orange,.button.button-fill.bg-orange,a.bg-orange,.list-block .swipeout-actions-left a.bg-orange,.list-block .swipeout-actions-right a.bg-orange{background-color:#ff9500}.border-orange{border-color:#ff9500}.color-pink{color:#ff2d55}.list-block .item-link.list-button.color-pink,.tabbar a.active.color-pink,a.color-pink{color:#ff2d55}.label-switch input[type=checkbox]:checked+.checkbox.color-pink,.label-switch.color-pink input[type=checkbox]:checked+.checkbox{background-color:#ff2d55}.color-pink.button:not(.button-fill),.color-pink.buttons-row .button,.theme-pink .button:not(.button-fill){border-color:#ff2d55}html:not(.watch-active-state) .color-pink.button:not(.button-fill):active,html:not(.watch-active-state) .color-pink.buttons-row .button:active,html:not(.watch-active-state) .theme-pink .button:not(.button-fill):active,.color-pink.button:not(.button-fill).active-state,.color-pink.buttons-row .button.active-state,.theme-pink .button:not(.button-fill).active-state{background-color:rgba(255,45,85,.15)}.color-pink.button:not(.button-fill).active,.color-pink.buttons-row .button.active,.theme-pink .button:not(.button-fill).active{background-color:#ff2d55;color:#fff}.theme-pink .button.button-fill,.button.button-fill.color-pink{background:#ff2d55;color:#fff}.color-pink i.icon,.theme-pink i.icon,i.icon.color-pink,i.icon.theme-pink{color:#ff2d55}i.icon-next.color-pink,i.icon-next.theme-pink,.theme-pink i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-pink,i.icon-prev.theme-pink,.theme-pink i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-pink,i.icon-back.theme-pink,.theme-pink i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-pink,i.icon-bars.theme-pink,.theme-pink i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-pink a,.theme-pink .item-link.list-button{color:#ff2d55}.theme-pink .tabbar a,.tabbar.theme-pink a{color:inherit}.theme-pink .tabbar a.active,.tabbar.theme-pink a.active{color:#ff2d55}.theme-pink .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-pink input[type=range]::-webkit-slider-thumb:before{background-color:#ff2d55}.theme-pink label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-pink label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#ff2d55}.theme-pink label.label-radio input[type=checkbox]:checked~.item-inner,.theme-pink label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-pink .slider-pagination-active{background-color:#ff2d55}.bg-pink,.button.button-fill.bg-pink,a.bg-pink,.list-block .swipeout-actions-left a.bg-pink,.list-block .swipeout-actions-right a.bg-pink{background-color:#ff2d55}.border-pink{border-color:#ff2d55}.color-blue{color:#007aff}.list-block .item-link.list-button.color-blue,.tabbar a.active.color-blue,a.color-blue{color:#007aff}.label-switch input[type=checkbox]:checked+.checkbox.color-blue,.label-switch.color-blue input[type=checkbox]:checked+.checkbox{background-color:#007aff}.color-blue.button:not(.button-fill),.color-blue.buttons-row .button,.theme-blue .button:not(.button-fill){border-color:#007aff}html:not(.watch-active-state) .color-blue.button:not(.button-fill):active,html:not(.watch-active-state) .color-blue.buttons-row .button:active,html:not(.watch-active-state) .theme-blue .button:not(.button-fill):active,.color-blue.button:not(.button-fill).active-state,.color-blue.buttons-row .button.active-state,.theme-blue .button:not(.button-fill).active-state{background-color:rgba(0,122,255,.15)}.color-blue.button:not(.button-fill).active,.color-blue.buttons-row .button.active,.theme-blue .button:not(.button-fill).active{background-color:#007aff;color:#fff}.theme-blue .button.button-fill,.button.button-fill.color-blue{background:#007aff;color:#fff}.color-blue i.icon,.theme-blue i.icon,i.icon.color-blue,i.icon.theme-blue{color:#007aff}i.icon-next.color-blue,i.icon-next.theme-blue,.theme-blue i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-blue,i.icon-prev.theme-blue,.theme-blue i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-blue,i.icon-back.theme-blue,.theme-blue i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-blue,i.icon-bars.theme-blue,.theme-blue i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-blue a,.theme-blue .item-link.list-button{color:#007aff}.theme-blue .tabbar a,.tabbar.theme-blue a{color:inherit}.theme-blue .tabbar a.active,.tabbar.theme-blue a.active{color:#007aff}.theme-blue .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-blue input[type=range]::-webkit-slider-thumb:before{background-color:#007aff}.theme-blue label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-blue label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#007aff}.theme-blue label.label-radio input[type=checkbox]:checked~.item-inner,.theme-blue label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-blue .slider-pagination-active{background-color:#007aff}.bg-blue,.button.button-fill.bg-blue,a.bg-blue,.list-block .swipeout-actions-left a.bg-blue,.list-block .swipeout-actions-right a.bg-blue{background-color:#007aff}.border-blue{border-color:#007aff}.color-green{color:#4cd964}.list-block .item-link.list-button.color-green,.tabbar a.active.color-green,a.color-green{color:#4cd964}.label-switch input[type=checkbox]:checked+.checkbox.color-green,.label-switch.color-green input[type=checkbox]:checked+.checkbox{background-color:#4cd964}.color-green.button:not(.button-fill),.color-green.buttons-row .button,.theme-green .button:not(.button-fill){border-color:#4cd964}html:not(.watch-active-state) .color-green.button:not(.button-fill):active,html:not(.watch-active-state) .color-green.buttons-row .button:active,html:not(.watch-active-state) .theme-green .button:not(.button-fill):active,.color-green.button:not(.button-fill).active-state,.color-green.buttons-row .button.active-state,.theme-green .button:not(.button-fill).active-state{background-color:rgba(76,217,100,.15)}.color-green.button:not(.button-fill).active,.color-green.buttons-row .button.active,.theme-green .button:not(.button-fill).active{background-color:#4cd964;color:#fff}.theme-green .button.button-fill,.button.button-fill.color-green{background:#4cd964;color:#fff}.color-green i.icon,.theme-green i.icon,i.icon.color-green,i.icon.theme-green{color:#4cd964}i.icon-next.color-green,i.icon-next.theme-green,.theme-green i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-green,i.icon-prev.theme-green,.theme-green i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-green,i.icon-back.theme-green,.theme-green i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-green,i.icon-bars.theme-green,.theme-green i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-green a,.theme-green .item-link.list-button{color:#4cd964}.theme-green .tabbar a,.tabbar.theme-green a{color:inherit}.theme-green .tabbar a.active,.tabbar.theme-green a.active{color:#4cd964}.theme-green .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-green input[type=range]::-webkit-slider-thumb:before{background-color:#4cd964}.theme-green label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-green label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#4cd964}.theme-green label.label-radio input[type=checkbox]:checked~.item-inner,.theme-green label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-green .slider-pagination-active{background-color:#4cd964}.bg-green,.button.button-fill.bg-green,a.bg-green,.list-block .swipeout-actions-left a.bg-green,.list-block .swipeout-actions-right a.bg-green{background-color:#4cd964}.border-green{border-color:#4cd964}.color-red{color:#ff3b30}.list-block .item-link.list-button.color-red,.tabbar a.active.color-red,a.color-red{color:#ff3b30}.label-switch input[type=checkbox]:checked+.checkbox.color-red,.label-switch.color-red input[type=checkbox]:checked+.checkbox{background-color:#ff3b30}.color-red.button:not(.button-fill),.color-red.buttons-row .button,.theme-red .button:not(.button-fill){border-color:#ff3b30}html:not(.watch-active-state) .color-red.button:not(.button-fill):active,html:not(.watch-active-state) .color-red.buttons-row .button:active,html:not(.watch-active-state) .theme-red .button:not(.button-fill):active,.color-red.button:not(.button-fill).active-state,.color-red.buttons-row .button.active-state,.theme-red .button:not(.button-fill).active-state{background-color:rgba(255,59,48,.15)}.color-red.button:not(.button-fill).active,.color-red.buttons-row .button.active,.theme-red .button:not(.button-fill).active{background-color:#ff3b30;color:#fff}.theme-red .button.button-fill,.button.button-fill.color-red{background:#ff3b30;color:#fff}.color-red i.icon,.theme-red i.icon,i.icon.color-red,i.icon.theme-red{color:#ff3b30}i.icon-next.color-red,i.icon-next.theme-red,.theme-red i.icon-next{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-prev.color-red,i.icon-prev.theme-red,.theme-red i.icon-prev{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-back.color-red,i.icon-back.theme-red,.theme-red i.icon-back{background-image:url("data:image/svg+xml;charset=utf-8,")}i.icon-bars.color-red,i.icon-bars.theme-red,.theme-red i.icon-bars{background-image:url("data:image/svg+xml;charset=utf-8,")}.theme-red a,.theme-red .item-link.list-button{color:#ff3b30}.theme-red .tabbar a,.tabbar.theme-red a{color:inherit}.theme-red .tabbar a.active,.tabbar.theme-red a.active{color:#ff3b30}.theme-red .range-slider input[type=range]::-webkit-slider-thumb:before,.range-slider.theme-red input[type=range]::-webkit-slider-thumb:before{background-color:#ff3b30}.theme-red label.label-checkbox input[type=checkbox]:checked+.item-media i.icon-form-checkbox,.theme-red label.label-checkbox input[type=radio]:checked+.item-media i.icon-form-checkbox{background-color:#ff3b30}.theme-red label.label-radio input[type=checkbox]:checked~.item-inner,.theme-red label.label-radio input[type=radio]:checked~.item-inner{background-image:url("data:image/svg+xml;charset=utf-8, ")}.theme-red .slider-pagination-active{background-color:#ff3b30}.bg-red,.button.button-fill.bg-red,a.bg-red,.list-block .swipeout-actions-left a.bg-red,.list-block .swipeout-actions-right a.bg-red{background-color:#ff3b30}.border-red{border-color:#ff3b30} \ No newline at end of file diff --git a/examples/raspberry_pi_mjpeg_led/web_root/framework7.min.js b/examples/raspberry_pi_mjpeg_led/web_root/framework7.min.js new file mode 100755 index 00000000..adf2042e --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/web_root/framework7.min.js @@ -0,0 +1,18 @@ +/* + * Framework7 0.9.6 + * Full Featured HTML Framework For Building iOS 7 Apps + * + * http://www.idangero.us/framework7 + * + * Copyright 2014, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: September 13, 2014 +*/ +!function(){"use strict";window.Framework7=function(b){function c(a){var b=a.replace(/^./,function(a){return a.toUpperCase()});l["onPage"+b]=function(b,c){return l.onPage(a,b,c)}}function d(a,b,c){b=n(b);var d=b.find(a);return d.length>1&&("string"==typeof c.selector&&(d=b.find(c.selector+" "+a)),d.length>1&&(d=b.find("."+l.params.viewMainClass+" "+a))),1===d.length?d:void 0}function e(a,b,c){"to-left"===c&&(a.removeClass("page-on-center").addClass("page-from-center-to-left"),b.addClass("page-from-right-to-center")),"to-right"===c&&(a.removeClass("page-on-left").addClass("page-from-left-to-center"),b.removeClass("page-on-center").addClass("page-from-center-to-right"))}function f(a,b,c){"to-left"===c&&(b.removeClass("navbar-on-right").addClass("navbar-from-right-to-center"),b.find(".sliding").each(function(){var a=n(this);a.transform("translate3d(0px,0,0)"),l.params.animateNavBackIcon&&a.hasClass("left")&&a.find(".back .icon").length>0&&a.find(".back .icon").transform("translate3d(0px,0,0)")}),a.removeClass("navbar-on-center").addClass("navbar-from-center-to-left"),a.find(".sliding").each(function(){var a=n(this);l.params.animateNavBackIcon&&(a.hasClass("center")&&b.find(".sliding.left .back .icon").length>0&&(this.f7NavbarLeftOffset+=b.find(".sliding.left .back span")[0].offsetLeft),a.hasClass("left")&&a.find(".back .icon").length>0&&a.find(".back .icon").transform("translate3d("+-this.f7NavbarLeftOffset+"px,0,0)")),a.transform("translate3d("+this.f7NavbarLeftOffset+"px,0,0)")})),"to-right"===c&&(a.removeClass("navbar-on-left").addClass("navbar-from-left-to-center"),a.find(".sliding").each(function(){var a=n(this);a.transform("translate3d(0px,0,0)"),l.params.animateNavBackIcon&&a.hasClass("left")&&a.find(".back .icon").length>0&&a.find(".back .icon").transform("translate3d(0px,0,0)")}),b.removeClass("navbar-on-center").addClass("navbar-from-center-to-right"),b.find(".sliding").each(function(){var a=n(this);l.params.animateNavBackIcon&&a.hasClass("left")&&a.find(".back .icon").length>0&&a.find(".back .icon").transform("translate3d("+-this.f7NavbarRightOffset+"px,0,0)"),a.transform("translate3d("+this.f7NavbarRightOffset+"px,0,0)")}))}function g(a,b,c,e){var f,g,h,i,j,k,m,o,p=n(a.container),q=n(a.pagesContainer);if(l.pluginHook("loadPage",a,b,c),l._tempDomElement.innerHTML="",b||"string"==typeof c)l._tempDomElement.innerHTML=c;else if("length"in c&&c.length>1)for(var r=0;r1)for(var v=0;v1){for(m=0;m0)){for(m=0;m0&&a.find(".back .icon").transform("translate3d("+-this.f7NavbarRightOffset+"px,0,0)")});i[0].clientLeft;l.pageAnimCallbacks("before",a,{pageContainer:i[0],url:b,position:"right",oldPage:j,newPage:i}),u?(e(j,i,"to-left",a),r&&setTimeout(function(){f(o,p,"to-left",a)},0),i.animationEnd(function(){h()})):h()}function i(a,b,c){l.pluginHook("preprocess",a,b,c),a=l.pluginProcess("preprocess",a),l.params.preprocess?(a=l.params.preprocess(a,b,c),"undefined"!=typeof a&&c(a)):c(a)}function j(){var a=this,b=a.scrollTop,c=a.scrollHeight,d=a.offsetHeight,e=a.getAttribute("data-distance");e||(e=50),"string"==typeof e&&e.indexOf("%")>=0&&(e=parseInt(e,10)/100*d),e>d&&(e=d),b+d>=c-e&&n(a).trigger("infinite")}function k(){l.device.ipad&&(document.body.scrollLeft=0,setTimeout(function(){document.body.scrollLeft=0},0))}var l=this;l.version="0.9.6",l.params={cache:!0,cacheIgnore:[],cacheIgnoreGetParameters:!1,cacheDuration:6e5,preloadPreviousPage:!0,uniqueHistory:!1,pushState:!1,pushStateRoot:void 0,pushStateNoAnimation:!1,pushStateSeparator:"#!/",fastClicks:!0,fastClicksDistanceThreshold:0,activeState:!0,activeStateElements:"a, button, label, span",animateNavBackIcon:!1,swipeBackPage:!0,swipeBackPageThreshold:0,swipeBackPageActiveArea:30,swipeBackPageBoxShadow:!0,ajaxLinks:void 0,externalLinks:["external"],sortable:!0,swipeout:!0,swipeoutNoFollow:!1,smartSelectBackTemplate:'',smartSelectBackText:"Back",smartSelectSearchbar:!1,smartSelectBackOnSelect:!1,searchbarHideDividers:!0,searchbarHideGroups:!0,swipePanel:!1,swipePanelActiveArea:0,swipePanelCloseOpposite:!0,swipePanelNoFollow:!1,swipePanelThreshold:0,panelsCloseByOutside:!0,modalButtonOk:"OK",modalButtonCancel:"Cancel",modalUsernamePlaceholder:"Username",modalPasswordPlaceholder:"Password",modalTitle:"Framework7",modalCloseByOutside:!1,actionsCloseByOutside:!0,popupCloseByOutside:!0,modalPreloaderTitle:"Loading... ",init:!0,viewClass:"view",viewMainClass:"view-main",viewsClass:"views",notificationCloseOnClick:!1,notificationCloseIcon:!0,animatePages:!0};for(var m in b)l.params[m]=b[m];var n=a,o=Template7;l._compiledTemplates={},l.touchEvents={start:l.support.touch?"touchstart":"mousedown",move:l.support.touch?"touchmove":"mousemove",end:l.support.touch?"touchend":"mouseup"},l.ls=localStorage,l.rtl="rtl"===n("body").css("direction"),l.rtl&&n("html").attr("dir","rtl"),"undefined"!=typeof l.params.statusbarOverlay&&(l.params.statusbarOverlay?n("html").addClass("with-statusbar-overlay"):n("html").removeClass("with-statusbar-overlay")),l.globalEventListeners={},l.initGlobalEventListeners=function(){function a(a){var b;n(document).on(a,function(c){for(b=0;b0;return("string"==typeof b||b.nodeType||"length"in b)&&(b=d?{content:b}:{url:b}),c.indexOf("reload")>=0&&(b.reload=!0,c.indexOf("previous")>=0&&(b.reloadPrevious=!0)),c.indexOf("refresh")>=0&&(b.url=c.indexOf("previous")>=0?f.history[f.history.length-2]:f.url,b.reload=!0,b.ignoreCache=!0,c.indexOf("previous")>=0&&(b.reloadPrevious=!0)),l.loadPage(f,b)}}var d={dynamicNavbar:!1,domCache:!1,linksView:void 0,uniqueHistory:l.params.uniqueHistory,swipeBackPage:l.params.swipeBackPage,swipeBackPageBoxShadow:l.params.swipeBackPageBoxShadow,swipeBackPageActiveArea:l.params.swipeBackPageActiveArea,swipeBackPageThreshold:l.params.swipeBackPageThreshold,animatePages:l.params.animatePages,preloadPreviousPage:l.params.preloadPreviousPage};b=b||{};for(var e in d)"undefined"==typeof b[e]&&(b[e]=d[e]);var f=this;f.params=b,f.selector=a;var g=n(a);f.container=g[0];var h=document.location.href;f.history=[];var i=h,j=l.params.pushStateSeparator,k=l.params.pushStateRoot;if(l.params.pushState&&(k?i=k:i.indexOf(j)>=0&&i.indexOf(j+"#")<0&&(i=i.split(j)[0])),f.url=g.attr("data-url")||f.params.url||i,f.url&&f.history.push(f.url),f.contentCache={},g[0].f7View=f,f.pagesContainer=g.find(".pages")[0],f.allowPageChange=!0,!f.activePage){var m,o=n(f.pagesContainer).find(".page-on-center");0===o.length&&(o=n(f.pagesContainer).find(".page"),o=o.eq(o.length-1)),o.length>0&&(m=o[0].f7PageData),m&&(m.view=f,f.url&&(m.url=f.url),f.activePage=m,o[0].f7PageData=m)}f.main=g.hasClass(l.params.viewMainClass);var p,q,r,s,t,u,v,w,x,y,z,A,B,C,D=!1,E=!1,F={},G=!0;f.handleTouchStart=function(a){G&&f.params.swipeBackPage&&!D&&!l.swipeoutOpenedEl&&(E=!1,D=!0,p=void 0,F.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,F.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY,u=(new Date).getTime(),B=f.params.dynamicNavbar&&g.find(".navbar-inner").length>1)},f.handleTouchMove=function(a){if(D){var b="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,c="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY;if("undefined"==typeof p&&(p=!!(p||Math.abs(c-F.y)>Math.abs(b-F.x))),p||a.f7PreventSwipeBack||l.preventSwipeBack)return void(D=!1);if(!E){var d=!1;s=g.width();var e=n(a.target),h=e.hasClass("swipeout")?e:e.parents(".swipeout");h.length>0&&(!l.rtl&&h.find(".swipeout-actions-left").length>0&&(d=!0),l.rtl&&h.find(".swipeout-actions-right").length>0&&(d=!0)),q=e.is(".page")?e:e.parents(".page"),q.hasClass("no-swipeback")&&(d=!0),r=g.find(".page-on-left:not(.cached)");var i=F.x-g.offset().left>f.params.swipeBackPageActiveArea;if(i=l.rtl?F.xf.params.swipeBackPageActiveArea,i&&(d=!0),(0===r.length||0===q.length)&&(d=!0),d)return void(D=!1);B&&(v=g.find(".navbar-on-center:not(.cached)"),w=g.find(".navbar-on-left:not(.cached)"),x=v.find(".left, .center, .right"),y=w.find(".left, .center, .right"),l.params.animateNavBackIcon&&(z=v.find(".left.sliding .back .icon"),A=w.find(".left.sliding .back .icon")))}a.f7PreventPanelSwipe=!0,E=!0,a.preventDefault();var j=l.rtl?-1:1;t=(b-F.x-f.params.swipeBackPageThreshold)*j,0>t&&(t=0);var k=t/s,m={percentage:k,activePage:q[0],previousPage:r[0],activeNavbar:v[0],previousNavbar:w[0]};f.params.onSwipeBackMove&&f.params.onSwipeBackMove(m),g.trigger("swipebackmove",m);var o=t*j,u=(t/5-s/5)*j;if(1===l.device.pixelRatio&&(o=Math.round(o),u=Math.round(u)),q.transform("translate3d("+o+"px,0,0)"),f.params.swipeBackPageBoxShadow&&"android"!==l.device.os&&(q[0].style.boxShadow="0px 0px 12px rgba(0,0,0,"+(.5-.5*k)+")"),r.transform("translate3d("+u+"px,0,0)"),r[0].style.opacity=.9+.1*k,B){var G;for(G=0;G=0){var H=k*C[0].f7NavbarRightOffset;1===l.device.pixelRatio&&(H=Math.round(H)),C.transform("translate3d("+H+"px,0,0)"),l.params.animateNavBackIcon&&C[0].className.indexOf("left")>=0&&z.length>0&&z.transform("translate3d("+-H+"px,0,0)")}for(G=0;G=0){var I=C[0].f7NavbarLeftOffset*(1-k);1===l.device.pixelRatio&&(I=Math.round(I)),C.transform("translate3d("+I+"px,0,0)"),l.params.animateNavBackIcon&&C[0].className.indexOf("left")>=0&&A.length>0&&A.transform("translate3d("+-I+"px,0,0)")}}}},f.handleTouchEnd=function(){if(!D||!E)return D=!1,void(E=!1);if(D=!1,E=!1,0===t)return n([q[0],r[0]]).transform("").css({opacity:"",boxShadow:""}),void(B&&(x.transform("").css({opacity:""}),y.transform("").css({opacity:""}),z&&z.length>0&&z.transform(""),A&&z.length>0&&A.transform("")));var a=(new Date).getTime()-u,b=!1;if((300>a&&t>10||a>=300&&t>s/2)&&(q.removeClass("page-on-center").addClass("page-on-right"),r.removeClass("page-on-left").addClass("page-on-center"),B&&(v.removeClass("navbar-on-center").addClass("navbar-on-right"),w.removeClass("navbar-on-left").addClass("navbar-on-center")),b=!0),n([q[0],r[0]]).transform("").css({opacity:"",boxShadow:""}).addClass("page-transitioning"),B&&(x.css({opacity:""}).each(function(){var a=b?this.f7NavbarRightOffset:0,c=n(this);c.transform("translate3d("+a+"px,0,0)"),l.params.animateNavBackIcon&&c.hasClass("left")&&z.length>0&&z.addClass("page-transitioning").transform("translate3d("+-a+"px,0,0)")}).addClass("page-transitioning"),y.transform("").css({opacity:""}).each(function(){var a=b?0:this.f7NavbarLeftOffset,c=n(this);c.transform("translate3d("+a+"px,0,0)"),l.params.animateNavBackIcon&&c.hasClass("left")&&A.length>0&&A.addClass("page-transitioning").transform("translate3d("+-a+"px,0,0)")}).addClass("page-transitioning")),G=!1,f.allowPageChange=!1,b){var c=f.history[f.history.length-2];f.url=c,l.pageAnimCallbacks("before",f,{pageContainer:r[0],url:c,position:"left",newPage:r,oldPage:q,swipeBack:!0})}q.transitionEnd(function(){n([q[0],r[0]]).removeClass("page-transitioning"),B&&(x.removeClass("page-transitioning").css({opacity:""}),y.removeClass("page-transitioning").css({opacity:""}),z&&z.length>0&&z.removeClass("page-transitioning"),A&&A.length>0&&A.removeClass("page-transitioning")),G=!0,f.allowPageChange=!0,b&&(l.params.pushState&&history.back(),l.pageAnimCallbacks("after",f,{pageContainer:r[0],url:c,position:"left",newPage:r,oldPage:q,swipeBack:!0}),l.afterGoBack(f,q,r))})},f.attachEvents=function(a){var b=a?"off":"on";g[b](l.touchEvents.start,f.handleTouchStart),g[b](l.touchEvents.move,f.handleTouchMove),g[b](l.touchEvents.end,f.handleTouchEnd)},f.detachEvents=function(){f.attachEvents(!0)},f.params.swipeBackPage&&f.attachEvents(),l.views.push(f),f.main&&(l.mainView=f);for(var H="loadPage loadContent reloadPage reloadContent reloadPreviousPage reloadPreviousContent refreshPage refreshPreviousPage".split(" "),I=0;I=0&&h.indexOf(j+"#")<0&&(J=h.split(j)[1]);var K=l.params.pushStateNoAnimation?!1:void 0;J&&l.loadPage(f,{url:J,animatePages:K,pushState:!1})}return f.destroy=function(){f.detachEvents(),f=void 0},l.pluginHook("addView",f),f};l.addView=function(a,b){return new p(a,b)},l.navbarInitCallback=function(a,b,c,d,e,f){var g={container:c,innerContainer:d},h={url:e,query:n.parseUrlQuery(e||""),container:b,name:n(b).attr("data-page"),view:a,from:f},i={navbar:g,page:h};l.pluginHook("navbarInit",g,h),n(d).trigger("navbarInit",i)},l.sizeNavbars=function(a){var b=a?n(a).find(".navbar .navbar-inner:not(.cached)"):n(".navbar .navbar-inner:not(.cached)");b.each(function(){var a,b,c=n(this),d=c.find(l.rtl?".right":".left"),e=c.find(l.rtl?".left":".right"),f=c.find(".center"),g=0===d.length,h=0===e.length,i=g?0:d.outerWidth(!0),j=h?0:e.outerWidth(!0),k=f.outerWidth(!0),m=c.width(),o=c.hasClass("navbar-on-left");h&&(a=m-k),g&&(a=0),g||h||(a=(m-j-k+i)/2);var p=(m-k)/2;m-i-j>k?(i>p&&(p=i),p+k>m-j&&(p=m-j-k),b=p-a):b=0;var q=l.rtl?-1:1,r=b;l.rtl&&g&&h&&f.length>0&&(r=-r),f.css({left:r+"px"}),f.hasClass("sliding")&&(f[0].f7NavbarLeftOffset=-(a+b)*q,f[0].f7NavbarRightOffset=(m-a-b-k)*q,o&&f.transform("translate3d("+f[0].f7NavbarLeftOffset+"px, 0, 0)")),!g&&d.hasClass("sliding")&&(l.rtl?(d[0].f7NavbarLeftOffset=-(m-d.outerWidth())/2*q,d[0].f7NavbarRightOffset=i*q):(d[0].f7NavbarLeftOffset=-i,d[0].f7NavbarRightOffset=(m-d.outerWidth())/2),o&&d.transform("translate3d("+d[0].f7NavbarLeftOffset+"px, 0, 0)")),!h&&e.hasClass("sliding")&&(l.rtl?(e[0].f7NavbarLeftOffset=-j*q,e[0].f7NavbarRightOffset=(m-e.outerWidth())/2*q):(e[0].f7NavbarLeftOffset=-(m-e.outerWidth())/2,e[0].f7NavbarRightOffset=j),o&&e.transform("translate3d("+e[0].f7NavbarLeftOffset+"px, 0, 0)"))})},l.hideNavbar=function(a){return n(a).addClass("hidden-navbar"),!0},l.showNavbar=function(a){var b=n(a);return b.addClass("hiding-navbar").removeClass("hidden-navbar").find(".navbar").transitionEnd(function(){b.removeClass("hiding-navbar")}),!0},l.hideToolbar=function(a){return n(a).addClass("hidden-toolbar"),!0},l.showToolbar=function(a){var b=n(a);b.addClass("hiding-toolbar").removeClass("hidden-toolbar").find(".toolbar").transitionEnd(function(){b.removeClass("hiding-toolbar")})},l.initSearchbar=function(a){function b(){o.val("").trigger("change"),k.removeClass("searchbar-active searchbar-not-empty"),q.length>0&&q.css(w,-v+"px"),r&&m.removeClass("searchbar-overlay-active"),l.device.ios?setTimeout(function(){o.blur()},400):o.blur()}function c(){l.device.ios?setTimeout(function(){r&&!k.hasClass("searchbar-active")&&m.addClass("searchbar-overlay-active"),k.addClass("searchbar-active"),q.length>0&&q.css(w,"0px"),r.trigger("enableSearch")},400):(r&&!k.hasClass("searchbar-active")&&m.addClass("searchbar-overlay-active"),k.addClass("searchbar-active"),q.length>0&&q.css(w,"0px"),r.trigger("disableSearch"))}function d(){o.val("").trigger("change"),r.trigger("clearSearch")}function e(){setTimeout(function(){var a=o.val().trim();0===a.length?(k.removeClass("searchbar-not-empty"),r&&k.hasClass("searchbar-active")&&m.addClass("searchbar-overlay-active")):(k.addClass("searchbar-not-empty"),r&&k.hasClass("searchbar-active")&&m.removeClass("searchbar-overlay-active")),r.length>0&&s&&i(a)},0)}function f(a){a.preventDefault()}function g(a){var g=a?"off":"on";k[g]("submit",f),q[g]("click",b),m[g]("click",b),o[g]("focus",c),o[g]("change keydown keypress keyup",e),p[g]("click",d)}function h(){g(!0)}function i(a){var b=a.trim().toLowerCase().split(" ");r.find("li").removeClass("hidden-by-searchbar");var c=[];r.find("li").each(function(a,d){d=n(d);var e=d.find(s);if(0!==e.length){var f;f=e.text().trim().toLowerCase();for(var g=0,h=0;h=0&&g++;g!==b.length?d.addClass("hidden-by-searchbar"):c.push(d[0])}}),l.params.searchbarHideDividers&&r.find(".item-divider, .list-group-title").each(function(){for(var a=n(this),b=a.nextAll("li"),c=!0,d=0;d0&&(v=q.width(),q.css(w,-v+"px")),k[0].f7DestroySearchbar=h,g(),a.hasClass("page")&&a.on("pageBeforeRemove",j)}},l.destroySearchbar=function(a){a=n(a);var b=a.hasClass("searchbar")?a:a.find(".searchbar");0!==b.length&&b[0].f7DestroySearchbar&&b[0].f7DestroySearchbar()},l.initMessagebar=function(a){function b(a){a.preventDefault()}function c(){j.css({height:""});var a=j[0].offsetHeight,b=a-j[0].clientHeight,c=j[0].scrollHeight;if(c+b>a){var d=c+b,e=l+(d-m),f=h.attr("data-max-height")||h.parents(".view")[0].offsetHeight-88;e>f&&(e=f,d=e-l+m),j.css("height",d+"px"),h.css("height",e+"px"),k.length>0&&(k.css("padding-bottom",e+"px"),k.scrollTop(k[0].scrollHeight-k[0].offsetHeight))}else k.length>0&&(h.css({height:""}),k.css({"padding-bottom":""}))}function d(){clearTimeout(i),i=setTimeout(function(){c()},0)}function e(a){var c=a?"off":"on";h[c]("submit",b),j[c]("change keydown keypress keyup paste cut",d)}function f(){e(!0)}function g(){f(),a.off("pageBeforeRemove",g)}a=n(a);var h=a.hasClass("messagebar")?a:a.find(".messagebar");if(0!==h.length){var i,j=h.find("textarea"),k=h.parents(".page").find(".page-content"),l=h[0].offsetHeight,m=j[0].offsetHeight;h[0].f7DestroyMessagebar=f,e(),a.hasClass("page")&&a.on("pageBeforeRemove",g)}},l.destroyMessagebar=function(a){a=n(a);var b=a.hasClass("messagebar")?a:a.find(".messagebar");0!==b.length&&b[0].f7DestroyMessagebar&&b[0].f7DestroyMessagebar()},l.cache=[],l.removeFromCache=function(a){for(var b=!1,c=0;c=0&&(e=a.split("?")[0]),l.params.cache&&!c&&a.indexOf("nocache")<0&&l.params.cacheIgnore.indexOf(e)<0)for(var f=0;f1){for(var d=b.split(" "),e=[],f=0;f0?"navbar-on-left":"navbar-on-center"),s.length>1&&(n(s[0]).remove(),s=u.find(".navbar-inner")),u.prepend(t[0])),x.prepend(r[0]),l.pageInitCallback(a,r[0],h,"left",v?t[0]:void 0),v&&l.navbarInitCallback(a,r[0],u[0],t[0],h,"right"),v&&t.hasClass("navbar-on-left")&&j&&t.find(".sliding").each(function(){var a=n(this);l.params.animateNavBackIcon&&(a.hasClass("left")&&a.find(".back .icon").length>0&&a.find(".back .icon").transform("translate3d("+-this.f7NavbarLeftOffset+"px,0,0)"),a.hasClass("center")&&s.find(".left .back .icon ~ span").length>0&&(this.f7NavbarLeftOffset+=s.find(".left .back span")[0].offsetLeft)),a.transform("translate3d("+this.f7NavbarLeftOffset+"px,0,0)")}),k)return r.addClass("page-on-left"),void(a.allowPageChange=!0);a.url=h;r[0].clientLeft;c()}if(!a.allowPageChange)return!1;var h=b.url,j=b.animatePages,k=b.preloadOnly,m=b.pushState,o=b.ignoreCache,p=b.forceUrl;a.allowPageChange=!1,l.xhr&&a.xhr&&a.xhr===l.xhr&&(l.xhr.abort(),l.xhr=!1),l.pluginHook("goBack",a,h,k),l.params.pushState&&("undefined"==typeof m&&(m=!0),!k&&history.state&&m&&history.back());var q,r,s,t,u,v,w=n(a.container),x=n(a.pagesContainer),y=x.children(".page");if("undefined"==typeof j&&(j=a.params.animatePages),y.length>1&&!p){if(k)return void(a.allowPageChange=!0);if(a.url=a.history[a.history.length-2],r=n(y[y.length-2]),q=n(y[y.length-1]),a.params.dynamicNavbar){v=!0;var z=w.find(".navbar-inner:not(.cached)");t=n(z[0]),s=n(z[1])}c()}else{if(y.length>1&&p&&(l.pageRemoveCallback(a,y[y.length-2],"left"),n(y[y.length-2]).remove(),a.params.dynamicNavbar&&w.find(".navbar-inner:not(.cached)").eq(0).remove(),y=x.children(".page")),h&&0===h.indexOf("#")&&(h=void 0),(p&&!h||!p)&&(h=a.history[a.history.length-2]),!h)return void(a.allowPageChange=!0);if(p&&a.history.indexOf(h)&&(a.history=a.history.slice(0,a.history.indexOf(h)+2)),!a.params.domCache&&h in a.contentCache){var A=a.contentCache[h];return l._tempDomElement.innerHTML="",n(l._tempDomElement).append(A),void g()}l.get(h,a,o,function(b,c){return c?void(a.allowPageChange=!0):void i(b,h,function(a){l._tempDomElement.innerHTML=a,g()})})}},l.afterGoBack=function(a,b,c){if(b=n(b),c=n(c),l.pageRemoveCallback(a,b[0],"right"),b.remove(),c.removeClass("page-from-left-to-center page-on-left").addClass("page-on-center"),a.allowPageChange=!0,a.params.dynamicNavbar){{var d=n(a.container).find(".navbar-inner:not(.cached)");n(d[1]).remove(),n(d[0]).removeClass("navbar-on-left navbar-from-left-to-center").addClass("navbar-on-center")}if(a.params.preloadPreviousPage&&a.params.domCache){var e=n(a.container).find(".navbar-inner.cached");n(e[e.length-1]).removeClass("cached")}}var f=a.history.pop();if(!a.params.domCache&&f&&f.indexOf("#content-")>-1&&f in a.contentCache&&(a.contentCache[f]=null,delete a.contentCache[f]),l.params.pushState&&l.pushStateClearQueue(),a.params.preloadPreviousPage){if(a.params.domCache){var g=n(a.container).find(".page.cached");n(g[g.length-1]).removeClass("cached")}l.goBack(a,{preloadOnly:!0})}};var s=document.createElement("div");l.modal=function(a){a=a||{};var b="";if(l.params.modalTemplate)l._compiledTemplates.modal||(l._compiledTemplates.modal=o.compile(l.params.modalTemplate)),b=l._compiledTemplates.modal(a);else{var c="";if(a.buttons&&a.buttons.length>0)for(var d=0;d'+a.buttons[d].text+""; +var e=a.title?'":"",f=a.title?'":"",g=a.afterText?a.afterText:"",h=a.buttons&&0!==a.buttons.length?"":"modal-no-buttons";b='"}s.innerHTML=b;var i=n(s).children();return n("body").append(i[0]),i.find(".modal-button").each(function(b,c){n(c).on("click",function(c){a.buttons[b].close!==!1&&l.closeModal(i),a.buttons[b].onClick&&a.buttons[b].onClick(i,c),a.onClick&&a.onClick(i,b)})}),l.openModal(i),i[0]},l.alert=function(a,b,c){return"function"==typeof b&&(c=arguments[1],b=void 0),l.modal({text:a||"",title:"undefined"==typeof b?l.params.modalTitle:b,buttons:[{text:l.params.modalButtonOk,bold:!0,onClick:c}]})},l.confirm=function(a,b,c,d){return"function"==typeof b&&(d=arguments[2],c=arguments[1],b=void 0),l.modal({text:a||"",title:"undefined"==typeof b?l.params.modalTitle:b,buttons:[{text:l.params.modalButtonCancel,onClick:d},{text:l.params.modalButtonOk,bold:!0,onClick:c}]})},l.prompt=function(a,b,c,d){return"function"==typeof b&&(d=arguments[2],c=arguments[1],b=void 0),l.modal({text:a||"",title:"undefined"==typeof b?l.params.modalTitle:b,afterText:'',buttons:[{text:l.params.modalButtonCancel},{text:l.params.modalButtonOk,bold:!0}],onClick:function(a,b){0===b&&d&&d(n(a).find(".modal-text-input").val()),1===b&&c&&c(n(a).find(".modal-text-input").val())}})},l.modalLogin=function(a,b,c,d){return"function"==typeof b&&(d=arguments[2],c=arguments[1],b=void 0),l.modal({text:a||"",title:"undefined"==typeof b?l.params.modalTitle:b,afterText:'',buttons:[{text:l.params.modalButtonCancel},{text:l.params.modalButtonOk,bold:!0}],onClick:function(a,b){var e=n(a).find('.modal-text-input[name="modal-username"]').val(),f=n(a).find('.modal-text-input[name="modal-password"]').val();0===b&&d&&d(e,f),1===b&&c&&c(e,f)}})},l.modalPassword=function(a,b,c,d){return"function"==typeof b&&(d=arguments[2],c=arguments[1],b=void 0),l.modal({text:a||"",title:"undefined"==typeof b?l.params.modalTitle:b,afterText:'',buttons:[{text:l.params.modalButtonCancel},{text:l.params.modalButtonOk,bold:!0}],onClick:function(a,b){var e=n(a).find('.modal-text-input[name="modal-password"]').val();0===b&&d&&d(e),1===b&&c&&c(e)}})},l.showPreloader=function(a){return l.modal({title:a||l.params.modalPreloaderTitle,text:'
'})},l.hidePreloader=function(){l.closeModal(".modal.modal-in")},l.showIndicator=function(){n("body").append('
')},l.hideIndicator=function(){n(".preloader-indicator-overlay, .preloader-indicator-modal").remove()},l.actions=function(a,b){var c,d,e,f=!1;1===arguments.length?b=a:l.device.ios?l.device.ipad&&(f=!0):n(window).width()>=768&&(f=!0),b=b||[],b.length>0&&!n.isArray(b[0])&&(b=[b]);var g;if(f){var h='
{{#each this}}
    {{#each this}}{{#if label}}
  • {{text}}
  • {{else}}
  • {{text}}
  • {{/if}}{{/each}}
{{/each}}
';l._compiledTemplates.actionsPopover||(l._compiledTemplates.actionsPopover=o.compile(h));var i=l._compiledTemplates.actionsPopover(b);c=n(l.popover(i,a,!0)),d=".list-block ul",e=".list-button"}else{if(l.params.modalActionsTemplate)l._compiledTemplates.actions||(l._compiledTemplates.actions=o.compile(l.params.modalActionsTemplate)),g=l._compiledTemplates.actions(b);else{for(var j="",k=0;k');var p=b[k][m],q=p.label?"actions-modal-label":"actions-modal-button";p.bold&&(q+=" actions-modal-button-bold"),p.color&&(q+=" color-"+p.color),j+=''+p.text+"",m===b[k].length-1&&(j+="
")}g='
'+j+"
"}s.innerHTML=g,c=n(s).children(),n("body").append(c[0]),d=".actions-modal-group",e=".actions-modal-button"}var r=c.find(d);return r.each(function(a,d){var g=a;n(d).children().each(function(a,d){var h,i=a,j=b[g][i];!f&&n(d).is(e)&&(h=n(d)),f&&n(d).find(e).length>0&&(h=n(d).find(e)),h&&h.on("click",function(a){j.close!==!1&&l.closeModal(c),j.onClick&&j.onClick(c,a)})})}),f||l.openModal(c),c[0]},l.popover=function(a,b,c){function d(){a.css({left:"",top:""});var c=a.width(),d=a.height(),e=a.find(".popover-angle"),f=e.width()/2;e.removeClass("on-left on-right on-top on-bottom").css({left:"",top:""});var g=b.outerWidth(),h=b.outerHeight(),i=b.offset(),j=b.parents(".page");j.length>0&&(i.top=i.top-j[0].scrollTop);var k=n(window).height(),l=n(window).width(),m=0,o=0,p=0,q="top";d+fm?m=5:m+d>k&&(m=k-d-5),p-=m),"top"===q||"bottom"===q?(o=g/2+i.left-c/2,p=o,5>o&&(o=5),o+c>l&&(o=l-c-5),"top"===q&&e.addClass("on-bottom"),"bottom"===q&&e.addClass("on-top"),p-=o,e.css({left:c/2-f+p+"px"})):"middle"===q&&(o=i.left-c-f,e.addClass("on-right"),5>o&&(o=i.left+g+f,e.removeClass("on-right").addClass("on-left")),o+c>l&&(o=l-c-5,e.removeClass("on-right").addClass("on-left")),e.css({top:d/2-f+p+"px"})),a.css({top:m+"px",left:o+"px"})}if("undefined"==typeof c&&(c=!0),"string"==typeof a&&a.indexOf("<")>=0){var e=document.createElement("div");if(e.innerHTML=n.trim(a),!(e.childNodes.length>0))return!1;a=e.childNodes[0],c&&a.classList.add("remove-on-close"),n("body").append(a)}return a=n(a),b=n(b),0===a.length||0===b.length?!1:(0===a.find(".popover-angle").length&&a.append('
'),a.show(),d(),n(window).on("resize",d),a.on("close",function(){n(window).off("resize",d)}),a.find("."+l.params.viewClass).length>0&&l.sizeNavbars(a.find("."+l.params.viewClass)[0]),l.openModal(a),a[0])},l.popup=function(a,b){if("undefined"==typeof b&&(b=!0),"string"==typeof a&&a.indexOf("<")>=0){var c=document.createElement("div");if(c.innerHTML=n.trim(a),!(c.childNodes.length>0))return!1;a=c.childNodes[0],b&&a.classList.add("remove-on-close"),n("body").append(a)}return a=n(a),0===a.length?!1:(a.show(),a.find("."+l.params.viewClass).length>0&&l.sizeNavbars(a.find("."+l.params.viewClass)[0]),l.openModal(a),a[0])},l.loginScreen=function(a){return a||(a=".login-screen"),a=n(a),0===a.length?!1:(a.show(),a.find("."+l.params.viewClass).length>0&&l.sizeNavbars(a.find("."+l.params.viewClass)[0]),l.openModal(a),a[0])},l.openModal=function(a){a=n(a);var b=a.hasClass("popover"),c=a.hasClass("popup"),d=a.hasClass("login-screen");b||c||d||a.css({marginTop:-Math.round(a.outerHeight()/2)+"px"});var e;d||(0!==n(".modal-overlay").length||c||n("body").append(''),0===n(".popup-overlay").length&&c&&n("body").append(''),e=n(c?".popup-overlay":".modal-overlay"));a[0].clientLeft;return a.trigger("open"),d||e.addClass("modal-overlay-visible"),a.removeClass("modal-out").addClass("modal-in").transitionEnd(function(){a.trigger(a.hasClass("modal-out")?"closed":"opened")}),!0},l.closeModal=function(a){if(a=n(a||".modal-in"),"undefined"==typeof a||0!==a.length){var b=a.hasClass("popover"),c=a.hasClass("popup"),d=a.hasClass("login-screen"),e=a.hasClass("remove-on-close"),f=n(c?".popup-overlay":".modal-overlay");return f.removeClass(c&&a.length===n(".popup.modal-in").length?"modal-overlay-visible":"modal-overlay-visible"),a.trigger("close"),b?(a.removeClass("modal-in modal-out").trigger("closed").hide(),e&&a.remove()):a.removeClass("modal-in").addClass("modal-out").transitionEnd(function(){a.trigger(a.hasClass("modal-out")?"closed":"opened"),c||d?(a.removeClass("modal-out").hide(),e&&a.length>0&&a.remove()):a.remove()}),!0}},l.allowPanelOpen=!0,l.openPanel=function(a){function b(){e.transitionEnd(function(a){n(a.target).is(e)?(c.trigger(c.hasClass("active")?"opened":"closed"),l.allowPanelOpen=!0):b()})}if(!l.allowPanelOpen)return!1;var c=n(".panel-"+a);if(0===c.length||c.hasClass("active"))return!1;l.closePanel(),l.allowPanelOpen=!1;var d=c.hasClass("panel-reveal")?"reveal":"cover";c.css({display:"block"}).addClass("active"),c.trigger("open"),c.find("."+l.params.viewClass).length>0&&l.sizeNavbars&&l.sizeNavbars(c.find("."+l.params.viewClass)[0]);var e=(c[0].clientLeft,"reveal"===d?n("."+l.params.viewsClass):c);return b(),n("body").addClass("with-panel-"+a+"-"+d),!0},l.closePanel=function(){var a=n(".panel.active");if(0===a.length)return!1;var b=a.hasClass("panel-reveal")?"reveal":"cover",c=a.hasClass("panel-left")?"left":"right";a.removeClass("active");var d="reveal"===b?n("."+l.params.viewsClass):a;a.trigger("close"),l.allowPanelOpen=!1,d.transitionEnd(function(){a.hasClass("active")||(a.css({display:""}),a.trigger("closed"),n("body").removeClass("panel-closing"),l.allowPanelOpen=!0)}),n("body").addClass("panel-closing").removeClass("with-panel-"+c+"-"+b)},l.initSwipePanels=function(){function a(a){if(l.allowPanelOpen&&l.params.swipePanel&&!e&&!(n(".modal-in, .photo-browser-in").length>0||!l.params.swipePanelCloseOpposite&&n(".panel.active").length>0&&!d.hasClass("active"))){if(s.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,s.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY,l.params.swipePanelCloseOpposite&&(q=n(".panel.active").length>0?n(".panel.active").hasClass("panel-left")?"left":"right":l.params.swipePanel),d=n(".panel.panel-"+q),l.params.swipePanelActiveArea){if("left"===q&&s.x>l.params.swipePanelActiveArea)return;if("right"===q&&s.xMath.abs(b-s.x))),g)return void(e=!1);if(!p&&(p=b>s.x?"to-right":"to-left","left"===q&&"to-left"===p&&!d.hasClass("active")||"right"===q&&"to-right"===p&&!d.hasClass("active")))return void(e=!1);if(l.params.swipePanelNoFollow){var n=(new Date).getTime()-h;return 300>n&&("to-left"===p&&("right"===q&&l.openPanel(q),"left"===q&&d.hasClass("active")&&l.closePanel()),"to-right"===p&&("left"===q&&l.openPanel(q),"right"===q&&d.hasClass("active")&&l.closePanel())),e=!1,void(f=!1)}f||(o=d.hasClass("panel-cover")?"cover":"reveal",d.show(),r.show(),k=d.hasClass("active"),m=d.width(),d.transition(0),d.find("."+l.params.viewClass).length>0&&l.sizeNavbars&&l.sizeNavbars(d.find("."+l.params.viewClass)[0])),f=!0,a.preventDefault();var u=k?0:-l.params.swipePanelThreshold;"right"===q&&(u=-u),i=b-s.x+u,"right"===q?(j=i-(k?m:0),j>0&&(j=0),-m>j&&(j=-m)):(j=i+(k?m:0),0>j&&(j=0),j>m&&(j=m)),"reveal"===o?(t.transform("translate3d("+j+"px,0,0)").transition(0),r.transform("translate3d("+j+"px,0,0)"),l.pluginHook("swipePanelSetTransform",t[0],d[0],Math.abs(j/m))):(d.transform("translate3d("+j+"px,0,0)").transition(0),l.pluginHook("swipePanelSetTransform",t[0],d[0],Math.abs(j/m)))}}function c(){if(!e||!f)return e=!1,void(f=!1);e=!1,f=!1;var a,b=(new Date).getTime()-h,c=0===j||Math.abs(j)===m;if(a=k?j===-m?"reset":300>b&&Math.abs(j)>=0||b>=300&&Math.abs(j)<=m/2?"left"===q&&j===m?"reset":"swap":"reset":0===j?"reset":300>b&&Math.abs(j)>0||b>=300&&Math.abs(j)>=m/2?"swap":"reset","swap"===a&&(l.allowPanelOpen=!0,k?(l.closePanel(),c&&(d.css({display:""}),n("body").removeClass("panel-closing"))):l.openPanel(q),c&&(l.allowPanelOpen=!0)),"reset"===a)if(k)l.allowPanelOpen=!0,l.openPanel(q);else if(l.closePanel(),c)l.allowPanelOpen=!0,d.css({display:""});else{var g="reveal"===o?t:d;n("body").addClass("panel-closing"),g.transitionEnd(function(){l.allowPanelOpen=!0,d.css({display:""}),n("body").removeClass("panel-closing")})}"reveal"===o&&(t.transition(""),t.transform("")),d.transition("").transform(""),r.css({display:""}).transform("")}var d=n(".panel.panel-"+l.params.swipePanel);if(0!==d.length){var e,f,g,h,i,j,k,m,o,p,q,r=n(".panel-overlay"),s={},t=n("."+l.params.viewsClass);q=l.params.swipePanel,n(document).on(l.touchEvents.start,a),n(document).on(l.touchEvents.move,b),n(document).on(l.touchEvents.end,c)}},l.initMessages=function(a){var b=n(a),c=b.find(".messages");if(0!==c.length){var d=b.find(".page-content");c.hasClass("new-messages-first")||(d[0].scrollTop=c.height()-d.height()),l.updateMessagesAngles(c)}},l.addMessage=function(a){if(a=a||{},a.type=a.type||"sent",!a.text||0===a.length)return!1;var b=n(".messages-content");if(0===b.length)return!1;var c=b.find(".messages"),d=c.hasClass("new-messages-first"),e="";a.day&&(e+='
'+a.day+(a.time?",":"")+(a.time?" "+a.time+"":"")+"
");var f=a.text.indexOf("=0?"message-pic":"",g=a.avatar?"message-with-avatar":"",h="message message-"+a.type+" "+f+" "+g+" message-appear";e+='
'+(a.name?'
'+a.name+"
":"")+'
'+a.text+"
"+(a.avatar?'
':"")+"
",d?c.prepend(e):c.append(e),l.updateMessagesAngles(c),l.scrollMessagesContainer(b)},l.updateMessagesAngles=function(a){a.find(".message").each(function(){var a=n(this);a.find(".message-text img").length>0&&a.addClass("message-pic"),a.find(".message-avatar").length>0&&a.addClass("message-with-avatar")}),a.find(".message-sent").each(function(){var a=n(this),b=a.next(".message-sent"),c=a.prev(".message-sent");0===b.length?a.addClass("message-last"):a.removeClass("message-last"),0===c.length?a.addClass("message-first"):a.removeClass("message-first"),c.length>0&&c.find(".message-name").length>0&&a.find(".message-name").length>0&&c.find(".message-name").text()!==a.find(".message-name").text()&&(c.addClass("message-last"),a.addClass("message-first"))}),a.find(".message-received").each(function(){var a=n(this),b=a.next(".message-received"),c=a.prev(".message-received");0===b.length?a.addClass("message-last"):a.removeClass("message-last"),0===c.length?a.addClass("message-first"):a.removeClass("message-first"),c.length>0&&c.find(".message-name").length>0&&a.find(".message-name").length>0&&c.find(".message-name").text()!==a.find(".message-name").text()&&(c.addClass("message-last"),a.addClass("message-first"))})},l.scrollMessagesContainer=function(a){if(a=n(a||".messages-content"),0!==a.length){var b=a.find(".messages"),c=b.hasClass("new-messages-first"),d=a[0].scrollTop,e=c?0:b.height()-a.height();e!==d&&a.scrollTop(e,300)}},l.swipeoutOpenedEl=void 0,l.allowSwipeout=!0,l.initSwipeout=function(a){function b(a){l.allowSwipeout&&(f=!1,e=!0,g=void 0,B.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,B.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY,h=(new Date).getTime())}function c(a){if(e){var b="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,c="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY;if("undefined"==typeof g&&(g=!!(g||Math.abs(c-B.y)>Math.abs(b-B.x))),g)return void(e=!1);if(!f){if(n(".list-block.sortable-opened").length>0)return;j=n(this),k=j.find(".swipeout-content"),m=j.find(".swipeout-actions-right"),o=j.find(".swipeout-actions-left"),p=q=u=v=y=x=null,o.length>0&&(p=o.width(),u=o.children("a"),x=o.find(".swipeout-overswipe")),m.length>0&&(q=m.width(),v=m.children("a"),y=m.find(".swipeout-overswipe")),s=j.hasClass("swipeout-opened"),s&&(t=j.find(".swipeout-actions-left.swipeout-actions-opened").length>0?"left":"right"),j.removeClass("transitioning"),l.params.swipeoutNoFollow||(j.find(".swipeout-actions-opened").removeClass("swipeout-actions-opened"),j.removeClass("swipeout-opened"))}if(f=!0,a.preventDefault(),i=b-B.x,r=i,s&&("right"===t?r-=q:r+=p),r>0&&0===o.length||0>r&&0===m.length){if(!s)return void(e=f=!1);r=0}w=0>r?"to-left":r>0?"to-right":w?w:"to-left";var d,h,C;if(a.f7PreventPanelSwipe=!0,l.params.swipeoutNoFollow)return s?("right"===t&&i>0&&l.swipeoutClose(j),"left"===t&&0>i&&l.swipeoutClose(j)):(0>i&&m.length>0&&l.swipeoutOpen(j,"right"),i>0&&o.length>0&&l.swipeoutOpen(j,"left")),e=!1,void(f=!1);z=!1,A=!1;var D;if(m.length>0)for(C=r/q,-q>r&&(r=-q-Math.pow(-r-q,.8),y.length>0&&(A=!0)),d=0;d0&&D.hasClass("swipeout-overswipe")&&D.css({left:(A?-h:0)+"px"}),D.transform("translate3d("+(r-h*(1+Math.max(C,-1)))+"px,0,0)");if(o.length>0)for(C=r/p,r>p&&(r=p+Math.pow(r-p,.8),x.length>0&&(z=!0)),d=0;d0&&D.hasClass("swipeout-overswipe")&&D.css({left:(z?h:0)+"px"}),D.css("z-index",u.length-d).transform("translate3d("+(r+h*(1-Math.min(C,1)))+"px,0,0)");k.transform("translate3d("+r+"px,0,0)")}}function d(){if(!e||!f)return e=!1,void(f=!1);e=!1,f=!1;var a,b,c,d,g,t=(new Date).getTime()-h;if(c="to-left"===w?m:o,b="to-left"===w?q:p,a=300>t&&(-10>i&&"to-left"===w||i>10&&"to-right"===w)||t>=300&&Math.abs(r)>b/2?"open":"close",300>t&&(0===Math.abs(r)&&(a="close"),Math.abs(r)===b&&(a="open")),"open"===a){l.swipeoutOpenedEl=j,j.trigger("open"),j.addClass("swipeout-opened transitioning");var x="to-left"===w?-b:b;if(k.transform("translate3d("+x+"px,0,0)"),c.addClass("swipeout-actions-opened"),d="to-left"===w?v:u)for(g=0;g0&&u!==d)for(g=0;g0&&v!==d)for(g=0;g0&&v.transform(""),o.length>0&&u.transform("")))})}var e,f,g,h,i,j,k,m,o,p,q,r,s,t,u,v,w,x,y,z,A,B={};n(document).on(l.touchEvents.start,function(a){if(l.swipeoutOpenedEl){var b=n(a.target);l.swipeoutOpenedEl.is(b[0])||b.parents(".swipeout").is(l.swipeoutOpenedEl)||b.hasClass("modal-in")||b.parents(".modal-in").length>0||b.hasClass("modal-overlay")||l.swipeoutClose(l.swipeoutOpenedEl)}}),a?(n(a).on(l.touchEvents.start,b),n(a).on(l.touchEvents.move,c),n(a).on(l.touchEvents.end,d)):(n(document).on(l.touchEvents.start,".list-block li.swipeout",b),n(document).on(l.touchEvents.move,".list-block li.swipeout",c),n(document).on(l.touchEvents.end,".list-block li.swipeout",d))},l.swipeoutOpen=function(a,b){if(a=n(a),0!==a.length&&(a.length>1&&(a=n(a[0])),a.hasClass("swipeout")&&!a.hasClass("swipeout-opened"))){b||(b=a.find(".swipeout-actions-right").length>0?"right":"left");var c=a.find(".swipeout-actions-"+b);if(0!==c.length){a.trigger("open").addClass("swipeout-opened").removeClass("transitioning"),c.addClass("swipeout-actions-opened");var d,e=c.children("a"),f=c.width(),g="right"===b?-f:f;if(e.length>1){for(d=0;d1&&(a=n(a[0])),l.swipeoutOpenedEl=void 0,a.trigger("delete"),a.css({height:a.outerHeight()+"px"});{a[0].clientLeft}a.css({height:"0px"}).addClass("deleting transitioning").transitionEnd(function(){a.trigger("deleted"),a.remove()});var b="-100%";a.find(".swipeout-content").transform("translate3d("+b+",0,0)")}},l.sortableToggle=function(a){return a=n(a),0===a.length&&(a=n(".list-block.sortable")),a.toggleClass("sortable-opened"),a.trigger(a.hasClass("sortable-opened")?"open":"close"),a},l.sortableOpen=function(a){return a=n(a),0===a.length&&(a=n(".list-block.sortable")),a.addClass("sortable-opened"),a.trigger("open"),a},l.sortableClose=function(a){return a=n(a),0===a.length&&(a=n(".list-block.sortable")),a.removeClass("sortable-opened"),a.trigger("close"),a},l.initSortable=function(){function a(a){e=!1,d=!0,f="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY,h=n(this).parent(),i=h.parent().find("li"),p=h.parents(".sortable"),a.preventDefault(),l.allowsPanelOpen=l.allowSwipeout=!1}function b(a){if(d&&h){var b=("touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,"touchmove"===a.type?a.targetTouches[0].pageY:a.pageY);e||(h.addClass("sorting"),p.addClass("sortable-sorting"),j=h[0].offsetTop,k=h.parent().height()-h[0].offsetTop-h.height()),e=!0,a.preventDefault(),a.f7PreventPanelSwipe=!0,g=b-f;var c=g;-j>c&&(c=-j),c>k&&(c=k),h.transform("translate3d(0,"+c+"px,0)"),o=m=void 0,i.each(function(){var a=n(this);if(a[0]!==h[0]){var b=a[0].offsetTop,d=a.height(),e=h[0].offsetTop+c;e>=b-d/2&&h.index()=e&&h.index()>a.index()?(n(this).transform("translate3d(0,100%,0)"),m=void 0,o||(o=a)):n(this).transform("translate3d(0, 0%,0)")}})}}function c(a){return l.allowsPanelOpen=l.allowSwipeout=!0,d&&e?(a.preventDefault(),i.transform(""),h.removeClass("sorting"),p.removeClass("sortable-sorting"),m&&(h.insertAfter(m),h.trigger("sort")),o&&(h.insertBefore(o),h.trigger("sort")),m=o=void 0,d=!1,void(e=!1)):(d=!1,void(e=!1))}var d,e,f,g,h,i,j,k,m,o,p;n(document).on(l.touchEvents.start,".list-block.sortable .sortable-handler",a),l.support.touch?(n(document).on(l.touchEvents.move,".list-block.sortable .sortable-handler",b),n(document).on(l.touchEvents.end,".list-block.sortable .sortable-handler",c)):(n(document).on(l.touchEvents.move,b),n(document).on(l.touchEvents.end,c))},l.initSmartSelects=function(a){var b=n(a);if(0!==b.length){var c=b.find(".smart-select");0!==c.length&&c.each(function(){var a=n(this),b=a.find("select");if(0!==b.length){var c=b[0];if(0!==c.length){for(var d=[],e=0;e'+d.join(", ")+""):f.text(d)}}})}},l.smartSelectOpen=function(a){function b(f){var g=f.detail.page;g.name===z&&(n(document).off("pageInit",b),n(g.container).find('input[name="'+q+'"]').on("change",function(){var b=this,f=b.value,g=[];if("checkbox"===b.type)for(var h=0;h'+f[s].group.label+"",i=f[s].group);var u="";"checkbox"===p&&(u+=''),f[s].icon&&(u+=''),f[s].image&&(u+=''),r+='
  • "}var v='",w="static";a.parents(".navbar-through").length>0&&(w="through"),a.parents(".navbar-fixed").length>0&&(w="fixed");var x,y,z="smart-select-"+q,A=a.parents(".page").hasClass("no-toolbar")?"no-toolbar":"",B=a.parents(".page").hasClass("no-navbar")?"no-navbar":"navbar-"+w,C="undefined"==typeof a.data("searchbar")?l.params.smartSelectSearchbar:"true"===a.data("searchbar")?!0:!1;C&&(x=a.data("searchbar-placeholder")||"Search",y=a.data("searchbar-cancel")||"Cancel");var D='
    ',E=("through"===w?v:"")+'
    '+("fixed"===w?v:"")+(C?D:"")+'
    '+("static"===w?v:"")+'
      '+r+"
    ";n(document).on("pageInit",b),c.loadContent(E)}}}},l.initPullToRefresh=function(a){function b(a){if(g){if("android"!==l.device.os)return;if("targetTouches"in a&&a.targetTouches.length>1)return}h=!1,g=!0,i=void 0,q=void 0,r.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,r.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY,k=(new Date).getTime(),m=n(this)}function c(a){if(g){var b="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,c="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY;if("undefined"==typeof i&&(i=!!(i||Math.abs(c-r.y)>Math.abs(b-r.x))),!i)return void(g=!1);if(p=m[0].scrollTop,"undefined"==typeof q&&0!==p&&(q=!0),!h){if(m.removeClass("transitioning"),p>m[0].offsetHeight)return void(g=!1);u=m.hasClass("refreshing")?44:0,t=m[0].scrollHeight===m[0].offsetHeight||"ios"!==l.device.os?!0:!1}return h=!0,j=c-r.y,j>0&&0>=p||0>p?("ios"===l.device.os&&parseInt(l.device.osVersion.split(".")[0],10)>7&&0===p&&!q&&(t=!0),t&&(a.preventDefault(),o=Math.pow(j,.85)+u,m.transform("translate3d(0,"+o+"px,0)")),t&&Math.pow(j,.85)>44||!t&&j>=88?(s=!0,m.addClass("pull-up").removeClass("pull-down")):(s=!1,m.removeClass("pull-up").addClass("pull-down")),void 0):(m.removeClass("pull-up pull-down"),void(s=!1))}}function d(){return g&&h?(o&&(m.addClass("transitioning"),o=0),m.transform(""),s?(m.addClass("refreshing"),m.trigger("refresh",{done:function(){l.pullToRefreshDone(m)}})):m.removeClass("pull-down"),g=!1,void(h=!1)):(g=!1,void(h=!1))}function e(){f.off(l.touchEvents.start,b),f.off(l.touchEvents.move,c),f.off(l.touchEvents.end,d),v.off("pageBeforeRemove",e)}var f=n(a);if(f.hasClass("pull-to-refresh-content")||(f=f.find(".pull-to-refresh-content")),0!==f.length){var g,h,i,j,k,m,o,p,q,r={},s=!1,t=!1,u=0;m=f,f.on(l.touchEvents.start,b),f.on(l.touchEvents.move,c),f.on(l.touchEvents.end,d);var v=f.hasClass("page")?f:f.parents(".page");0!==v.length&&v.on("pageBeforeRemove",e)}},l.pullToRefreshDone=function(a){a=n(a),0===a.length&&(a=n(".pull-to-refresh-content.refreshing")),a.removeClass("refreshing").addClass("transitioning"),a.transitionEnd(function(){a.removeClass("transitioning pull-up pull-down")})},l.pullToRefreshTrigger=function(a){a=n(a),0===a.length&&(a=n(".pull-to-refresh-content")),a.hasClass("refreshing")||(a.addClass("transitioning refreshing"),a.trigger("refresh",{done:function(){l.pullToRefreshDone(a)}}))},l.attachInfiniteScroll=function(a){n(a).on("scroll",j)},l.detachInfiniteScroll=function(a){n(a).off("scroll",j)},l.initInfiniteScroll=function(a){function b(){l.detachInfiniteScroll(c),a.off("pageBeforeRemove",b)}a=n(a);var c=a.find(".infinite-scroll");l.attachInfiniteScroll(c),a.on("pageBeforeRemove",b)},l.showTab=function(a,b){var c=n(a);if(c.hasClass("active"))return!1;if(0===c.length)return!1;var d=c.parent(".tabs");if(0===d.length)return!1;l.allowSwipeout=!0;var e=d.parent().hasClass("tabs-animated-wrap");e&&d.transform("translate3d("+100*-c.index()+"%,0,0)");var f=d.children(".tab.active").removeClass("active");if(c.addClass("active"),c.trigger("show"),!e&&c.find(".navbar").length>0){var g;g=c.hasClass(l.params.viewClass)?c[0]:c.parents("."+l.params.viewClass)[0],l.sizeNavbars(g)}if(b?b=n(b):(b=n("string"==typeof a?'.tab-link[href="'+a+'"]':'.tab-link[href="#'+c.attr("id")+'"]'),0===b.length&&n("[data-tab]").each(function(){c.is(n(this).attr("data-tab"))&&(b=n(this))})),0!==b.length){var h;if(f&&f.length>0){var i=f.attr("id");i&&(h=n('.tab-link[href="#'+i+'"]')),0===h.length&&n("[data-tab]").each(function(){f.is(n(this).attr("data-tab"))&&(h=n(this))})}return b&&b.length>0&&b.addClass("active"),h&&h.length>0&&h.removeClass("active"),!0}},l.accordionToggle=function(a){a=n(a),0!==a.length&&(a.hasClass("accordion-item-expanded")?l.accordionClose(a):l.accordionOpen(a))},l.accordionOpen=function(a){a=n(a);var b=a.parents(".accordion-list"),c=a.find(".accordion-item-content"),d=b.find(".accordion-item-expanded");d.length>0&&l.accordionClose(d),c.css("height",c[0].scrollHeight+"px").transitionEnd(function(){if(a.hasClass("accordion-item-expanded")){c.transition(0),c.css("height","auto");{c[0].clientLeft}c.transition(""),a.trigger("opened")}else c.css("height",""),a.trigger("closed")}),a.trigger("open"),a.addClass("accordion-item-expanded")},l.accordionClose=function(a){a=n(a);var b=a.find(".accordion-item-content");a.removeClass("accordion-item-expanded"),b.transition(0),b.css("height",b[0].scrollHeight+"px");b[0].clientLeft;b.transition(""),b.css("height","").transitionEnd(function(){if(a.hasClass("accordion-item-expanded")){b.transition(0),b.css("height","auto");{b[0].clientLeft}b.transition(""),a.trigger("opened")}else b.css("height",""),a.trigger("closed")}),a.trigger("close")},l.initFastClicks=function(){function a(a){var b=n(a.target),c=b.parents(l.params.activeStateElements);return c.length>0?c:b +}function b(){var a=B.parents(".page-content, .panel");return 0===a.length?!1:("yes"!==a.prop("scrollHandlerSet")&&(a.on("scroll",function(){clearTimeout(C)}),a.prop("scrollHandlerSet","yes")),!0)}function c(){B.addClass("active-state")}function d(){B.removeClass("active-state")}function e(a){var b="button checkbox file image radio submit input textarea".split(" ");return document.activeElement&&a!==document.activeElement&&document.activeElement!==document.body?b.indexOf(a.nodeName.toLowerCase())>=0?!1:!0:!1}function f(a){return"input"===a.nodeName.toLowerCase()&&"file"===a.type?!1:a.className.indexOf("no-fastclick")>=0?!1:!0}function g(a){if(document.activeElement===a)return!1;var b=a.nodeName.toLowerCase(),c="button checkbox file image radio submit".split(" ");return a.disabled||a.readOnly?!1:"textarea"===b?!0:"select"===b?"android"===l.device.os?!1:!0:"input"===b&&c.indexOf(a.type)<0?!0:void 0}function h(a){if(a=n(a),a.is("label")||a.parents("label").length>0){if("android"===l.device.os){var b=l.device.osVersion.split(".");return 1*b[0]>4||1*b[0]===4&&1*b[1]>=4?!1:!0}return!1}return!0}function i(b){a(b).addClass("active-state"),"which"in b&&3===b.which&&setTimeout(function(){n(".active-state").removeClass("active-state")},0)}function j(){n(".active-state").removeClass("active-state")}function k(){n(".active-state").removeClass("active-state")}function m(d){if(A=!1,d.targetTouches.length>1)return!0;if(D=f(d.target),!D)return w=!1,!0;if("ios"===l.device.os){var g=window.getSelection();if(g.rangeCount&&(!g.isCollapsed||document.activeElement===g.focusNode))return x=!0,!0;x=!1}"android"===l.device.os&&e(d.target)&&document.activeElement.blur(),w=!0,v=d.target,u=(new Date).getTime(),s=d.targetTouches[0].pageX,t=d.targetTouches[0].pageY,"ios"===l.device.os&&(y=void 0,n(v).parents().each(function(){var a=this;a.scrollHeight>a.offsetHeight&&!y&&(y=a,y.f7ScrollTop=y.scrollTop)})),d.timeStamp-z<200&&d.preventDefault(),l.params.activeState&&(B=a(d),b(d)?C=setTimeout(c,80):c())}function o(a){if(w){var b=!1,c=l.params.fastClicksDistanceThreshold;if(c){var e=a.targetTouches[0].pageX,f=a.targetTouches[0].pageY;(Math.abs(e-s)>c||Math.abs(f-t)>c)&&(b=!0)}else b=!0;b&&(w=!1,v=null,A=!0),l.params.activeState&&(clearTimeout(C),d())}}function p(a){if(clearTimeout(C),!w)return!x&&D&&a.preventDefault(),!0;if(document.activeElement===a.target)return!0;if(x||a.preventDefault(),a.timeStamp-z<200)return!0;if(z=a.timeStamp,u=0,w=!1,"ios"===l.device.os&&y&&y.scrollTop!==y.f7ScrollTop)return!1;l.params.activeState&&(c(),setTimeout(d,0)),g(v)&&v.focus(),a.preventDefault();var b=a.changedTouches[0],e=document.createEvent("MouseEvents"),f="click";return"android"===l.device.os&&"select"===v.nodeName.toLowerCase()&&(f="mousedown"),e.initMouseEvent(f,!0,!0,window,1,b.screenX,b.screenY,b.clientX,b.clientY,!1,!1,!1,!1,0,null),e.forwardedTouchEvent=!0,v.dispatchEvent(e),!1}function q(){w=!1,v=null}function r(a){var b=!1;return w?(v=null,w=!1,!0):"submit"===a.target.type&&0===a.detail?!0:(v||(b=!0),document.activeElement===v&&(b=!0),a.forwardedTouchEvent&&(b=!0),a.cancelable||(b=!0),b||(a.stopImmediatePropagation(),a.stopPropagation(),v?(h(v)||A)&&a.preventDefault():a.preventDefault(),v=null),b)}l.params.activeState&&n("html").addClass("watch-active-state");var s,t,u,v,w,x,y,z,A,B,C,D;l.support.touch?(document.addEventListener("click",r,!0),l.addGlobalEventListener("touchstart",m),l.addGlobalEventListener("touchmove",o),l.addGlobalEventListener("touchend",p),l.addGlobalEventListener("touchcancel",q)):l.params.activeState&&(l.addGlobalEventListener("mousedown",i),l.addGlobalEventListener("mousemove",j),l.addGlobalEventListener("mouseup",k))},l.initClickEvents=function(){function a(a){function b(a){return"false"===a?!1:"true"===a?!0:void 0}var c=n(this),d=c.attr("href"),e="a"===c[0].nodeName.toLowerCase();if(e)for(var f=0;f0&&l.params.modalCloseByOutside&&l.closeModal(".modal.modal-in"),n(".actions-modal.modal-in").length>0&&l.params.actionsCloseByOutside&&l.closeModal(".actions-modal.modal-in"),n(".popover.modal-in").length>0&&l.closeModal(".popover.modal-in")),c.hasClass("popup-overlay")&&n(".popup.modal-in").length>0&&l.params.popupCloseByOutside&&l.closeModal(".popup.modal-in"),c.hasClass("tab-link")&&l.showTab(c.attr("data-tab")||c.attr("href"),c),c.hasClass("swipeout-delete"))if(c.attr("data-confirm")){var j=c.attr("data-confirm"),k=c.attr("data-confirm-title");k?l.confirm(j,k,function(){l.swipeoutDelete(c.parents(".swipeout"))}):l.confirm(j,function(){l.swipeoutDelete(c.parents(".swipeout"))})}else l.swipeoutDelete(c.parents(".swipeout"));if(c.hasClass("toggle-sortable")&&l.sortableToggle(c.data("sortable")),c.hasClass("open-sortable")&&l.sortableOpen(c.data("sortable")),c.hasClass("close-sortable")&&l.sortableClose(c.data("sortable")),c.hasClass("accordion-item-toggle")||c.hasClass("item-link")&&c.parent().hasClass("accordion-item")){var m=c.parents(".accordion-item");0===m.length&&(m=c.parents("li")),l.accordionToggle(m)}if((!l.params.ajaxLinks||c.is(l.params.ajaxLinks))&&e){e&&a.preventDefault();var o=d&&d.length>0&&0!==d.indexOf("#");if(o||c.hasClass("back")){var p;if(c.attr("data-view")?p=n(c.attr("data-view"))[0].f7View:(p=c.parents("."+l.params.viewClass)[0]&&c.parents("."+l.params.viewClass)[0].f7View,p&&p.params.linksView&&(p=n(p.params.linksView)[0].f7View)),!p)for(var f=0;f=0||d.indexOf(f)>=0||!f))if("select"===h&&e.attr("multiple"))d.push(f),b[f]=[],a.find('select[name="'+f+'"] option').each(function(){this.selected&&b[f].push(this.value)});else switch(g){case"checkbox":d.push(f),b[f]=[],a.find('input[name="'+f+'"]').each(function(){this.checked&&b[f].push(this.value)});break;case"radio":d.push(f),a.find('input[name="'+f+'"]').each(function(){this.checked&&(b[f]=this.value)});break;default:b[f]=e.val()}}),b},l.formFromJSON=function(a,b){if(a=n(a),1!==a.length)return!1;var c=["submit","image","button","file"],d=[];a.find("input, select, textarea").each(function(){var e=n(this),f=e.attr("name"),g=e.attr("type"),h=this.nodeName.toLowerCase();if(b[f]&&!(c.indexOf(g)>=0||d.indexOf(f)>=0||!f))if("select"===h&&e.attr("multiple"))d.push(f),a.find('select[name="'+f+'"] option').each(function(){this.selected=b[f].indexOf(this.value)>=0?!0:!1});else switch(g){case"checkbox":d.push(f),a.find('input[name="'+f+'"]').each(function(){this.checked=b[f].indexOf(this.value)>=0?!0:!1});break;case"radio":d.push(f),a.find('input[name="'+f+'"]').each(function(){this.checked=b[f]===this.value?!0:!1});break;default:e.val(b[f])}})},l.initFormsStorage=function(a){function b(){var a=n(this),b=a[0].id;if(b){var c=l.formToJSON(a);c&&(l.formStoreData(b,c),a.trigger("store",{data:c}))}}function c(){d.off("change submit",b),a.off("pageBeforeRemove",c)}if(a=n(a),0!==a.length){var d=a.find("form.store-data");0!==d.length&&(d.each(function(){var a=this.getAttribute("id");if(a){var b=l.formGetData(a);b&&l.formFromJSON(this,b)}}),d.on("change submit",b),a.on("pageBeforeRemove",c))}},n(document).on("submit change","form.ajax-submit, form.ajax-submit-onchange",function(a){var b=n(this);if("change"!==a.type||b.hasClass("ajax-submit-onchange")){"submit"===a.type&&a.preventDefault();var c=b.attr("method")||"GET",d=b.attr("enctype"),e=b.attr("action");if(e){var f;f="POST"===c?new FormData(b[0]):n.serializeObject(l.formToJSON(b[0]));var g=n.ajax({method:c,url:e,contentType:d,data:f,success:function(a){b.trigger("submitted",{data:a,xhr:g})}})}}}),l.pushStateQueue=[],l.pushStateClearQueue=function(){if(0!==l.pushStateQueue.length){var a,b=l.pushStateQueue.pop();l.params.pushStateNoAnimation===!0&&(a=!1),"goBack"===b.action&&l.goBack(b.view,{animatePages:a}),"loadPage"===b.action&&l.loadPage(b.view,{url:b.stateUrl,animatePages:a,pushState:!1}),"loadContent"===b.action&&l.loadPage(b.view,{content:b.stateContent,animatePages:a,pushState:!1})}},l.initPushState=function(){function a(a){if(!b){for(var c,d=0;d=0?c.allowPageChange?l.goBack(c,{url:void 0,animatePages:f,pushState:!1,preloadOnly:!1}):l.pushStateQueue.push({action:"goBack",view:c}):g&&!h?c.allowPageChange?l.loadPage(c,{url:g,animatePages:f,pushState:!1}):l.pushStateQueue.unshift({action:"loadPage",stateUrl:g,view:c}):h&&(c.allowPageChange?l.loadPage(c,{content:h,animatePages:f,pushState:!1}):l.pushStateQueue.unshift({action:"loadContent",stateContent:h,view:c})))}}}var b=!0;n(window).on("load",function(){setTimeout(function(){b=!1},0)}),n(window).on("popstate",a)};var t=function(a,b){var c={initialSlide:0,spaceBetween:0,speed:300,slidesPerView:1,direction:"horizontal",paginationHide:!0,slideClass:"slider-slide",slideActiveClass:"slider-slide-active",slideNextClass:"slider-slide-next",slidePrevClass:"slider-slide-prev",wrapperClass:"slider-wrapper",bulletClass:"slider-pagination-bullet",bulletActiveClass:"slider-pagination-active",preventClicks:!0,preventClicksPropagation:!0,autoplay:!1,autoplayDisableOnInteraction:!0};b=b||{};for(var d in c)"undefined"==typeof b[d]&&(b[d]=c[d]);var e=this;if(e.params=b,e.container=n(a),0!==e.container.length){e.container[0].f7Slider=e,e.container.addClass("vertical"===e.params.direction?"slider-container-vertical":"slider-container-horizontal"),e.wrapper=e.container.children("."+e.params.wrapperClass),e.params.pagination&&(e.paginationContainer=n(e.params.pagination)),e.activeSlideIndex=e.previousSlideIndex=e.params.initialSlide||0;var f="horizontal"===e.params.direction,g=f&&l.rtl?-1:1;e.updateSlides=function(){if(e.slides=e.wrapper.children("."+e.params.slideClass),0!==e.params.spaceBetween){var a=l.rtl?"marginLeft":"marginRight";f?e.slides.css(a,e.params.spaceBetween+"px"):e.slides.css({marginBottom:e.params.spaceBetween+"px"})}if(e.params.slidesPerView>1){var c="(100% - "+(e.params.slidesPerView-1)*b.spaceBetween+"px)/"+e.params.slidesPerView;f?(e.slides.css("width","-webkit-calc("+c+")"),e.slides.css("width","-moz-calc("+c+")"),e.slides.css("width","calc("+c+")")):(e.slides.css("height","-webkit-calc("+c+")"),e.slides.css("height","-moz-calc("+c+")"),e.slides.css("height","calc("+c+")"))}},e.updatePagination=function(){if(e.paginationContainer&&e.paginationContainer.length>0){for(var a="",b=0;b';e.paginationContainer.html(a),e.bullets=e.paginationContainer.find("."+e.params.bulletClass)}},e.updateSize=function(){e.width=e.container[0].offsetWidth,e.height=e.container[0].offsetHeight,e.size=f?e.width:e.height},e.attachEvents=function(a){var b=a?"off":"on";e.container[b](l.touchEvents.start,e.onTouchStart),e.container[b](l.touchEvents.move,e.onTouchMove),e.container[b](l.touchEvents.end,e.onTouchEnd),n(window)[b]("resize",e.onResize),e.params.nextButton&&n(e.params.nextButton)[b]("click",e.onClickNext),e.params.prevButton&&n(e.params.prevButton)[b]("click",e.onClickPrev),e.params.indexButton&&n(e.params.indexButton)[b]("click",e.onClickIndex),(e.params.preventClicks||e.params.preventClicksPropagation)&&e.container[b]("click",e.onClick,!0)},e.detachEvents=function(){e.attachEvents(!0)},e.onResize=function(){e.updateSize(),e.slideTo(e.activeSlideIndex,0,!1)};var h,i,j,k,m,o,p={},q={},r=!1,s=Date.now();e.allowClick=!0,e.onClick=function(a){e.params.preventClicks&&!e.allowClick&&(a.preventDefault(),e.params.preventClicksPropagation&&(a.stopPropagation(),a.stopImmediatePropagation()))},e.onTouchStart=function(a){h=!0,i=!1,k=void 0,p.x=q.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,p.y=q.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY,j=Date.now(),e.allowClick=!0,e.updateSize(),e.params.onTouchStart&&e.params.onTouchStart(e,a),"mousedown"===a.type&&a.preventDefault()},e.onTouchMove=function(a){if(e.params.onTouchMove&&e.params.onTouchMove(e,a),e.allowClick=!1,!(a.targetTouches&&a.targetTouches.length>1)&&(q.x="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,q.y="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,"undefined"==typeof k&&(k=!!(k||Math.abs(q.y-p.y)>Math.abs(q.x-p.x))),(f&&k||!f&&!k)&&e.params.onOppositeTouchMove&&e.params.onOppositeTouchMove(e,a),h)){if(f&&k||!f&&!k)return void(h=!1);e.params.onSliderMove&&e.params.onSliderMove(e,a),a.preventDefault(),a.stopPropagation(),i||(m=n.getTranslate(e.wrapper[0],f?"x":"y")*g,e.wrapper.transition(0),r&&e.onTransitionEnd(),b.autoplay&&u&&(e.params.autoplayDisableOnInteraction?e.stopAutoplay():t&&clearTimeout(t))),i=!0;var c=f?(q.x-p.x)*g:q.y-p.y;c>0&&0===e.activeSlideIndex?c=Math.pow(c,.85):0>c&&e.activeSlideIndex===e.slides.length-e.params.slidesPerView&&(c=-Math.pow(-c,.85));var d=f?(c+m)*g:0,j=f?0:c+m;e.wrapper.transform("translate3d("+d+"px, "+j+"px,0)")}},e.onTouchEnd=function(a){e.params.onTouchEnd&&e.params.onTouchEnd(e,a);var b=Date.now(),c=b-j;if(e.allowClick&&(300>c&&b-s>300&&(o&&clearTimeout(o),o=setTimeout(function(){e&&(e.params.paginationHide&&e.paginationContainer&&e.paginationContainer.toggleClass("slider-pagination-hidden"),e.params.onClick&&e.params.onClick(e,a))},300)),300>c&&300>b-s&&(o&&clearTimeout(o),e.params.onDoubleTap&&e.params.onDoubleTap(e,a)),e.params.onTap&&e.params.onTap(e,a)),s=Date.now(),!h||!i)return void(h=i=!1);h=i=!1;var d=f?(q.x-p.x)*g:q.y-p.y;Math.abs(d)<5&&300>c&&e.allowClick===!1&&(e.allowClick=!0),setTimeout(function(){e&&(e.allowClick=!0)},100);var k=e.params.autoplay&&u&&!e.params.autoplayDisableOnInteraction;if(0===d)return void(k&&e.startAutoplay());var l=1,m=e.size/e.params.slidesPerView;e.params.slidesPerView>1&&(l=Math.abs((Math.abs(d)+m/2)/m)),k&&e.wrapper.transitionEnd(function(){e.startAutoplay()}),c>300?-m/2>=d?e.slideTo(e.activeSlideIndex+Math.floor(l)):d>m/2?e.slideTo(e.activeSlideIndex-Math.floor(l)):e.slideReset():Math.abs(d)<10?e.slideReset():e.slideTo(0>d?e.activeSlideIndex+Math.round(l):e.activeSlideIndex-Math.round(l))},e.slideTo=function(a,b,c){"undefined"==typeof a&&(a=0),0>a&&(a=0),a>e.slides.length-e.params.slidesPerView&&(a=e.slides.length-e.params.slidesPerView);var d=-(e.size+e.params.spaceBetween)*a/e.params.slidesPerView;"undefined"==typeof b&&(b=e.params.speed),e.previousSlideIndex=e.activeSlideIndex,e.activeSlideIndex=Math.round(a),e.isFirst=0===e.activeSlideIndex,e.isLast=e.activeSlideIndex===e.slides.length-e.params.slidesPerView,e.onTransitionStart();var h=f?d*g:0,i=f?0:d;0===b?(e.wrapper.transition(0).transform("translate3d("+h+"px,"+i+"px,0)"),c!==!1&&e.onTransitionEnd()):(r=!0,e.wrapper.transition(b).transform("translate3d("+h+"px,"+i+"px,0)").transitionEnd(function(){c!==!1&&e.onTransitionEnd()}))},e.updateClasses=function(){e.slides.removeClass(e.params.slideActiveClass+" "+e.params.slideNextClass+" "+e.params.slidePrevClass);var a=e.slides.eq(e.activeSlideIndex);a.addClass(e.params.slideActiveClass),a.next().addClass(e.params.slideNextClass),a.prev().addClass(e.params.slidePrevClass),e.bullets&&e.bullets.length>0&&(e.bullets.removeClass(e.params.bulletActiveClass),e.bullets.eq(e.activeSlideIndex).addClass(e.params.bulletActiveClass))},e.onTransitionStart=function(){e.updateClasses(),e.activeSlideIndex!==e.previousSlideIndex&&e.params.onSlideChangeStart&&e.params.onSlideChangeStart(e),e.params.onTransitionStart&&e.params.onTransitionStart(e)},e.onTransitionEnd=function(){r=!1,e.wrapper.transition(0),e.activeSlideIndex!==e.previousSlideIndex&&e.params.onSlideChangeEnd&&e.params.onSlideChangeEnd(e),e.params.onTransitionEnd&&e.params.onTransitionEnd(e)},e.slideNext=function(){e.slideTo(e.activeSlideIndex+1)},e.slidePrev=function(){e.slideTo(e.activeSlideIndex-1)},e.slideReset=function(){e.slideTo(e.activeSlideIndex)},e.onClickNext=function(a){a.preventDefault(),e.slideNext()},e.onClickPrev=function(a){a.preventDefault(),e.slidePrev()},e.onClickIndex=function(a){a.preventDefault(),e.slideTo(n(this).index())};var t,u;return e.startAutoplay=function(){e.params.autoplay&&(u=!0,t&&clearTimeout(t),t=setTimeout(function(){e.wrapper.transitionEnd(function(){e.startAutoplay()});var a=e.activeSlideIndex+1;a>e.slides.length-e.params.slidesPerView&&(a=0),e.slideTo(a)},e.params.autoplay))},e.stopAutoplay=function(){u=!1,t&&clearTimeout(t)},e.resetAutoplay=function(){e.stopAutoplay(),e.startAutoplay()},e.init=function(){e.updateSlides(),e.updatePagination(),e.updateSize(),e.params.initialSlide>0?e.slideTo(e.params.initialSlide,0,!1):e.updateClasses(),e.attachEvents(),e.params.autoplay&&e.startAutoplay()},e.update=function(){e.updateSlides(),e.updatePagination(),e.updateSize(),e.updateClasses()},e.destroy=function(){e.detachEvents(),e.params.onDestroy&&e.params.onDestroy(),e=void 0},e.init(),e}};l.slider=function(a,b){return new t(a,b)},l.initSlider=function(a){function b(a){function b(){a.destroy(),c.off("pageBeforeRemove",b)}c.on("pageBeforeRemove",b)}var c=n(a),d=c.find(".slider-init");if(0!==d.length)for(var e=0;e',i=l.rtl?"next":"prev",j=l.rtl?"prev":"next",k=d.params.toolbarTemplate||'
    ',m=d.params.template||'
    ',o=d.params.photoTemplate||'
    ',p=d.params.captionsTheme||d.params.theme,q=d.params.captionsTemplate||'
    {{captions}}
    ',r=d.params.captionTemplate||'
    {{caption}}
    ',s=d.params.objectTemplate||'
    {{html}}
    ',t="",u="";for(c=0;c=0||v.indexOf(">")>=0?s.replace(/{{html}}/g,v):o.replace(/{{url}}/g,v):"object"==typeof v&&(v.hasOwnProperty("html")&&v.html.length>0?w=s.replace(/{{html}}/g,v.html):v.hasOwnProperty("url")&&v.url.length>0&&(w=o.replace(/{{url}}/g,v.url)),v.hasOwnProperty("caption")&&v.caption.length>0?u+=r.replace(/{{caption}}/g,v.caption).replace(/{{captionIndex}}/g,c):w=w.replace(/{{caption}}/g,"")),t+=w}var x=m.replace("{{navbar}}",d.params.navbar?h:"").replace("{{noNavbar}}",d.params.navbar?"":"no-navbar").replace("{{photos}}",t).replace("{{captions}}",q.replace(/{{captions}}/g,u)).replace("{{toolbar}}",d.params.toolbar?k:"");d.activeSlideIndex=d.params.initialSlide,d.openIndex=d.activeSlideIndex,d.opened=!1,d.open=function(a){return"undefined"==typeof a&&(a=d.activeSlideIndex),a=parseInt(a,10),d.opened&&d.slider?void d.slider.slideTo(a):(d.opened=!0,d.openIndex=a,"standalone"===d.params.type&&n("body").append(x),"popup"===d.params.type&&(d.popup=l.popup('"),n(d.popup).on("closed",d.onPopupClose)),"page"===d.params.type?(n(document).on("pageBeforeInit",d.onPageBeforeInit),n(document).on("pageBeforeRemove",d.onPageBeforeRemove),d.params.view||(d.params.view=b()),void d.params.view.loadContent(x)):(d.layout(d.openIndex),void(d.params.onOpen&&d.params.onOpen(d))))},d.close=function(){d.opened=!1,d.sliderContainer&&0!==d.sliderContainer.length&&(d.params.onClose&&d.params.onClose(d),d.attachEvents(!0),"standalone"===d.params.type&&d.container.removeClass("photo-browser-in").addClass("photo-browser-out").animationEnd(function(){d.container.remove()}),d.slider.destroy(),d.slider=d.sliderContainer=d.sliderWrapper=d.slides=y=z=A=void 0)},d.onPopupClose=function(){d.close(),n(d.popup).off("pageBeforeInit",d.onPopupClose)},d.onPageBeforeInit=function(a){"photo-browser-slides"===a.detail.page.name&&d.layout(d.openIndex),n(document).off("pageBeforeInit",d.onPageBeforeInit)},d.onPageBeforeRemove=function(a){"photo-browser-slides"===a.detail.page.name&&d.close(),n(document).off("pageBeforeRemove",d.onPageBeforeRemove)},d.layout=function(a){d.container="page"===d.params.type?n(".photo-browser-slider-container").parents(".view"):n(".photo-browser"),"standalone"===d.params.type&&(d.container.addClass("photo-browser-in"),l.sizeNavbars(d.container)),d.sliderContainer=d.container.find(".photo-browser-slider-container"),d.sliderWrapper=d.container.find(".photo-browser-slider-wrapper"),d.slides=d.container.find(".photo-browser-slide"),d.captionsContainer=d.container.find(".photo-browser-captions"),d.captions=d.container.find(".photo-browser-caption");var b={nextButton:d.params.nextButton||".photo-browser-next",prevButton:d.params.prevButton||".photo-browser-prev",indexButton:d.params.indexButton,initialSlide:a,spaceBetween:d.params.spaceBetween,speed:d.params.speed,onTap:function(a,b){d.params.onTap&&d.params.onTap(a,b)},onClick:function(a,b){d.params.exposition&&d.toggleExposition(),d.params.onClick&&d.params.onClick(a,b)},onDoubleTap:function(a,b){d.toggleZoom(n(b.target).parents(".photo-browser-slide")),d.params.onDoubleTap&&d.params.onDoubleTap(a,b)},onSlideChangeStart:function(a){d.activeSlideIndex=a.activeSlideIndex,d.container.find(".photo-browser-current").text(a.activeSlideIndex+1),d.container.find(".photo-browser-total").text(a.slides.length),n(".photo-browser-prev, .photo-browser-next").removeClass("photo-browser-link-inactive"),a.isFirst&&n(".photo-browser-prev").addClass("photo-browser-link-inactive"),a.isLast&&n(".photo-browser-next").addClass("photo-browser-link-inactive"),d.captions.length>0&&(d.captionsContainer.find(".photo-browser-caption-active").removeClass("photo-browser-caption-active"),d.captionsContainer.find('[data-caption-index="'+d.activeSlideIndex+'"]').addClass("photo-browser-caption-active"));var b=a.slides.eq(a.previousSlideIndex).find("video");b.length>0&&"pause"in b[0]&&b[0].pause(),d.params.onSlideChangeStart&&d.params.onSlideChangeStart(a)},onSlideChangeEnd:function(a){d.params.zoom&&y&&a.previousSlideIndex!==a.activeSlideIndex&&(z.transform("translate3d(0,0,0) scale(1)"),A.transform("translate3d(0,0,0)"),y=z=A=void 0,B=C=1),d.params.onSlideChangeEnd&&d.params.onSlideChangeEnd(a)}};d.params.swipeToClose&&"page"!==d.params.type&&(b.onTouchStart=d.swipeCloseTouchStart,b.onOppositeTouchMove=d.swipeCloseTouchMove,b.onTouchEnd=d.swipeCloseTouchEnd),d.slider=l.slider(d.sliderContainer,b),d.attachEvents()},d.attachEvents=function(a){var b=a?"off":"on";d.params.zoom&&(d.slides[b]("gesturestart",d.onSlideGestureStart),d.slides[b]("gesturechange",d.onSlideGestureChange),d.slides[b]("gestureend",d.onSlideGestureEnd),d.slides[b](l.touchEvents.start,d.onSlideTouchStart),d.slides[b](l.touchEvents.move,d.onSlideTouchMove),d.slides[b](l.touchEvents.end,d.onSlideTouchEnd)),d.container.find(".photo-browser-close-link")[b]("click",d.close)};d.exposed=!1,d.toggleExposition=function(){d.container&&d.container.toggleClass("photo-browser-exposed"),d.params.expositionHideCaptions&&d.captionsContainer.toggleClass("photo-browser-captions-exposed"),d.exposed=!d.exposed},d.expositionOn=function(){d.container&&d.container.addClass("photo-browser-exposed"),d.params.expositionHideCaptions&&d.captionsContainer.addClass("photo-browser-captions-exposed"),d.exposed=!0},d.expositionOff=function(){d.container&&d.container.removeClass("photo-browser-exposed"),d.params.expositionHideCaptions&&d.captionsContainer.removeClass("photo-browser-captions-exposed"),d.exposed=!1};var y,z,A,B=1,C=1,D=!1;d.onSlideGestureStart=function(){y||(y=n(this),z=y.find("img"),A=z.parent()),z.transition(0),D=!0},d.onSlideGestureChange=function(a){B=a.scale*C,B>d.params.maxZoom&&(B=d.params.maxZoom-1+Math.pow(B-d.params.maxZoom+1,.5)),BV.x))return void(E=!1);a.stopPropagation(),F=!0,G=W.x-V.x+O,H=W.y-V.y+P,I>G&&(G=I+1-Math.pow(I-G+1,.8)),G>K&&(G=K-1+Math.pow(G-K+1,.8)),J>H&&(H=J+1-Math.pow(J-H+1,.8)),H>L&&(H=L-1+Math.pow(H-L+1,.8)),Q||(Q=W.x),T||(T=W.y),R||(R=Date.now()),S=(W.x-Q)/(Date.now()-R)/2,U=(W.y-T)/(Date.now()-R)/2,Math.abs(W.x-Q)<2&&(S=0),Math.abs(W.y-T)<2&&(U=0),Q=W.x,T=W.y,R=Date.now(),A.transform("translate3d("+G+"px, "+H+"px,0)")}}},d.onSlideTouchEnd=function(){if(!E||!F)return E=!1,void(F=!1);E=!1,F=!1;var a=300,b=300,c=S*a,e=G+c,f=U*b,g=H+f;0!==S&&(a=Math.abs((e-G)/S)),0!==U&&(b=Math.abs((g-H)/U));var h=Math.max(a,b);G=e,H=g;var i=M*B,j=N*B;I=Math.min(d.slider.width/2-i/2,0),K=-I,J=Math.min(d.slider.height/2-j/2,0),L=-J,G=Math.max(Math.min(G,K),I),H=Math.max(Math.min(H,L),J),A.transition(h).transform("translate3d("+G+"px, "+H+"px,0)")};var X,Y,Z,$,_,ab=!1,bb=!0,cb=!1;return d.swipeCloseTouchStart=function(){bb&&(ab=!0)},d.swipeCloseTouchMove=function(a,b){if(ab){cb||(cb=!0,Y="touchmove"===b.type?b.targetTouches[0].pageY:b.pageY,$=d.slider.slides.eq(d.slider.activeSlideIndex),_=(new Date).getTime()),b.preventDefault(),Z="touchmove"===b.type?b.targetTouches[0].pageY:b.pageY,X=Y-Z;var c=1-Math.abs(X)/300;$.transform("translate3d(0,"+-X+"px,0)"),d.slider.container.css("opacity",c).transition(0)}},d.swipeCloseTouchEnd=function(){if(ab=!1,!cb)return void(cb=!1);cb=!1,bb=!1;var a=Math.abs(X),b=(new Date).getTime()-_;return 300>b&&a>20||b>=300&&a>100?void setTimeout(function(){"standalone"===d.params.type&&d.close(),"popup"===d.params.type&&l.closeModal(d.popup),d.params.onSwipeToClose&&d.params.onSwipeToClose(d),bb=!0},0):(0!==a?$.addClass("transitioning").transitionEnd(function(){bb=!0,$.removeClass("transitioning")}):bb=!0,d.slider.container.css("opacity","").transition(""),void $.transform(""))},d};l.photoBrowser=function(a){return new u(a)};var v; +l.addNotification=function(a){if(a){"undefined"==typeof a.media&&(a.media=l.params.notificationMedia),"undefined"==typeof a.title&&(a.title=l.params.notificationTitle),"undefined"==typeof a.subtitle&&(a.subtitle=l.params.notificationSubtitle),"undefined"==typeof a.closeIcon&&(a.closeIcon=l.params.notificationCloseIcon),"undefined"==typeof a.hold&&(a.hold=l.params.notificationHold),"undefined"==typeof a.closeOnClick&&(a.closeOnClick=l.params.notificationCloseOnClick),v||(v=document.createElement("div"));var b=n(".notifications");0===b.length&&(n("body").append('
      '),b=n(".notifications"));var c,d=b.children("ul");c=a.custom?"
    • "+a.custom+"
    • ":'
    • '+(a.media?'
      '+a.media+"
      ":"")+'
      '+(a.title?'
      '+a.title+"
      ":"")+(a.closeIcon?'
      ':"")+"
      "+(a.subtitle?'
      '+a.subtitle+"
      ":"")+(a.message?'
      '+a.message+"
      ":"")+"
    • ",v.innerHTML=c;var e=n(v).children();e.on("click",function(b){var c=!1;n(b.target).is(".close-notification")||n(b.target).parents(".close-notification").length>0?c=!0:(a.onClick&&a.onClick(b,e[0]),a.closeOnClick&&(c=!0)),c&&l.closeNotification(e[0])}),a.onClose&&e.data("f7NotificationOnClose",function(){a.onClose(e[0])}),a.additionalClass&&e.addClass(a.additionalClass),a.hold&&setTimeout(function(){e.length>0&&l.closeNotification(e[0])},a.hold),d.prepend(e[0]),b.show();var f=e.height();e.css("marginTop",-f+"px"),e.transition(0);{e[0].clientLeft}return e.transition(""),e.css("marginTop","0px"),b.transform("translate3d(0, 0,0)"),e.removeClass("notification-hidden"),e[0]}},l.closeNotification=function(a){if(a=n(a),0!==a.length&&!a.hasClass("notification-item-removing")){var b=n(".notifications"),c=a.height();a.css("height",c+"px").transition(0);{a[0].clientLeft}a.css("height","0px").transition("").addClass("notification-item-removing"),a.data("f7NotificationOnClose")&&a.data("f7NotificationOnClose")(),0===b.find(".notification-item:not(.notification-item-removing)").length&&b.transform(""),a.addClass("notification-hidden").transitionEnd(function(){a.remove(),0===b.find(".notification-item").length&&b.hide()})}};var w=[];return l.initPlugins=function(){for(var a in l.plugins){var b=l.plugins[a](l,l.params[a]);b&&w.push(b)}},l.pluginHook=function(a){for(var b=0;b0&&b[0].nodeType)for(e=0;e0?parseFloat(this.css("width"))-parseFloat(this.css("padding-left"))-parseFloat(this.css("padding-right")):null},outerWidth:function(a){return this.length>0?a?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null},height:function(){return this[0]===window?window.innerHeight:this.length>0?this[0].offsetHeight-parseFloat(this.css("padding-top"))-parseFloat(this.css("padding-bottom")):null},outerHeight:function(a){return this.length>0?a?this[0].offsetHeight+parseFloat(this.css("margin-top"))+parseFloat(this.css("margin-bottom")):this[0].offsetHeight:null},offset:function(){if(this.length>0){var a=this[0],b=a.getBoundingClientRect(),c=document.body,d=a.clientTop||c.clientTop||0,e=a.clientLeft||c.clientLeft||0,f=window.pageYOffset||a.scrollTop,g=window.pageXOffset||a.scrollLeft;return{top:b.top+f-d,left:b.left+g-e}}return null},hide:function(){for(var a=0;ad-1?new a([]):0>b?(c=d+b,new a(0>c?[]:[this[c]])):new a([this[b]])},append:function(b){var c,d;for(c=0;c=0;d--)this[c].insertBefore(e.childNodes[d],this[c].childNodes[0])}else if(b instanceof a)for(d=0;d1)for(var e=0;e1)for(var e=0;e0?c?this[0].nextElementSibling&&b(this[0].nextElementSibling).is(c)?[this[0].nextElementSibling]:[]:this[0].nextElementSibling?[this[0].nextElementSibling]:[]:[])},nextAll:function(c){var d=[],e=this[0];if(!e)return new a([]);for(;e.nextElementSibling;){var f=e.nextElementSibling;d.push(c&&b(f).is(c)?f:f),e=f}return new a(d)},prev:function(c){return new a(this.length>0?c?this[0].previousElementSibling&&b(this[0].previousElementSibling).is(c)?[this[0].previousElementSibling]:[]:this[0].previousElementSibling?[this[0].previousElementSibling]:[]:[])},prevAll:function(c){var d=[],e=this[0];if(!e)return new a([]);for(;e.previousElementSibling;){var f=e.previousElementSibling;d.push(c&&b(f).is(c)?f:f),e=f}return new a(d)},parent:function(a){for(var c=[],d=0;d=0?a.data.split("?")[1]:a.data:b.serializeObject(a.data),a.url+=a.url.indexOf("?")>=0?"&"+g:"?"+g}if("json"===a.dataType&&a.url.indexOf("callback=")>=0){var h,i,j="f7jsonp_"+Date.now()+c++,k=a.url.split("callback=");if(k[1].indexOf("&")>=0){var l=k[1].split("&").filter(function(a){return a.indexOf("=")>0}).join("&");h=k[0]+"callback="+j+(l.length>0?"&"+l:"")}else h=k[0]+"callback="+j;var m=document.createElement("script");return m.type="text/javascript",m.onerror=function(){clearTimeout(i),a.error&&a.error()},m.src=h,window[j]=function(b){clearTimeout(i),a.success&&a.success(b),m.parentNode.removeChild(m),m=null,delete window[j]},document.querySelector("head").appendChild(m),void(a.timeout>0&&(i=setTimeout(function(){m.parentNode.removeChild(m),m=null,a.error&&a.error()},a.timeout)))}("GET"===f||"HEAD"===f)&&a.cache===!1&&(a.url+="_nocache="+Date.now());var n=new XMLHttpRequest;n.open(f,a.url,a.async,a.user,a.password);var o=null;if(("POST"===f||"PUT"===f)&&a.data)if(a.processData){var p=[ArrayBuffer,Blob,Document,FormData];if(p.indexOf(a.data.constructor)>=0)o=a.data;else{var q="---------------------------"+Date.now().toString(16);"multipart/form-data"===a.contentType?n.setRequestHeader("Content-Type","multipart/form-data; boundary="+q):n.setRequestHeader("Content-Type",a.contentType),o="";var r=b.serializeObject(a.data);if("multipart/form-data"===a.contentType){q="---------------------------"+Date.now().toString(16),r=r.split("&");for(var s=[],t=0;t=0))return e;for(a=a.split("?")[1],c=a.split("&"),b=0;bf&&l>=j&&(n.scrollTop=j,c=!0),o&&f>j&&j>=l&&(n.scrollTop=j,c=!0),p&&k>g&&m>=k&&(n.scrollLeft=k,c=!0),p&&g>k&&k>=m&&(n.scrollLeft=k,c=!0),c||(o&&(n.scrollTop=l),p&&(n.scrollLeft=m),b.requestAnimationFrame(e))}var f,g,h,i,j,k,l,m,n=this,o=c>0||0===c,p=a>0||0===a;if(o&&(f=n.scrollTop,d||(n.scrollTop=c)),p&&(g=n.scrollLeft,d||(n.scrollLeft=a)),d){o&&(h=n.scrollHeight-n.offsetHeight,j=Math.max(Math.min(c,h),0)),p&&(i=n.scrollWidth-n.offsetWidth,k=Math.max(Math.min(a,i),0));var q=null;o&&j===f&&(o=!1),p&&k===g&&(p=!1),b.requestAnimationFrame(e)}})},b.fn.scrollTop=function(a,b){var c=this;return"undefined"==typeof a?c.length>0?c[0].scrollTop:null:c.scrollTo(void 0,a,b)},b.fn.scrollLeft=function(a,b){var c=this;return"undefined"==typeof a?c.length>0?c[0].scrollLeft:null:c.scrollTo(a,void 0,b)},b}();Framework7.$=a;window.Dom7=a,Framework7.prototype.support=function(){var a={touch:!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)};return a}(),Framework7.prototype.device=function(){var b={},c=navigator.userAgent,d=a,e=c.match(/(Android);?[\s\/]+([\d.]+)?/),f=c.match(/(iPad).*OS\s([\d_]+)/),g=c.match(/(iPod)(.*OS\s([\d_]+))?/),h=!f&&c.match(/(iPhone\sOS)\s([\d_]+)/);if(b.ios=b.android=b.iphone=b.ipad=!1,e&&(b.os="android",b.osVersion=e[2],b.android=!0),(f||h||g)&&(b.os="ios",b.ios=!0),h&&!g&&(b.osVersion=h[2].replace(/_/g,"."),b.iphone=!0),f&&(b.osVersion=f[2].replace(/_/g,"."),b.ipad=!0),g&&(b.osVersion=g[3]?g[3].replace(/_/g,"."):null,b.iphone=!0),b.ios&&b.osVersion&&c.indexOf("Version/")>=0&&"10"===b.osVersion.split(".")[0]&&(b.osVersion=c.toLowerCase().split("version/")[1].split(" ")[0]),b.webView=(h||f||g)&&c.match(/.*AppleWebKit(?!.*Safari)/i),b.os&&"ios"===b.os){var i=b.osVersion.split(".");b.minimalUi=!b.webView&&(g||h)&&(1*i[0]===7?1*i[1]>=1:1*i[0]>7)&&d('meta[name="viewport"]').length>0&&d('meta[name="viewport"]').attr("content").indexOf("minimal-ui")>=0}var j=d(window).width(),k=d(window).height();b.statusBar=!1,b.statusBar=b.webView&&j*k===screen.width*screen.height?!0:!1;var l=[];if(b.pixelRatio=window.devicePixelRatio||1,b.pixelRatio>=2&&l.push("retina"),b.os&&(l.push(b.os,b.os+"-"+b.osVersion.split(".")[0],b.os+"-"+b.osVersion.replace(/\./g,"-")),"ios"===b.os))for(var m=parseInt(b.osVersion.split(".")[0],10),n=m-1;n>=6;n--)l.push("ios-gt-"+n);return b.statusBar?l.push("with-statusbar-overlay"):d("html").removeClass("with-statusbar-overlay"),l.length>0&&d("html").addClass(l.join(" ")),b}(),Framework7.prototype.plugins={}}(),window.Template7=function(){"use strict";function a(a){return"[object Array]"===Object.prototype.toString.apply(a)}function b(a){return"function"==typeof a}function c(a){var b,c,d,e=a.replace(/[{}#}]/g,"").split(" "),f=[];for(c=0;c=0){b=d,f.push(g);break}b&&(c=b)}else if(g.indexOf("=")>0){var h=g.split("="),i=h[0],j=h[1];if(2!==j.match(/"/g).length){for(b=0,d=c+1;d=0){b=d;break}b&&(c=b)}var k=[i,j.replace(/"/g,"")];f.push(k)}else f.push(g)}return f}function d(b){var d,e,f=[];if(!b)return[];var g=b.split(/({{[^{^}]*}})/);for(d=0;d=0)continue;if(h.indexOf("{#")<0&&h.indexOf(" ")<0&&h.indexOf("else")<0){f.push({type:"variable",contextName:h.replace(/[{}]/g,"")});continue}var i=c(h),j=i[0],k=[],l={};for(e=1;e=0){var n,o="",p="",q=0,r=!1,s=!1,t=0;for(e=d+1;e=0&&t++,g[e].indexOf("{{/")>=0&&t--,g[e].indexOf("{{#"+j)>=0)o+=g[e],s&&(p+=g[e]),q++;else if(g[e].indexOf("{{/"+j)>=0){if(!(q>0)){n=e,r=!0;break}q--,o+=g[e],s&&(p+=g[e])}else g[e].indexOf("else")>=0&&0===t?s=!0:(s||(o+=g[e]),s&&(p+=g[e]));r&&(n&&(d=n),f.push({type:"helper",helperName:j,contextName:k,content:o,inverseContent:p,hash:l}))}else h.indexOf(" ")>0&&f.push({type:"helper",helperName:j,contextName:k,hash:l})}}return f}var e=function(a,b){function c(a,b){return a.content?h(a.content,b):function(){return""}}function e(a,b){return a.inverseContent?h(a.inverseContent,b):function(){return""}}function f(a,b){var c;if(a.indexOf(".")>0)c=0===a.indexOf("this")?a.replace("this",b):b+"."+a;else if(0===a.indexOf("../")){var d=a.split("../").length-1,e=a.split("../")[a.split("../").length-1],f=b.split("_")[1]-d;c="ctx_"+(f>=1?f:1)+"."+e}else c="this"===a?b:b+"."+a;return a&&a.indexOf("@")>=0&&(c="(data && data."+a.replace("@","")+")"),c}function g(a,b){for(var c=[],d=0;d0)throw new Error('Template7: Missing helper: "'+m.helperName+'"');n=f(m.helperName,j),k+="if ("+n+") {",k+="if (isArray("+n+")) {",k+="r += (Template7.helpers.each).call("+j+", "+n+", {hash:"+JSON.stringify(m.hash)+", data: data || {}, fn: "+c(m,b+1)+", inverse: "+e(m,b+1)+"});",k+="}else {",k+="r += (Template7.helpers.with).call("+j+", "+n+", {hash:"+JSON.stringify(m.hash)+", data: data || {}, fn: "+c(m,b+1)+", inverse: "+e(m,b+1)+"});",k+="}}"}}else k+="r +='"+m.content.replace(/\n/g,"\\n").replace(/'/g,"\\'")+"';"}return k+="\nreturn r;})",eval.call(window,k)}var i=this;i.template=a,i.context=b,i.compile=function(a){return i.compiled||(i.compiled=h(a)),i.compiled}};e.prototype={options:{},helpers:{"if":function(a,c){return b(a)&&(a=a.call(this)),a?c.fn(this,c.data):c.inverse(this,c.data)},unless:function(a,c){return b(a)&&(a=a.call(this)),a?c.inverse(this,c.data):c.fn(this,c.data)},each:function(c,d){var e="",f=0;if(b(c)&&(c=c.call(this)),a(c)){for(d.hash.reverse&&(c=c.reverse()),f=0;f0?e:d.inverse(this)},"with":function(a,c){return b(a)&&(a=a.call(this)),c.fn(a)},join:function(a,c){return b(a)&&(a=a.call(this)),a.join(c.hash.delimeter)}}};var f=function(a,b){if(2===arguments.length){var c=new e(a),d=c.compile()(b);return c=null,d}return new e(a)};return f.registerHelper=function(a,b){e.prototype.helpers[a]=b},f.compile=function(a){var b=new e(a);return b.compile()},f.options=e.prototype.options,f.helpers=e.prototype.helpers,f}(); \ No newline at end of file diff --git a/examples/raspberry_pi_mjpeg_led/web_root/index.html b/examples/raspberry_pi_mjpeg_led/web_root/index.html new file mode 100644 index 00000000..0d257a32 --- /dev/null +++ b/examples/raspberry_pi_mjpeg_led/web_root/index.html @@ -0,0 +1,108 @@ + + + + + + + + + + + + Smart.c mjpg example + + + + + +
      + + +
      + +
      + + + + +
      +
      + + + + + diff --git a/examples/restful_api/Makefile b/examples/restful_api/Makefile deleted file mode 100644 index 97fcf3f9..00000000 --- a/examples/restful_api/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = restful_api -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/restful_api/restful_api.c b/examples/restful_api/restful_api.c deleted file mode 100644 index ff0ac83a..00000000 --- a/examples/restful_api/restful_api.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include "mongoose.h" - -static const char *s_no_cache_header = - "Cache-Control: max-age=0, post-check=0, " - "pre-check=0, no-store, no-cache, must-revalidate\r\n"; - -static void handle_restful_call(struct mg_connection *conn) { - char n1[100], n2[100]; - - // Get form variables - mg_get_var(conn, "n1", n1, sizeof(n1)); - mg_get_var(conn, "n2", n2, sizeof(n2)); - - mg_printf_data(conn, "{ \"result\": %lf }", strtod(n1, NULL) + strtod(n2, NULL)); -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: return MG_TRUE; - case MG_REQUEST: - if (!strcmp(conn->uri, "/api/sum")) { - handle_restful_call(conn); - return MG_TRUE; - } - mg_send_file(conn, "index.html", s_no_cache_header); - return MG_MORE; - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server; - - // Create and configure the server - server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8000"); - - // Serve request. Hit Ctrl-C to terminate the program - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) { - mg_poll_server(server, 1000); - } - - // Cleanup, and free server instance - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/restful_client/Makefile b/examples/restful_client/Makefile new file mode 100644 index 00000000..9a05d799 --- /dev/null +++ b/examples/restful_client/Makefile @@ -0,0 +1,14 @@ +PROG = restful_client +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -pthread $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/restful_client/restful_client.c b/examples/restful_client/restful_client.c new file mode 100644 index 00000000..ec73f894 --- /dev/null +++ b/examples/restful_client/restful_client.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#include "mongoose.h" + +/* RESTful server host and request URI */ +static const char *s_target_address = "ajax.googleapis.com:80"; +static const char *s_request = "/ajax/services/search/web?v=1.0&q=cesanta"; + +static int s_exit_flag = 0; + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; + int connect_status; + + switch (ev) { + case NS_CONNECT: + connect_status = * (int *) ev_data; + if (connect_status == 0) { + printf("Connected to %s, sending request...\n", s_target_address); + mg_printf(nc, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", + s_request, s_target_address); + } else { + printf("Error connecting to %s: %s\n", + s_target_address, strerror(connect_status)); + s_exit_flag = 1; + } + break; + case NS_HTTP_REPLY: + printf("Got reply:\n%.*s\n", (int) hm->body.len, hm->body.p); + nc->flags |= NSF_SEND_AND_CLOSE; + s_exit_flag = 1; + break; + default: + break; + } +} + +int main(void) { + struct mg_mgr mgr; + struct mg_connection *nc; + + mg_mgr_init(&mgr, NULL); + nc = mg_connect(&mgr, s_target_address, ev_handler); + mg_set_protocol_http_websocket(nc); + + printf("Starting RESTful client against %s\n", s_target_address); + while (s_exit_flag == 0) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/restful_server/Makefile b/examples/restful_server/Makefile new file mode 100644 index 00000000..e259c1b7 --- /dev/null +++ b/examples/restful_server/Makefile @@ -0,0 +1,20 @@ +PROG = restful_server +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. $(CFLAGS_EXTRA) + +ifeq ($(SSL), openssl) + CFLAGS += -DNS_ENABLE_SSL -lssl -lcrypto -lcrypto +else ifeq ($(SSL), krypton) + CFLAGS += -DNS_ENABLE_SSL ../../../krypton/krypton.c +endif + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /MD /DNS_ENABLE_THREADS /Fe$@ advapi32.lib + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/restful_api/index.html b/examples/restful_server/index.html similarity index 75% rename from examples/restful_api/index.html rename to examples/restful_server/index.html index 9051ff08..339f3c87 100644 --- a/examples/restful_api/index.html +++ b/examples/restful_server/index.html @@ -5,10 +5,11 @@ RESTful API demo - + + + + +
      +

      RESTful server with Amazon S3 integration demo.

      + +

      + This page demonstrates how Mongoose could be used to implement + a RESTful service that uses another RESTful service to handle + it's own API call. This example takes form data and uploads it as a file + to Amazon S3. + Open S3 console and create a bucket for testing. Fill out correct + bucket name in the fields below. +

      + +

      If you're getting a "Temporary Redirect" error, look what is the + Endpoint value is. It's likely that you have something like + BUCKET_NAME.S3_ZONE.amazonaws.com. Change + the Host field to S3_ZONE.amazonaws.com and retry. +

      + +
      +
      + +
      + +
      + +
      + +
      + + +
      +
       
      +
      +
      + +
      + + diff --git a/examples/restful_server_s3/restful_server_s3.c b/examples/restful_server_s3/restful_server_s3.c new file mode 100644 index 00000000..b6248ae6 --- /dev/null +++ b/examples/restful_server_s3/restful_server_s3.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2014 Cesanta Software Limited + * All rights reserved + */ + +#include "mongoose.h" + +static const char *s_http_port = "8000"; +static const char *s_access_key_id = NULL; +static const char *s_secret_access_key = NULL; +static struct mg_serve_http_opts s_http_server_opts; + +static void send_error_result(struct mg_connection *nc, const char *msg) { + mg_printf_http_chunk(nc, "Error: %s", msg); + mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */ +} + +static void link_conns(struct mg_connection *nc1, struct mg_connection *nc2) { + nc1->user_data = nc2; + nc2->user_data = nc1; +} + +static void unlink_conns(struct mg_connection *nc1) { + struct mg_connection *nc2 = (struct mg_connection *) nc1->user_data; + if (nc1->user_data != NULL) { + nc1->user_data = NULL; + nc2->user_data = NULL; + } +} + +/* S3 client handler */ +static void s3_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; + struct mg_connection *nc2 = (struct mg_connection *) nc->user_data; + + switch (ev) { + case NS_HTTP_REPLY: + if (nc2 != NULL) { + mg_printf_http_chunk(nc2, "Error: %.*s", (int)hm->message.len, + hm->message.p); + mg_send_http_chunk(nc2, "", 0); + } + unlink_conns(nc); + nc->flags |= NSF_SEND_AND_CLOSE; + break; + case NS_CLOSE: + unlink_conns(nc); + break; + default: + break; + } +} + +static void send_s3_request(struct mg_connection *nc, const char *file_name, + const char *file_data, const char *host, + const char *bucket) { + char host_port[100]; + struct mg_connection *s3_conn; + + snprintf(host_port, sizeof(host_port), "%s:80", host); + s3_conn = mg_connect(nc->mgr, host_port, s3_handler); + + if (s3_conn == NULL) { + send_error_result(nc, "s3 connection failed"); + } else { + const char *content_type = "text/plain", *method = "PUT"; + char date[100], to_sign[500], signature[100], sha1[20], req[1000]; + time_t now = time(NULL); + + link_conns(nc, s3_conn); + strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); + mg_set_protocol_http_websocket(s3_conn); + + /* Prepare S3 authorization header */ + snprintf(to_sign, sizeof(to_sign), "%s\n\n%s\n%s\n/%s/%s", method, + content_type, date, bucket, file_name); + hmac_sha1((unsigned char *)s_secret_access_key, strlen(s_secret_access_key), + (unsigned char *)to_sign, strlen(to_sign), (unsigned char *)sha1); + mg_base64_encode((unsigned char *) sha1, sizeof(sha1), signature); + snprintf(req, sizeof(req), + "%s /%s HTTP/1.1\r\n" + "Host: %s.%s\r\n" + "Date: %s\r\n" + "Content-Type: %s\r\n" + "Content-Length: %lu\r\n" + "Authorization: AWS %s:%s\r\n" + "\r\n", + method, file_name, bucket, host, date, content_type, + (unsigned long)strlen(file_data), s_access_key_id, signature); + mg_printf(s3_conn, "%s%s", req, file_data); + /* S3 request sent, wait for a reply */ + } +} + +static void handle_api_call(struct mg_connection *nc, struct http_message *hm) { + char file_name[100], file_data[100], host[100], bucket[100]; + + /* Get form variables */ + mg_get_http_var(&hm->body, "file_name", file_name, sizeof(file_name)); + mg_get_http_var(&hm->body, "file_data", file_data, sizeof(file_data)); + mg_get_http_var(&hm->body, "host", host, sizeof(host)); + mg_get_http_var(&hm->body, "bucket", bucket, sizeof(bucket)); + + /* Send headers */ + mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); + + /* Send body */ + if (file_name[0] == '\0' || file_data[0] == '\0' || bucket[0] == '\0') { + send_error_result(nc, "bad input"); + } else { + send_s3_request(nc, file_name, file_data, host, bucket); + } +} + +/* Server handler */ +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; + + switch (ev) { + case NS_HTTP_REQUEST: + if (mg_vcmp(&hm->uri, "/upload") == 0) { + handle_api_call(nc, hm); /* Handle RESTful call */ + } else { + mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */ + } + break; + case NS_CLOSE: + unlink_conns(nc); + break; + default: + break; + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + int i; + char *cp; + + mg_mgr_init(&mgr, NULL); + nc = mg_bind(&mgr, s_http_port, ev_handler); + mg_set_protocol_http_websocket(nc); + s_http_server_opts.document_root = "."; + s_http_server_opts.enable_directory_listing = "yes"; + + /* Use current binary directory as document root */ + if (argc > 0 && ((cp = strrchr(argv[0], '/')) != NULL || + (cp = strrchr(argv[0], '/')) != NULL)) { + *cp = '\0'; + s_http_server_opts.document_root = argv[0]; + } + + /* Process command line options to customize HTTP server */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-D") == 0 && i + 1 < argc) { + mgr.hexdump_file = argv[++i]; + } else if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) { + s_http_port = argv[++i]; + } else if (strcmp(argv[i], "-a") == 0 && i + 1 < argc) { + s_access_key_id = argv[++i]; + } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) { + s_secret_access_key = argv[++i]; + } + } + + if (s_access_key_id == NULL || s_secret_access_key == NULL) { + fprintf(stderr, "Usage: %s -a access_key_id -s s_secret_access_key " + "[-p port] [-D hexdump_file]\n", argv[0]); + exit(1); + } + + printf("Starting RESTful server on port %s\n", s_http_port); + for (;;) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/rules.mk b/examples/rules.mk new file mode 100644 index 00000000..0d40124c --- /dev/null +++ b/examples/rules.mk @@ -0,0 +1,13 @@ +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -pthread -DNS_ENABLE_SSL -DNS_ENABLE_IPV6 -DNS_ENABLE_THREADS -lssl -lcrypto $(CFLAGS_EXTRA) $(MODULE_CFLAGS) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +$(PROG).exe: $(SOURCES) + cl $(SOURCES) /I../.. /DNS_ENABLE_SSL /MD /Fe$@ + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/send_file/Makefile b/examples/send_file/Makefile deleted file mode 100644 index 4c20d6ac..00000000 --- a/examples/send_file/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2014 Cesanta Software -# All rights reserved - -PROG = send_file -CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -all: $(PROG) - -run: $(PROG) - ./$(PROG) - -$(PROG): $(SOURCES) Makefile - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -win: - wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe - wine $(PROG).exe - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc* diff --git a/examples/send_file/send_file.c b/examples/send_file/send_file.c deleted file mode 100644 index 345c3af6..00000000 --- a/examples/send_file/send_file.c +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2014 Cesanta Software -// All rights reserved -// -// This example demostrates how to send arbitrary files to the client. - -#include "mongoose.h" - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_REQUEST: - mg_send_file(conn, "send_file.c", NULL); // Also could be a dir, or CGI - return MG_MORE; // It is important to return MG_MORE after mg_send_file! - case MG_AUTH: return MG_TRUE; - default: return MG_FALSE; - } -} - -int main(void) { - struct mg_server *server = mg_create_server(NULL, ev_handler); - mg_set_option(server, "listening_port", "8080"); - - printf("Starting on port %s\n", mg_get_option(server, "listening_port")); - for (;;) mg_poll_server(server, 1000); - mg_destroy_server(&server); - - return 0; -} diff --git a/examples/server_data_push/Makefile b/examples/server_data_push/Makefile deleted file mode 100644 index 8e19d30b..00000000 --- a/examples/server_data_push/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015 Cesanta Software -# All rights reserved - -PROG = server_data_push -CFLAGS = -W -Wall -I../.. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS $(CFLAGS_EXTRA) -SOURCES = $(PROG).c ../../mongoose.c - -$(PROG): $(SOURCES) - $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) - -clean: - rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/server_data_push/server_data_push.c b/examples/server_data_push/server_data_push.c deleted file mode 100644 index 3bb90bfc..00000000 --- a/examples/server_data_push/server_data_push.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2015 Cesanta Software Limited - * - * In this example we have a background data producer that periodically - * produces a piece of data, which is then distributed to all connected - * WebSocket clients. - * - * Data producing thread is outside of the event loop so synchronization - * using a mutex is required. - */ - -#include -#include -#include -#include - -#include - -#include "mongoose.h" - -static pthread_mutex_t s_data_lock = PTHREAD_MUTEX_INITIALIZER; -static int s_data_version = 0; -static char s_data[100]; - -void *data_producer(void *arg) { - (void) arg; - fprintf(stderr, "Data producer running\n"); - srand(time(NULL)); - while (1) { - pthread_mutex_lock(&s_data_lock); - snprintf(s_data, sizeof(s_data), "The lucky number is %d.", rand() % 100); - s_data_version++; - pthread_mutex_unlock(&s_data_lock); - sleep(1 + rand() % 10); - } -} - -struct conn_state { - int data_version; - /* More state goes here. */ -}; - -void maybe_send_data(struct mg_connection *conn) { - struct conn_state *cs = (struct conn_state *) conn->connection_param; - if (cs == NULL) return; /* Not connected yet. */ - pthread_mutex_lock(&s_data_lock); - if (cs->data_version != s_data_version) { - mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "%s\n", s_data); - cs->data_version = s_data_version; - } - pthread_mutex_unlock(&s_data_lock); -} - -static int ev_handler(struct mg_connection *conn, enum mg_event ev) { - switch (ev) { - case MG_AUTH: - return MG_TRUE; /* Authenticated. */ - case MG_WS_HANDSHAKE: - return MG_FALSE; /* Let Mongoose complete the handshake. */ - case MG_WS_CONNECT: - fprintf(stderr, "%s:%u joined\n", conn->remote_ip, conn->remote_port); - conn->connection_param = calloc(1, sizeof(struct conn_state)); - mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "Hi %p!\n", conn); - maybe_send_data(conn); - return MG_FALSE; /* Keep the connection open. */ - case MG_POLL: - maybe_send_data(conn); - return MG_FALSE; /* Keep the connection open. */ - case MG_CLOSE: - fprintf(stderr, "%s:%u went away\n", conn->remote_ip, conn->remote_port); - free(conn->connection_param); - conn->connection_param = NULL; - return MG_TRUE; - default: - return MG_FALSE; - } -} - -int main(void) { - const char *listen_port = "8080"; - struct mg_server *server; - const char *err; - - server = mg_create_server(NULL, ev_handler); - err = mg_set_option(server, "listening_port", listen_port); - if (err != NULL) { - fprintf(stderr, "Error setting up listener on %s: %s\n", listen_port, err); - return 1; - } - - mg_start_thread(data_producer, NULL); - - printf("Listening on %s\n", listen_port); - while (1) { - mg_poll_server(server, 100); - } - - return 0; -} diff --git a/examples/settings_panel_for_a_device/Makefile b/examples/settings_panel_for_a_device/Makefile new file mode 100644 index 00000000..eb3fab97 --- /dev/null +++ b/examples/settings_panel_for_a_device/Makefile @@ -0,0 +1,11 @@ +PROG = settings_panel +SOURCES = $(PROG).c ../../mongoose.c +CFLAGS = -W -Wall -I../.. -DNS_ENABLE_SSL -lssl -lcrypto $(CFLAGS_EXTRA) + +all: $(PROG) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) -o $@ $(CFLAGS) + +clean: + rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/settings_panel_for_a_device/settings_panel.c b/examples/settings_panel_for_a_device/settings_panel.c new file mode 100644 index 00000000..6772075a --- /dev/null +++ b/examples/settings_panel_for_a_device/settings_panel.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 Cesanta Software Limited + * All rights reserved + */ + +#include "mongoose.h" + +struct device_settings { + char setting1[100]; + char setting2[100]; +}; + +static const char *s_http_port = "8000"; +static struct mg_serve_http_opts s_http_server_opts; +static struct device_settings s_settings = { "value1", "value2" }; + +static void handle_save(struct mg_connection *nc, struct http_message *hm) { + /* Get form variables and store settings values */ + mg_get_http_var(&hm->body, "setting1", s_settings.setting1, + sizeof(s_settings.setting1)); + mg_get_http_var(&hm->body, "setting2", s_settings.setting2, + sizeof(s_settings.setting2)); + + /* Send response */ + mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%.*s", + (unsigned long) hm->body.len, (int) hm->body.len, hm->body.p); +} + +static void handle_ssi_call(struct mg_connection *nc, const char *param) { + if (strcmp(param, "setting1") == 0) { + mg_printf_html_escape(nc, "%s", s_settings.setting1); + } else if (strcmp(param, "setting2") == 0) { + mg_printf_html_escape(nc, "%s", s_settings.setting2); + } +} + +static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { + struct http_message *hm = (struct http_message *) ev_data; + + switch (ev) { + case NS_HTTP_REQUEST: + if (mg_vcmp(&hm->uri, "/save") == 0) { + handle_save(nc, hm); /* Handle RESTful call */ + } else { + mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */ + } + break; + case NS_SSI_CALL: + handle_ssi_call(nc, ev_data); + break; + default: + break; + } +} + +int main(int argc, char *argv[]) { + struct mg_mgr mgr; + struct mg_connection *nc; + char *p, path[512]; + + mg_mgr_init(&mgr, NULL); + nc = mg_bind(&mgr, s_http_port, ev_handler); + mg_set_protocol_http_websocket(nc); + s_http_server_opts.document_root = "./web_root"; + s_http_server_opts.auth_domain = "example.com"; + //mgr.hexdump_file = "/dev/stdout"; + + /* If our current directory */ + if (argc > 0 && (p = strrchr(argv[0], '/'))) { + snprintf(path, sizeof(path), "%.*s/web_root", (int)(p - argv[0]), argv[0]); + s_http_server_opts.document_root = path; + } + + printf("Starting device configurator on port %s\n", s_http_port); + for (;;) { + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + + return 0; +} diff --git a/examples/settings_panel_for_a_device/web_root/fossa.jpg b/examples/settings_panel_for_a_device/web_root/fossa.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8450ccccded458561f828d49d591babdad6a0da1 GIT binary patch literal 16584 zcmeIYcT`i|^EY}z3m_s@K#Gwdz4sDOI-&P22q8cO5=cU~P(%>{DbkCebOfY#1?gSs zU6dwO0R>T%8}unY-}T)0d*8c$|Gn>FWoORpna|AZJ$ud^R*ol+7XTV<4Y&pX0)c>T z!XI$FMeJ(mios)Wt{6{}Apr;%u_znJ8X#u9sL4hI07L*08<816q-DTH zWC)P!sOv*i47Bvwh;YDpYXbva15LQ9vM$8LKozcTY6UUSfS4%jL)75vngoRafXYl0 zVrtCKZ(^v*&(B8W2ik$7Ar27F6Wb6^EXD`rgmi*9`a|%pNQgBC4Fg?D2fYtV9GeCP3nUn*Phki4zbM`fsbk z1YHyk;_Tpoa{uWM!2uTx28V>4a53I!rxWoL_X98(9vnmm<%@!tVjWQKf)HOZq67suM44UA{ zFVlpm^&FfWTpVx&z(4Gv@IUPklu$T#0v5q3cL%Hs5{EyribnZhumn)}PboCU7lOc` zafEHa5;lUc)JU|G1KQ>19nKR;*ae(0gjd-R@-tmT{_7U$Akh#Nj4PTC!p{%UHy~t# zuDS_LvJs&H8fBA{{82VlSA!TDtDBgx5y1d5F&QyQ zNrI?7K%}b7Mx=D2E+!!=B|+f10Av=HCK3`7Y(%60g@%ENi892{%#e+U7tl2{HZX^) z5ujA8Af{UCkpGgUf`54_2r)5L)>nfl>l)~*LkzVHObID`2{!cgD63hem$awNy6kQpzax@_tE$=)eA9sI zsuK<(;bd_stEs3H(Exx48jm&BRDoDpSwp}>00^K3P7y|72L#Sj+0amza0mf3At8QZ z|6|x6C&&@55up>Te@y-N8%l&H7Ecg6B7C@=kT?VYfVc>>n=jszzz4+;Xa+~OpLEU% zjWsn^CGhJAG_}hwnovssYR6yn1VNB_e`wT_0Msaa32Sv`-4x&2hcfy z^rs9!bQ{F_7aa-W{Y_WwL>GV%^6()@{3p#opsPR%KWPdA-5rwrlLiy$;kzi{HIat!>Ny}#=#%Dx4>+mW@}g4m5~2_> zu@gc}2Kcjy0Dxc500I^nq1X`e3?LB|7Z-~m{xctmd1FZaqG4H}U-^4{OgJ?}f9505 zo<;l@?MJ{M*c6qP7nPM4BiNLY7n78i6#d-~Q8{@DNqH$r;P@>?jVm7SDK8>|#tA!| zR2X3d#zVxfb(Ab;Yh5lS=`<%vfT9{MM^4vrXaydo#(iJ`x)Uw;1VuTFZq zzs&t3z`v${hWT#*gs}fz_0P5WHzg;;Upk)NSofc?IUz)l?nnB!b7V zzxNkxWP6kh2++rEG3{}TCEb!Bh7 zD+Y@*#NbdT38SQC@Vn-J&i*Te8X-niERrxfDV>xHAyHW&F;UY$%f;__zl;7WmI=li zOW551(r5k-`G>}DXoT}7|I42fa|D;fB!onzgd{{w|EyMo{!?C56ejW?lK+N*!I~1@ zq?Gd{x>u6-;?en9q}lP-Fl*coG zDnLSfauG%nG7`cEOiDsR3MMBb1Cx=FQ<75=r?H~|5Xkdl&v$-qy)DK(l-e600}KA-32jaGI}EiFsB!T zcyMesIaH;*mC^Y1M=l9RYzPJASte$da~HXJc=`AxrKDwK<>Xb>)HO7<;MyjpX66=z zS4jk+db+rxuHo?BKE8hb0in0U?%WN(7ZDf#Fd;E1IVJV+lbqbV{DQ)wipr|$n%cVh zhL>&a9i3g>J-x#tqhsR}lT*`g-z_dJudKdbTi@B;`}BGL;LG9Hleh?7_^+`3itIn) zA}j)kh=i~oC))vlhvj1;^h5Y}D?61K7j%ymAA|||4(-PAHmw=7xKzP=@Ql{9*g->Oi+N;`f z8{V1TSDP<|?-zOsB(F=l$$FHWv%n-jNRvvV1J8u)ZSRJXU`P}zBUlm>g8!D)l%f>Pdi7PxD>0;#v*)>b3~7QHT!Dek1tlWcvuh|9oFE+Dy^F z0Z#P+nWR(kDyJ@Em?2mOE_s{3C^{#8_+gUqlhV5n=Z-u+YCNn^!w(pk8RmAhgM<)B zlBKTIt1s9JAp!vhr7qz*c^St*$uUrx?=Bj(z4hh${xNV@;k$K@M~<4gbF`~toigWU zEFyy>g5AFj@F#wu{l0qqF6+US$PGz_dzh4m2*qat>e({&1;_|3ZP~4%>eFEn(g8oR zbDk!Cy`By6-6Mxy5;J`MJc2LpRd{t@k{>MW@a~%JaCBagHFGS%4v0$ZQSx|V1Ltzz zdAUVi+bzWhxd!~M3@K)tbkn!yp0C0(MI}<+JJN6{Vw?ku71 zORM<-=T619KV9hIR*AlK?i#0r@OFx@X+ig(o*RR1@>=d5gBCSMNsJy9?^+`B=MtJ! z&bknYY9YXPbd7Vab5om+4whx#pwQT?>K77cF|1@*EbLyX(n?F+?e08FoK=W~!lplHx)}Sd%~wyc zOmAjW#idNoQt>VoE{$lv$EfV}?vy2xu@)$eIn5S|`L#GJ`mY3AHoGI-Zgd27A2#2j z)C-Z=hVDU~jNzMSuHD&|G{}>%5$NKvI|j4|5=*g4(mNf4!KG{Ggc4IHCgcl!_9z_K zj5NAa4pq-O4l3D^&BnDc7~fBrLh)qxZA>2n?FHTxl9OATDes_UmDSdq+ zL9(>@{G-EEm58+08KrkUyq-MP#32-C(=NLe*T-2Q9nZ*KHpTT&0>qhlO>5>W34>oo zmd#~KuZDPwHP`Fp3#=49k5{90{n`}F&Ofj3d^;G^rx0{8Ev2?EjLzGqK& zU-g>~IN#V>W_@3uC&hZlrAli%F7n1mYlqpOsp)S#&-Okn&wS? zw!B8kTmQ}t|3FWy0F;*g;94K~Y+lsPSwk20oSd4R6a#8(ec3CNqTqFPy@A4{0RO0N zwy`?;ezWTOz69tayUBtj{sXD(Y9>`mi6PFs#}(x9b140oNAW9)dQKU=SFSxK57afR|>zD{|ZkdFLMVfx*4H@b0(ftU%#(efIiP+7O zIX(4Y>Pg+(nYZ_>Caa-wUt&*xfBMzDHU}=1JJ8Tal~m)#Tt}(f!n#s%mcXb_es` zgOrcU?-w3v8Bnc_+cCV_j5{!|twoLsmy|28+-qwpOyK`;5K_=;c7Z8kx=E>0pZ~|r zvi_GD>Kf={;A3C+d-oFWLVULr9P@gM{j8bclRyfFtJ{c}{7J73d)cM<O63W>kNR25anq?|u4iv6-3}bulxC zJ#TvbwLsU)y2CDms|L*1Ht%~nOK9g9xSB=3BaKsv<8^owB5`FOmZ-5u&g>EyVCHD>+2WMy6&UIk!gz2Bs@(NPaS29{Z?I%^?H!v?=8$ZTTEf^RbWj~^7&@O)%Cl#rF zk0HTRw8blaq-?yr4VmCN+E{sI;xo3Kx!W`>@rR4x*+oM?G`-L3Rz)%idn@vs2PyHR z@0DI%e{eB;F7jLrXH4V;S;cF@62?RA*66!?Z+c^eWvOl=9w?je*4V17zSBs+vN#0i zT&XA38k}`XzaiI&+cMg;$8I9#ujv%d=6I8t#j**6?c}*MR~9M?9%7EJiSmVEPcYp;v7m%|(o)PSujZv_ z1&+=zI)AIcOD^f960wb3hzQPlP?j!TpN%aGK5itUxXR|cf=PYIIxP-eRKoDK5~2wvpOUlX zc=E_-{9aqam4GC$kKWmA-+aCOxX0W5GGEOeKD7}DxlOf-YJD5b4#2#uG#YiMUhBDf z$INLMOI6^6?nTSgVjFeT)}`YV*gQ2$ZU}PcGEA5(ud8?JDTRuFlP$pcM%G;FJ&1(F z+2B47@OV`P&16p9)Sin}D3a~^Ih;+RDV!@>t76il!#Ni@@=ejsBnEZ!LfEm zLZzZ1WO;|xy|-4S*RLB!I~tpLC$-Q^(yn%V`Hq~qctw@LJvN3L?Q9ZaaxH9hWFRQ> z=Q-V;C$|hnAJ;|5g$iD*_e)w?h>Zg-`F^Qq6REzIhven9jq`(w9XX$SFll)wEZFfh6LH>; z+2-01_)?9>WaqM>X#tn;Tvlukq*T;z$-A&#eX>cDD%^VZ*##Vz9tD~xG?EWeI7q>) zC=SY-yB&Km<8xC?TD{*x`OtGm9l>&MYGG6#Z%K4qge(iEm^zws3`Qzj_~S*~X}UF$=9x{@Z z* zSX!>S+d;!E#5BYq%)E-NL)=X;BqLMJ-Qv5&0_^TJ4NbMQGgGLM?tUHHrtq00-z;eQ zNBGck>bpqCh77dFw#UHRD98Dhq1*Rrww?GXY%}ZG#a?-J;pVf)#=8r;>fg?beHnQ2 zg>(0cf=0z%^KtG-fpt%9Ybn1R(vmlj)%3HF>-Egs&70ipb@K*4Kpo*_y_@m7n}af% zUy2LiH++>!n37O_!-JeX3GXcW`~x4Jp5%FjU+^ilRVTfL-)e(bJKs>un(6U)n{jq< z&CB=nLmkh$R*UP;N4B$r%5=csb7BVN3yV&<)_T-&B7xITZixaLC3s<~8D@#x{6 z3AX}M_9-rhv}N?W%Gt`Kx}EP$+Qr{vVGl&#UO*xz&j>ZQKx0Ruy}G29Zy4v}X7*oi z8rJVz3M&)VoTjt!hk6V^Ta(A$1YP-h9u4PsnQdIm{z^_crMAIQ(D7@h7P2b#`iP*7 zmOGt(KU)a-Y0=s4K57ZBNrs9D>$cqRISQJ0+~SwUX?_Uevcq=JZj98@l%j`cp**pxs&AUSF^=(N`wDPJL<9eZ1C+stuJhQ4dZB^s2Mb5{E3 zP^jmd)ckTUh^i>NSBd$~^yL;F(#nV5QFGzf8yfqExCBnWyd#j{eqpvzhBHyY^X3QG zGZq%et5=+J&!66r5Pv#6*!!3s=7&`#t(CvZO}^c)I!-7BbJ}mAIS54%Wpoq^gT;TPsz>Z3{ATf zD_y3=G~18EXSm&G=Vf?;0)oe%2h!d)cssJ|Qm9{Clb^R?r|@z9MZUe24Qpbkkt##c z)2qF*OM*`lm=__Tv*#A`DNGWko|bU=!5&p^%GAD@PL!B|p*NxDic=6_Hj&BMGpimX z9_DyrAU^eA4Po~5$MSbquipFU4e!xScO{B1GHqC!d7-wAB=i2rJSWSyd+{XOX2d?j z#H2jH!d}E$o8kV0lv?!M#44tLwcRm85$g85xtV%7|AL%cJo}A}vDihl=-EtY9d5(; zEN7f}K?Qxf&sS3|SNmG>A6Ie?-c@4xpxhhqGaSZm&BEzUN09H4Z!*w->h9Vroyo0l zwBVclqP<}puFA1yty_1`@v1&Km5nDry*gfjy?4E=aA5Ae^=jDCu7}t@eE<97sVOIO zqgIf`1+5=+XI@CP%6p~NH=wzUY_no``A!WgnE~*|5HJ{^nT?U>@Mm|hQ@FRT_dV_O zC?74Znf6}&OakcxIoMS`W{xk+MXQYWE|rfth!0iObs}fG(!&N{_jJO0SX#Rom0k&I zI9OVnCNtd5wt47#7#Sh!><~l~M;W|#c6HPYNAZMOGG?&Hhe6L%S;H$ha%(D`iqB4K z+h4X=FQTJ<^CH}HfIr$?^1Li-VB!+hPNWkM;PSYxy>fW53V~ay8C}qcwxSA;Ac)&zgxpix<5NUF5tMl@qFNfCyqg2}tI&!n?^?8>c^QzGlIyAED z6wAn=bJ8OhLnKUd1gK3U$Hhdun>bS{0_IUkNko@AEcgg@5$}SND>f!Q~FsgS`sfm4eL(_nJ&bH?~ ztGysGC`P$^olJJg%hEJ23IToHB=e5l#;PUSDwTnC%94ht%zY&F0}F_}Cl{cEuP(l@akzqWQU7RTq+RiPNlHR+@J9%7W?92qs({+gf^ zQS~tp4O3?uulaf-(s2bJyArX8+caZM2vYAhmgqz91RK5@r471{dAE3{E^&~L89lwz zcOINae0A{+LkZnOtIdJ@xwT?qlvhkdr=e*%;=w}>&3^ElEj5@YB78u?U!#+DVzr)I zx-xERYF-YC;&K)|kAk=?gIR!E)?+3$ISm=4^{7&)^cGQdL(m3`qp^y?K+L2-%b;8< zPjHLeZmQiXUqN|You6aG_?SvOg{gmz@crGlb%v|o-y|_}#^+~KYf3)n8pGE}O#k@7 z>g0kHsMjCNFJoE1OgvqQkEu^_YY0P<4xU)W%TOrWUaDzR8@h#Rk%25uufJH@()dE~g3=(`zV9hTKN1}0J_1iu>fNAWhU z*k@$ZfTD(|EDyw_?jG{>(``XI(m?-J@w-dDA`j%s~*6UpgHWn|L5K zqw!i(3NGC%KhdTzK-cPhD#|-YIfbj{o-v;w7sp)=FYGzr2Qw&bA_v`2C+mrA^qRi=}Bx{F;(-&^47Err;jyLnSB-af`p z&->1~6KQQs)DM_M!dG1EbGx2w#A#ws64tq+6auz0eb4;0vA)u9j=B%F-t4ijPi3Th z)JxWSqd76P>2&4&UT1uHABQT(tfzv7@Ygh)qyetTex1o{wh#8~&Gi+n{VhlG&dngO zV)@2=jgGQ3(nh_ov*SX#_LU6#Ek2fqEc%wkbQH4hsr3U8jE_eO&lpqCp6j2k>;=V( zQ&3zKS3b1F6Bo`>Y}%0JcDCtuHq}@m_8j8zabhm~TI8TM7dAi>@}N(Ws(TF$_ubiHNwoS3Zt2^_S3FqKvjdftE%jf+Z>bq{f z2~L|7^i2E#jNzHxF+K^^4ahh?$M?R{%w+7}WM1U*R~wq-1!P9KKht%0w$e;wDE&A{ z6elW!Nc`|)h-Am^dY(7$4DMNoWVlirtFAxx?usF+>~%K8`SyHvzYkXRlhq8g<^*d$C1_RKCbj1kW?DEI8h}Q$zn^ADsO{oZ&YeSyJWGETGQiPT9|WH|D(t>~2rK z35GUSiHniuu&&JBw3i6-<;hyWb(3(+I`GcEc6G5s<(5o6(TG;NU=Q0`?|%x~SQ~++ z_KKq>Ygvnv&wlK4uV~{6qon6TN3fV{v~tl8>0j<-41$=iYv`TL9f_0ncTb{xZ_mQ* zXn2*rF24TW;a%_pW$mv~r*O^%udI*4qxu-_v>O)Lch=IqS^e%Scu&v4)N-m7)8JwYw{XXYF{;9xHNs%oR=z~edlR>@AhCGYyl1-;X6M^ z5=2cVTYBH#to&g@_~&l!;Z&c@L$gH5SO+t1jlEN+8!G}xTcPZJ@AYU7_9s4px6^fd zR^gue9A+i$x20MrVwljOZdj1EG)rnUt8D_7FU2^s4$<>qV#k;B_ zV`)^Dwy$c4vI-io$hJUXb8zMF#WuO04i7j_m!^GQZze;@OFheo72>L{sEJkWb6wAV z7?TBWDpy~O5 z=e*XDo!x(W-@rd-RF?h=uw@DMF>R@&qJ zet$l;B53C>luP^}b$?ngLS-)?97?d0&t;-=6&UPQ+8jYjsM4z7vI zmF0cwGf~w`aHix5UQWwb{MixGeQ1&H)6voki7k>+qj3j!y-Dk9?klJGK7#4ERyycU zTq)rIK_S=sYL^H7xtlh1<)0MYudI~W{`AZ_;@hAQU7S(qS=OYitAQLEvTKUyZ@YLP(ai?eL%`PK;<~LJkH4<1@kP?egdxE`rjfuExNVuS z|3bj{jx$zZ_Wi-5<`k=E-Q8#A&+`rmjM7iU9&M;~JFZp0-FW)bYBQc}-{lXzkVY)a z(xqqshK<>p%c};WZd^?gTOEo`oqBaWtXpm_bBS%~^Lv5JB5TWW67vSZ53E-cZ{%$9 z*DpqvcjAW7H#0QshC8sfahTHz4OP)EX}VR#W1bGP#i)9B*>^#{4ppy9>Eh>E1%Ucf z%`y$0tggy;zD+_S7dXCY5+&6NOi9F#RX4IrnOfDMUY1(@glWt$>k|`cLOAA|CUlK8gfcVUW|*kH-XzUv9%x|H6xUwFc6-Xs zG_su9-Id#Rdod+ow<_V0BHwWggf+q6jx}3B@0;=~hgpbsNJw0Oq6UWn$c@=Ei4pjv z`P9-pT%3+cWZZU#WMkd-JX|E#<0WRkGL+@}q`4eB#X=vH)rI+%MApm)1y;t6)v#MR%@lwgan6> zQ40*W?U@-Q2wf^|V3V>A9UXkOb1U>SL-_Pubt8Ir^opv4cG~4RmM(>4wrGPFsy2gR zYWqjJV_K3Hfp1Qg7VigMlK;AO=Y!Cr&DZ69Y+^SCf**?9?kF#kG8+y$)pS!=d zr1M4i0zUl#r&fL(16xchy@RY#*boVAtc_-+ec_qr&Mx8N+)j2(azc1Fq7K^{{Qj1Y z%vBm0xkG=_XlgR!i1T-CA;JR#oO8b`l*zyozq#=+?^%5HR(B=&4+& z<($qGrFc)-l66V#lw@IT)5}9bUX6k%n!yOkhay*Qw8R*Sa>E*A8ycrs9mDR8x z@4WKiZdq2u3Tqt|hS{8Mn$|BmC`eabe=+WI=jGqA|U4AgW7Nj+q#?H>i1Sr7#@sj-vF)Y<}#g zE1iP5(3B{5MOBBT8du%DL?ljrK=Q+TsgIHSE3`)PY2@dT?bo@M5Su%JpoG&ybO}ZUE;J z&T{q%cWO9PZZE4kDzA=}UMz_Ph|K8CT7|CI>n?l0I3kL_Lh0)(ZxG}0;ZtB*T3rmR zRtOTsh=hb84aHurx}lMSU=p(qwkwJ{ugG67GgA%yHv;| zx=P#=zNXZm*3BEFa;tFqv2%@Kv7AwT1xC!XQ(Wg0DjU7l8!gy(Z6}1P5CaaRRXE!Y zs_|N;Ge06Zlxr9kYL;y?&7Rw<==}Ei79hUIHeBPp$!S%jPH@8aY@e&cwUX-Qt4w5)4mv$RJ45&vC7fm*UAWs6u!4rhA+uQ z*aWhuAxn9Zo9ublqcWv~ZW_HThk>kQn-9(}NZ+Ejd}44Wwc_OfTP0bD6>Uuc=*pAJ z(g&0{%ifg7@h%1~Jo_K+l$5g6Xr0sYxKH$=@peXbWj7ZBmMJ!oy0hN;^2ufZJ|~xS z)+Z|GjUEnzpl4G8A%a*Hnes8Wu4(&7FDnJ@Slk{~6o8-gEuXQooZQN!fJUpwT7Fpc z6J$on+P@eXZglOrF5+8;*;w%(L(e3sZTeTeUJuH-k7MKJ-D49IaQC%O{-97>6dL(> zaRrts@SKllcFCiHzKKn6{=Re+z^DZ$EwBS(RI?~^N zrHnb(9sBZV8=yMdLwrjp=5k93>LvVh%|YOsqo%uZ>Sc;0!)@+O^zXtfi6$lAsh&I3 zjqnN5k|SoL!@Y_Lj25_ctuduQYUJytPSF>0MKazG!kl^|0!4l93=Oh|n#ruPGwHN3 zlk8E*E!$7Wz@0-@*^6bL_Y^U$Z|JIdUcG%_a!RTn+)K|HQyP&~NU3$IwbkqpOR=tp zm2#FW^?w^`SV^lYHP_MjwBLGOgK~{3XiMuLS|X}ntMjIjT~SqRTM<`NaNPOwl8)wH zaetQqgLw+JWh-0JX@*Y#u8m_98?o$RU{GDoxze+wrgBfzk-{QO$zLV7O-unxe$=7= zq(MDHpxxYOKhtcFZoe_d{6cO@Xw;-nM)X!X+isu>Q4-{^@hq~js-Y&(1}sD6w1@8P zF51r47=1|7&y*e%wETdF@m&7RusJD5KS8e1s3mh&MCOIP6)D#k;K|AbeZQsX{HW&B zGDg|FPsH%2?jbT#zmIca5)~h7P#w-v&pMm|`!8{jzvpWRHR4mw6+|uf30zT`^wuh+ z<2IIaG)h+rBqN57FdWWscPB{R7kDH;uRxLGAL{V#7=YI)KT3!}29%NB)u*P`DtwsR zd<+;g<;3Po$7Te!kCT2__P3UUW$@cFq5 zJxlRDJ)Jk)w5B$lM})crEsV;k=-xS#saSd#>JxSP9e|aZ3+pD;YR@^D6x+-RbRt=y znXrZeVp#BNTq`usZ$MM!wf-AdTkkj#&z{w1J7K+LRgtSLKEnhm7Onq@r{P zKe1_JRbt&a9oA?21+}HiWFq-BEJw+bGT5tG_K-pJFaehyqHu0k%+x928|wS5l$pDa znq4ML3SL!z=bp!>YRsD@Jd}nX-gp2Ue8n@i7MpLk5ipp-Jv;Orq@9b8~rLzQ;SsVh=t zAGR-R32ibk2+$0^<>M-seScYQV>fa_uwW?j;2`iv;(PC+nB|5qjriL5b>HF1YfNjT zxi#tI4M)M}hD>BQZd4hTe_yOeUM45W8^}2e*_A8xKBavyQqvh%=(kmdJqC_0sO;p{ zk9{z-dTVV$MdL3%i)G1y70NALnj7MBE-YrT%`fpg*FLK@;4j^I&l<|GGo7t65JJoJ zS(fJ&m9fPp6Kqa!+g)-ha$@&>ca8zSq{7UDG~q!CLD1o4bhDRDLuxS#?^Kp0Vdp+@)F}-gBLS*n%`zLMDHELJ%oFg*Rnx>4=*D^fiLTVt}m)L=`9g5c; zDHCL*&b(LjGOl_wKCjRF@Lo6{<`L?Bz|zqyE@DjKjluf6dhLz2X4VV)GTmsu8$flAG)c)nb( zgHG}-OY06Q8TyxoGtWerTNDmsYI#7lPP7M?Nycsai=mNqsVn2ln4`pRYS@&pS+BaN z^P!3E9>g5^d47cnx!${M7+h2Ji;silr^t`$M7X@2tz`7@W$N5Nc1YWc93%g)o_>pK>_ z3b*Xj7_93tdc&I{rHQ*bfyD~NAww8Rt(x76@~d|t6%c4#j`sp+JRTeI`lwcj>p)W{ z_x;2xjS6-Z9Ut>sm7V)A^=0D)utG74 + + + + RESTful API demo + + + + + + + +
      + +

      Device Configurator demo.

      + +

      + This page demonstrates how Mongoose could be used to implement + device settings page.

      + +

      How to show device parameters on the page

      +

      This page has embedded + <!--#call parameter_name --> blocks. For each such + block, mongoose triggers NS_SSI_CALL event, passing + parameter_name string as an event parameter. A callback + then can print some content, which will replace the + <!--#call parameter_name --> block. + Take a look at handle_ssi_call() to see how that is done. +

      + +

      How to save updated values

      +

      When Save button is clicked, this page makes Ajax call and passes + values to the backend in a POST request. Backend extracts values from + the POST request and updates the configuration. Take a look at + handle_save() to see how that is done.

      + + +

      You can change values, click Save button, refresh this page - make sure + settings values stay intact between refreshes.

      + +
      +
      + Device settings + + +
      + +
      + +
      +
       
      +
      + +
      + + diff --git a/examples/settings_panel_for_a_device/web_root/jquery-1.11.3.min.js b/examples/settings_panel_for_a_device/web_root/jquery-1.11.3.min.js new file mode 100644 index 00000000..0f60b7bd --- /dev/null +++ b/examples/settings_panel_for_a_device/web_root/jquery-1.11.3.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
      a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
      ","
      "],area:[1,"",""],param:[1,"",""],thead:[1,"","
      "],tr:[2,"","
      "],col:[2,"","
      "],td:[3,"","
      "],_default:k.htmlSerialize?[0,"",""]:[1,"X
      ","
      "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("